diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a3cf335221fa..13521bf848dd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1323,6 +1323,10 @@ jobs: if: env.test_java == 'true' && success() run: ant $OPTS -f java/java.completion test + - name: java.editor.base + if: env.test_java == 'true' && success() + run: ant $OPTS -f java/java.editor.base test + - name: java.editor if: env.test_java == 'true' && success() run: .github/retry.sh ant $OPTS -f java/java.editor test-unit diff --git a/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java b/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java index 9242e63687ef..78fdd4caa30d 100644 --- a/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java +++ b/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java @@ -44,6 +44,8 @@ import org.netbeans.api.java.lexer.JavaTokenId; import org.netbeans.api.java.source.*; import org.netbeans.api.java.source.support.ReferencesCount; +import org.netbeans.api.lexer.PartType; +import org.netbeans.api.lexer.TokenHierarchy; import org.netbeans.api.lexer.TokenSequence; import org.netbeans.modules.parsing.api.ResultIterator; import org.netbeans.modules.parsing.api.UserTask; @@ -233,8 +235,11 @@ Env getCompletionEnvironment(CompilationController controller, boolean bottomUpS ts.token().id().primaryCategory().startsWith("string") || //NOI18N ts.token().id().primaryCategory().equals("literal")) //NOI18N { //TODO: Use isKeyword(...) when available - prefix = ts.token().text().toString().substring(0, len); - offset = ts.offset(); + String prefixInToken = ts.token().text().toString().substring(0, len); + if (!ts.token().id().primaryCategory().startsWith("string") || !prefixInToken.endsWith("\\{")) { + prefix = prefixInToken; + offset = ts.offset(); + } } else if ((ts.token().id() == JavaTokenId.DOUBLE_LITERAL || ts.token().id() == JavaTokenId.FLOAT_LITERAL || ts.token().id() == JavaTokenId.FLOAT_LITERAL_INVALID @@ -308,7 +313,7 @@ private Env getEnvImpl(CompilationController controller, TreePath orig, TreePath && (parent.getKind() == Tree.Kind.METHOD || TreeUtilities.CLASS_TREE_KINDS.contains(parent.getKind()))) { controller.toPhase(withinAnonymousOrLocalClass(tu, path) ? JavaSource.Phase.RESOLVED : JavaSource.Phase.ELEMENTS_RESOLVED); int blockPos = (int) sourcePositions.getStartPosition(root, tree); - String blockText = controller.getText().substring(blockPos, upToOffset ? offset : (int) sourcePositions.getEndPosition(root, tree)); + String blockText = fixStringTemplates(path, controller.getText().substring(blockPos, upToOffset ? offset : (int) sourcePositions.getEndPosition(root, tree))); final SourcePositions[] sp = new SourcePositions[1]; final StatementTree block = (((BlockTree) tree).isStatic() ? tu.parseStaticBlock(blockText, sp) : tu.parseStatement(blockText, sp)); if (block == null) { @@ -618,7 +623,34 @@ public Tree.Kind getKind() { } return null; } - + + private static String fixStringTemplates(TreePath tp, String blockText) { + if (!blockText.contains("\\{")) { + return blockText; + } + + TokenHierarchy th = TokenHierarchy.create(blockText, JavaTokenId.language()); + TokenSequence ts = th.tokenSequence(JavaTokenId.language()); + StringBuilder augmented = new StringBuilder(); + + augmented.append(blockText); + ts.moveEnd(); + + while (ts.movePrevious()) { + if ((ts.token().id() == JavaTokenId.STRING_LITERAL || + ts.token().id() == JavaTokenId.MULTILINE_STRING_LITERAL) && + ts.token().partType() == PartType.START) { + if (ts.token().id() == JavaTokenId.STRING_LITERAL) { + augmented.append("}\""); + } else { + augmented.append("}\"\"\""); + } + } + } + + return augmented.toString(); + } + private static String whitespaceString(int length) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < length; i++) { diff --git a/java/java.completion/src/org/netbeans/modules/java/completion/JavaCompletionTask.java b/java/java.completion/src/org/netbeans/modules/java/completion/JavaCompletionTask.java index eed308f75db0..cb541a6959b1 100644 --- a/java/java.completion/src/org/netbeans/modules/java/completion/JavaCompletionTask.java +++ b/java/java.completion/src/org/netbeans/modules/java/completion/JavaCompletionTask.java @@ -500,6 +500,9 @@ protected void resolve(CompilationController controller) throws IOException { case DECONSTRUCTION_PATTERN: insideDeconstructionRecordPattern(env); break; + case TEMPLATE: + insideStringTemplate(env); + break; } } @@ -3389,6 +3392,16 @@ private boolean isSealedSupported(final Env env) { return env.getController().getSourceVersion().compareTo(SourceVersion.RELEASE_15) >= 0; } + private void insideStringTemplate(Env env) throws IOException { + final int offset = env.getOffset(); + final TreePath path = env.getPath(); + TokenSequence ts = findLastNonWhitespaceToken(env, path.getLeaf(), offset); + if (ts.token().id() == JavaTokenId.STRING_LITERAL || ts.token().id() == JavaTokenId.MULTILINE_STRING_LITERAL) { + localResult(env); + addValueKeywords(env); + } + } + private void localResult(Env env) throws IOException { addLocalMembersAndVars(env); addClassTypes(env, null); @@ -6170,6 +6183,10 @@ public boolean accept(Element e, TypeMirror t) { break; case BLOCK: return null; + case TEMPLATE: + //TODO:can there be good smart types? + //(how about incomplete String templates?) + return null; } lastTree = tree; path = path.getParentPath(); @@ -6597,4 +6614,5 @@ private static ElementKind simplifyElementKind(ElementKind kind) { } return kind; } + } diff --git a/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/templateStart.pass b/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/templateStart.pass new file mode 100644 index 000000000000..315dcfe2442a --- /dev/null +++ b/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/1.8/templateStart.pass @@ -0,0 +1,129 @@ +Integer i +String str +protected native Object clone() +public boolean equals(Object arg0) +protected void finalize() +public String get1(String str, Integer i) +public String get2(String str, Integer i) +public String get3(String str, Integer i) +public final native Class getClass() +public native int hashCode() +public final native void notify() +public final native void notifyAll() +public String toString() +public final void wait() +public final native void wait(long arg0) +public final void wait(long arg0, int arg1) +boolean +byte +char +double +false +float +int +long +new +null +short +super +this +true +AbstractMethodError +Appendable +ArithmeticException +ArrayIndexOutOfBoundsException +ArrayStoreException +AssertionError +AutoCloseable +Boolean +BootstrapMethodError +Byte +CharSequence +Character +Class +ClassCastException +ClassCircularityError +ClassFormatError +ClassLoader +ClassNotFoundException +ClassValue +CloneNotSupportedException +Cloneable +Comparable +Compiler +Deprecated +Double +Enum +EnumConstantNotPresentException +Error +Exception +ExceptionInInitializerError +Float +FunctionalInterface +IllegalAccessError +IllegalAccessException +IllegalArgumentException +IllegalMonitorStateException +IllegalStateException +IllegalThreadStateException +IncompatibleClassChangeError +IndexOutOfBoundsException +InheritableThreadLocal +InstantiationError +InstantiationException +Integer +InternalError +InterruptedException +Iterable +LinkageError +Long +Math +NegativeArraySizeException +NoClassDefFoundError +NoSuchFieldError +NoSuchFieldException +NoSuchMethodError +NoSuchMethodException +NullPointerException +Number +NumberFormatException +Object +OutOfMemoryError +Override +Package +Process +ProcessBuilder +Readable +ReflectiveOperationException +Runnable +Runtime +RuntimeException +RuntimePermission +SafeVarargs +SecurityException +SecurityManager +Short +StackOverflowError +StackTraceElement +StrictMath +String +StringBuffer +StringBuilder +StringIndexOutOfBoundsException +StringTemplates +SuppressWarnings +System +Thread +ThreadDeath +ThreadGroup +ThreadLocal +Throwable +TypeNotPresentException +UnknownError +UnsatisfiedLinkError +UnsupportedClassVersionError +UnsupportedOperationException +VerifyError +VirtualMachineError +Void +java diff --git a/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/10/templateStart.pass b/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/10/templateStart.pass new file mode 100644 index 000000000000..6c333323ae1f --- /dev/null +++ b/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/10/templateStart.pass @@ -0,0 +1,139 @@ +Integer i +String str +protected native Object clone() +public boolean equals(Object arg0) +protected void finalize() +public String get1(String str, Integer i) +public String get2(String str, Integer i) +public String get3(String str, Integer i) +public final native Class getClass() +public native int hashCode() +public final native void notify() +public final native void notifyAll() +public String toString() +public final void wait() +public final native void wait(long arg0) +public final void wait(long arg0, int arg1) +boolean +byte +char +double +false +float +int +long +new +null +short +super +this +true +AbstractMethodError +Appendable +ArithmeticException +ArrayIndexOutOfBoundsException +ArrayStoreException +AssertionError +AutoCloseable +Boolean +BootstrapMethodError +Byte +CharSequence +Character +Class +ClassCastException +ClassCircularityError +ClassFormatError +ClassLoader +ClassNotFoundException +ClassValue +CloneNotSupportedException +Cloneable +Comparable +Compiler +Deprecated +Double +Enum +EnumConstantNotPresentException +Error +Exception +ExceptionInInitializerError +Float +FunctionalInterface +IllegalAccessError +IllegalAccessException +IllegalArgumentException +IllegalCallerException +IllegalMonitorStateException +IllegalStateException +IllegalThreadStateException +IncompatibleClassChangeError +IndexOutOfBoundsException +InheritableThreadLocal +InstantiationError +InstantiationException +Integer +InternalError +InterruptedException +Iterable +LayerInstantiationException +LinkageError +Long +Math +Module +ModuleLayer +NegativeArraySizeException +NoClassDefFoundError +NoSuchFieldError +NoSuchFieldException +NoSuchMethodError +NoSuchMethodException +NullPointerException +Number +NumberFormatException +Object +OutOfMemoryError +Override +Package +Process +ProcessBuilder +ProcessHandle +Readable +ReflectiveOperationException +Runnable +Runtime +RuntimeException +RuntimePermission +SafeVarargs +SecurityException +SecurityManager +Short +StackOverflowError +StackTraceElement +StackWalker +StrictMath +String +StringBuffer +StringBuilder +StringIndexOutOfBoundsException +StringTemplates +SuppressWarnings +System +Thread +ThreadDeath +ThreadGroup +ThreadLocal +Throwable +TypeNotPresentException +UnknownError +UnsatisfiedLinkError +UnsupportedClassVersionError +UnsupportedOperationException +VerifyError +VirtualMachineError +Void +com +java +javax +org +sun diff --git a/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/14/templateStart.pass b/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/14/templateStart.pass new file mode 100644 index 000000000000..3e86c1d0d771 --- /dev/null +++ b/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/14/templateStart.pass @@ -0,0 +1,140 @@ +Integer i +String str +protected native Object clone() +public boolean equals(Object arg0) +protected void finalize() +public String get1(String str, Integer i) +public String get2(String str, Integer i) +public String get3(String str, Integer i) +public final native Class getClass() +public native int hashCode() +public final native void notify() +public final native void notifyAll() +public String toString() +public final void wait() +public final native void wait(long arg0) +public final void wait(long arg0, int arg1) +boolean +byte +char +double +false +float +int +long +new +null +short +super +this +true +AbstractMethodError +Appendable +ArithmeticException +ArrayIndexOutOfBoundsException +ArrayStoreException +AssertionError +AutoCloseable +Boolean +BootstrapMethodError +Byte +CharSequence +Character +Class +ClassCastException +ClassCircularityError +ClassFormatError +ClassLoader +ClassNotFoundException +ClassValue +CloneNotSupportedException +Cloneable +Comparable +Compiler +Deprecated +Double +Enum +EnumConstantNotPresentException +Error +Exception +ExceptionInInitializerError +Float +FunctionalInterface +IllegalAccessError +IllegalAccessException +IllegalArgumentException +IllegalCallerException +IllegalMonitorStateException +IllegalStateException +IllegalThreadStateException +IncompatibleClassChangeError +IndexOutOfBoundsException +InheritableThreadLocal +InstantiationError +InstantiationException +Integer +InternalError +InterruptedException +Iterable +LayerInstantiationException +LinkageError +Long +Math +Module +ModuleLayer +NegativeArraySizeException +NoClassDefFoundError +NoSuchFieldError +NoSuchFieldException +NoSuchMethodError +NoSuchMethodException +NullPointerException +Number +NumberFormatException +Object +OutOfMemoryError +Override +Package +Process +ProcessBuilder +ProcessHandle +Readable +Record +ReflectiveOperationException +Runnable +Runtime +RuntimeException +RuntimePermission +SafeVarargs +SecurityException +SecurityManager +Short +StackOverflowError +StackTraceElement +StackWalker +StrictMath +String +StringBuffer +StringBuilder +StringIndexOutOfBoundsException +StringTemplates +SuppressWarnings +System +Thread +ThreadDeath +ThreadGroup +ThreadLocal +Throwable +TypeNotPresentException +UnknownError +UnsatisfiedLinkError +UnsupportedClassVersionError +UnsupportedOperationException +VerifyError +VirtualMachineError +Void +com +java +javax +org +sun diff --git a/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/19/templateStart.pass b/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/19/templateStart.pass new file mode 100644 index 000000000000..22ece7f58a15 --- /dev/null +++ b/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/19/templateStart.pass @@ -0,0 +1,142 @@ +Integer i +String str +protected native Object clone() +public boolean equals(Object arg0) +protected void finalize() +public String get1(String str, Integer i) +public String get2(String str, Integer i) +public String get3(String str, Integer i) +public final native Class getClass() +public native int hashCode() +public final native void notify() +public final native void notifyAll() +public String toString() +public final void wait() +public final void wait(long arg0) +public final void wait(long arg0, int arg1) +boolean +byte +char +double +false +float +int +long +new +null +short +super +this +true +AbstractMethodError +Appendable +ArithmeticException +ArrayIndexOutOfBoundsException +ArrayStoreException +AssertionError +AutoCloseable +Boolean +BootstrapMethodError +Byte +CharSequence +Character +Class +ClassCastException +ClassCircularityError +ClassFormatError +ClassLoader +ClassNotFoundException +ClassValue +CloneNotSupportedException +Cloneable +Comparable +Compiler +Deprecated +Double +Enum +EnumConstantNotPresentException +Error +Exception +ExceptionInInitializerError +Float +FunctionalInterface +IllegalAccessError +IllegalAccessException +IllegalArgumentException +IllegalCallerException +IllegalMonitorStateException +IllegalStateException +IllegalThreadStateException +IncompatibleClassChangeError +IndexOutOfBoundsException +InheritableThreadLocal +InstantiationError +InstantiationException +Integer +InternalError +InterruptedException +Iterable +LayerInstantiationException +LinkageError +Long +MatchException +Math +Module +ModuleLayer +NegativeArraySizeException +NoClassDefFoundError +NoSuchFieldError +NoSuchFieldException +NoSuchMethodError +NoSuchMethodException +NullPointerException +Number +NumberFormatException +Object +OutOfMemoryError +Override +Package +Process +ProcessBuilder +ProcessHandle +Readable +Record +ReflectiveOperationException +Runnable +Runtime +RuntimeException +RuntimePermission +SafeVarargs +SecurityException +SecurityManager +Short +StackOverflowError +StackTraceElement +StackWalker +StrictMath +String +StringBuffer +StringBuilder +StringIndexOutOfBoundsException +StringTemplates +SuppressWarnings +System +Thread +ThreadDeath +ThreadGroup +ThreadLocal +Throwable +TypeNotPresentException +UnknownError +UnsatisfiedLinkError +UnsupportedClassVersionError +UnsupportedOperationException +VerifyError +VirtualMachineError +Void +WrongThreadException +com +java +javax +org +sun diff --git a/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/21/stringContent.pass b/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/21/stringContent.pass new file mode 100644 index 000000000000..486ef0d9a03f --- /dev/null +++ b/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/21/stringContent.pass @@ -0,0 +1,76 @@ +public char charAt(int arg0) +public IntStream chars() +public int codePointAt(int arg0) +public int codePointBefore(int arg0) +public int codePointCount(int arg0, int arg1) +public IntStream codePoints() +public int compareTo(String arg0) +public int compareToIgnoreCase(String arg0) +public String concat(String arg0) +public boolean contains(CharSequence arg0) +public boolean contentEquals(CharSequence arg0) +public boolean contentEquals(StringBuffer arg0) +public Optional describeConstable() +public boolean endsWith(String arg0) +public boolean equals(Object arg0) +public boolean equalsIgnoreCase(String arg0) +public String formatted(Object... arg0) +public byte[] getBytes() +public byte[] getBytes(Charset arg0) +public byte[] getBytes(String arg0) +public void getBytes(int arg0, int arg1, byte[] arg2, int arg3) +public void getChars(int arg0, int arg1, char[] arg2, int arg3) +public final native Class getClass() +public int hashCode() +public String indent(int arg0) +public int indexOf(String arg0) +public int indexOf(int arg0) +public int indexOf(String arg0, int arg1) +public int indexOf(int arg0, int arg1) +public int indexOf(String arg0, int arg1, int arg2) +public int indexOf(int arg0, int arg1, int arg2) +public native String intern() +public boolean isBlank() +public boolean isEmpty() +public int lastIndexOf(String arg0) +public int lastIndexOf(int arg0) +public int lastIndexOf(String arg0, int arg1) +public int lastIndexOf(int arg0, int arg1) +public int length() +public Stream lines() +public boolean matches(String arg0) +public final native void notify() +public final native void notifyAll() +public int offsetByCodePoints(int arg0, int arg1) +public boolean regionMatches(int arg0, String arg1, int arg2, int arg3) +public boolean regionMatches(boolean arg0, int arg1, String arg2, int arg3, int arg4) +public String repeat(int arg0) +public String replace(CharSequence arg0, CharSequence arg1) +public String replace(char arg0, char arg1) +public String replaceAll(String arg0, String arg1) +public String replaceFirst(String arg0, String arg1) +public String resolveConstantDesc(Lookup arg0) +public String[] split(String arg0) +public String[] split(String arg0, int arg1) +public String[] splitWithDelimiters(String arg0, int arg1) +public boolean startsWith(String arg0) +public boolean startsWith(String arg0, int arg1) +public String strip() +public String stripIndent() +public String stripLeading() +public String stripTrailing() +public CharSequence subSequence(int arg0, int arg1) +public String substring(int arg0) +public String substring(int arg0, int arg1) +public char[] toCharArray() +public String toLowerCase() +public String toLowerCase(Locale arg0) +public String toString() +public String toUpperCase() +public String toUpperCase(Locale arg0) +public R transform(Function arg0) +public String translateEscapes() +public String trim() +public final void wait() +public final void wait(long arg0) +public final void wait(long arg0, int arg1) diff --git a/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/21/templateStart.pass b/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/21/templateStart.pass new file mode 100644 index 000000000000..7a74446ad9c5 --- /dev/null +++ b/java/java.completion/test/unit/data/goldenfiles/org/netbeans/modules/java/completion/JavaCompletionTaskTest/21/templateStart.pass @@ -0,0 +1,140 @@ +int a +boolean b +protected native Object clone() +public boolean equals(Object arg0) +protected void finalize() +public final native Class getClass() +public native int hashCode() +public final native void notify() +public final native void notifyAll() +public void op(int a, boolean b) +public String toString() +public final void wait() +public final void wait(long arg0) +public final void wait(long arg0, int arg1) +boolean +byte +char +double +false +float +int +long +new +short +super +this +true +AbstractMethodError +Appendable +ArithmeticException +ArrayIndexOutOfBoundsException +ArrayStoreException +AssertionError +AutoCloseable +Boolean +BootstrapMethodError +Byte +CharSequence +Character +Class +ClassCastException +ClassCircularityError +ClassFormatError +ClassLoader +ClassNotFoundException +ClassValue +CloneNotSupportedException +Cloneable +Comparable +Deprecated +Double +Enum +EnumConstantNotPresentException +Error +Exception +ExceptionInInitializerError +Float +FunctionalInterface +IllegalAccessError +IllegalAccessException +IllegalArgumentException +IllegalCallerException +IllegalMonitorStateException +IllegalStateException +IllegalThreadStateException +IncompatibleClassChangeError +IndexOutOfBoundsException +InheritableThreadLocal +InstantiationError +InstantiationException +Integer +InternalError +InterruptedException +Iterable +LayerInstantiationException +LinkageError +Long +MatchException +Math +Module +ModuleLayer +NegativeArraySizeException +NoClassDefFoundError +NoSuchFieldError +NoSuchFieldException +NoSuchMethodError +NoSuchMethodException +NullPointerException +Number +NumberFormatException +Object +OutOfMemoryError +Override +Package +Process +ProcessBuilder +ProcessHandle +Readable +Record +ReflectiveOperationException +Runnable +Runtime +RuntimeException +RuntimePermission +SafeVarargs +ScopedValue +SecurityException +SecurityManager +Short +StackOverflowError +StackTraceElement +StackWalker +StrictMath +String +StringBuffer +StringBuilder +StringIndexOutOfBoundsException +StringTemplate +SuppressWarnings +System +Test +Thread +ThreadDeath +ThreadGroup +ThreadLocal +Throwable +TypeNotPresentException +UnknownError +UnsatisfiedLinkError +UnsupportedClassVersionError +UnsupportedOperationException +VerifyError +VirtualMachineError +Void +WrongThreadException +com +java +javax +org +sun diff --git a/java/java.completion/test/unit/data/org/netbeans/modules/java/completion/data/StringTemplates.java b/java/java.completion/test/unit/data/org/netbeans/modules/java/completion/data/StringTemplates.java new file mode 100644 index 000000000000..d59ec8394e5a --- /dev/null +++ b/java/java.completion/test/unit/data/org/netbeans/modules/java/completion/data/StringTemplates.java @@ -0,0 +1,33 @@ +/* + * 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 test; + +public class StringTemplates { + public String get1(String str, Integer i) { + return STR. + } + public String get2(String str, Integer i) { + return STR."\{}"; + } + public String get3(String str, Integer i) { + return STR.""" + \{}"""; + } +} diff --git a/java/java.completion/test/unit/src/org/netbeans/modules/java/completion/StringTemplatesTest.java b/java/java.completion/test/unit/src/org/netbeans/modules/java/completion/StringTemplatesTest.java new file mode 100644 index 000000000000..b6c74e9fdb5b --- /dev/null +++ b/java/java.completion/test/unit/src/org/netbeans/modules/java/completion/StringTemplatesTest.java @@ -0,0 +1,97 @@ +/* + * 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.completion; + +import java.util.ArrayList; +import java.util.List; +import javax.lang.model.SourceVersion; +import javax.swing.event.ChangeListener; +import org.netbeans.modules.java.source.parsing.JavacParser; +import org.netbeans.spi.java.queries.CompilerOptionsQueryImplementation; +import org.openide.filesystems.FileObject; +import org.openide.util.lookup.ServiceProvider; + +public class StringTemplatesTest extends CompletionTestBase { + + public StringTemplatesTest(String testName) { + super(testName); + } + + public void testStringTemplates1() throws Exception { + TestCompilerOptionsQueryImplementation.EXTRA_OPTIONS.add("--enable-preview"); + performTest("StringTemplates", 922, "\"\\{str.", "stringContent.pass", getLatestSource()); + } + + public void testStringTemplates2() throws Exception { + TestCompilerOptionsQueryImplementation.EXTRA_OPTIONS.add("--enable-preview"); + performTest("StringTemplates", 999, "str.", "stringContent.pass", getLatestSource()); + } + + public void testStringTemplates3() throws Exception { + TestCompilerOptionsQueryImplementation.EXTRA_OPTIONS.add("--enable-preview"); + performTest("StringTemplates", 922, "\"\\{\"\\{str.", "stringContent.pass", getLatestSource()); + } + + public void testStringTemplates4() throws Exception { + TestCompilerOptionsQueryImplementation.EXTRA_OPTIONS.add("--enable-preview"); + performTest("StringTemplates", 922, "\"\\{", "templateStart.pass", getLatestSource()); + } + + public void testStringTemplatesBlock1() throws Exception { + TestCompilerOptionsQueryImplementation.EXTRA_OPTIONS.add("--enable-preview"); + performTest("StringTemplates", 922, "\"\"\"\n\\{str.", "stringContent.pass", getLatestSource()); + } + + public void testStringTemplatesBlock2() throws Exception { + TestCompilerOptionsQueryImplementation.EXTRA_OPTIONS.add("--enable-preview"); + performTest("StringTemplates", 1101, "str.", "stringContent.pass", getLatestSource()); + } + + private String getLatestSource() { + return SourceVersion.latest().name().substring(SourceVersion.latest().name().indexOf("_") + 1); + } + + static { + JavacParser.DISABLE_SOURCE_LEVEL_DOWNGRADE = true; + } + + @ServiceProvider(service = CompilerOptionsQueryImplementation.class, position = 100) + public static class TestCompilerOptionsQueryImplementation implements CompilerOptionsQueryImplementation { + + private static final List EXTRA_OPTIONS = new ArrayList<>(); + + @Override + public CompilerOptionsQueryImplementation.Result getOptions(FileObject file) { + return new CompilerOptionsQueryImplementation.Result() { + @Override + public List getArguments() { + return EXTRA_OPTIONS; + } + + @Override + public void addChangeListener(ChangeListener listener) { + } + + @Override + public void removeChangeListener(ChangeListener listener) { + } + }; + } + } +} diff --git a/java/java.editor/nbproject/project.xml b/java/java.editor/nbproject/project.xml index e3b37e48959e..42b86a983bc1 100644 --- a/java/java.editor/nbproject/project.xml +++ b/java/java.editor/nbproject/project.xml @@ -500,6 +500,11 @@ + + org.netbeans.modules.editor.bracesmatching + + + org.netbeans.modules.editor.lib2 diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/JavaBracesMatcher.java b/java/java.editor/src/org/netbeans/modules/editor/java/JavaBracesMatcher.java index b2e51537aafe..d83320d4e9de 100644 --- a/java/java.editor/src/org/netbeans/modules/editor/java/JavaBracesMatcher.java +++ b/java/java.editor/src/org/netbeans/modules/editor/java/JavaBracesMatcher.java @@ -18,14 +18,11 @@ */ package org.netbeans.modules.editor.java; -import com.sun.source.tree.ClassTree; import com.sun.source.tree.IfTree; import com.sun.source.tree.StatementTree; import com.sun.source.tree.Tree; import com.sun.source.util.TreePath; import java.io.IOException; -import java.util.Collections; -import java.util.LinkedList; import java.util.List; import javax.swing.text.AbstractDocument; import javax.swing.text.BadLocationException; @@ -35,13 +32,11 @@ import org.netbeans.api.java.source.JavaSource; import org.netbeans.api.java.source.Task; import org.netbeans.api.lexer.Language; +import org.netbeans.api.lexer.PartType; +import org.netbeans.api.lexer.Token; import org.netbeans.api.lexer.TokenHierarchy; import org.netbeans.api.lexer.TokenId; import org.netbeans.api.lexer.TokenSequence; -import org.netbeans.modules.parsing.api.ParserManager; -import org.netbeans.modules.parsing.api.ResultIterator; -import org.netbeans.modules.parsing.api.Source; -import org.netbeans.modules.parsing.api.UserTask; import org.netbeans.spi.editor.bracesmatching.BraceContext; import org.netbeans.spi.editor.bracesmatching.BracesMatcher; import org.netbeans.spi.editor.bracesmatching.BracesMatcherFactory; @@ -152,7 +147,8 @@ public int[] findMatches() throws InterruptedException, BadLocationException { seq.move(originOffset); if (seq.moveNext()) { - if (seq.token().id() == JavaTokenId.STRING_LITERAL) { + Token token = seq.token(); + if (token.id() == JavaTokenId.STRING_LITERAL) { for(TokenSequenceIterator tsi = new TokenSequenceIterator(list, backward); tsi.hasMore(); ) { TokenSequence sq = tsi.getSequence(); if (sq.token().id() == JavaTokenId.STRING_LITERAL) { @@ -192,6 +188,53 @@ public int[] findMatches() throws InterruptedException, BadLocationException { } } } + if ((token.partType() == PartType.START || token.partType() == PartType.MIDDLE) && (seq.offset() + token.length()) == originOffset + (backward ? 0 : 1)) { + while (seq.moveNext()) { + Token t = seq.token(); + + if (t.id() == JavaTokenId.STRING_LITERAL || + t.id() == JavaTokenId.MULTILINE_STRING_LITERAL) { + + switch (t.partType()) { + case START: counter++; break; + case END: + if (counter > 0) { + counter--; + break; + } + case MIDDLE: + if (counter == 0) { + return new int[] {seq.offset(), seq.offset() + 1}; + } + break; + } + } + } + } + if ((token.partType() == PartType.END || token.partType() == PartType.MIDDLE) && seq.offset() == originOffset - (backward ? 0 : 1)) { + while (seq.movePrevious()) { + Token t = seq.token(); + + if (t.id() == JavaTokenId.STRING_LITERAL || + t.id() == JavaTokenId.MULTILINE_STRING_LITERAL) { + + switch (t.partType()) { + case END: counter++; break; + case START: + if (counter > 0) { + counter--; + break; + } + case MIDDLE: + if (counter == 0) { + int endPos = seq.offset() + seq.token().length(); + return new int[] {endPos - 1, endPos}; + } + break; + } + } + } + } return null; } } diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/JavaKit.java b/java/java.editor/src/org/netbeans/modules/editor/java/JavaKit.java index 12b5034b29db..f836db9930cb 100644 --- a/java/java.editor/src/org/netbeans/modules/editor/java/JavaKit.java +++ b/java/java.editor/src/org/netbeans/modules/editor/java/JavaKit.java @@ -561,11 +561,13 @@ public void insert(MutableContext context) throws BadLocationException { switch(insertedChar) { case '(': case '[': + case '{': if (TypingCompletion.isCompletionSettingEnabled()) TypingCompletion.completeOpeningBracket(context); break; case ')': case ']': + case '}': if (TypingCompletion.isCompletionSettingEnabled()) caretPosition = TypingCompletion.skipClosingBracket(context); break; diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java b/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java index af6d8cc3994b..59340af52c2e 100644 --- a/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java +++ b/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java @@ -31,6 +31,7 @@ import org.netbeans.api.java.lexer.JavaTokenId; import org.netbeans.api.java.queries.SourceLevelQuery; import org.netbeans.api.lexer.PartType; +import org.netbeans.api.lexer.Token; import org.netbeans.api.lexer.TokenHierarchy; import org.netbeans.api.lexer.TokenSequence; import org.netbeans.editor.BaseDocument; @@ -122,7 +123,27 @@ static void removeBrackets(DeletedTextInterceptor.Context context) throws BadLoc */ static int skipClosingBracket(TypedTextInterceptor.MutableContext context) throws BadLocationException { TokenSequence javaTS = javaTokenSequence(context, false); - if (javaTS == null || (javaTS.token().id() != JavaTokenId.RPAREN && javaTS.token().id() != JavaTokenId.RBRACKET) || isStringOrComment(javaTS.token().id())) { + + if (javaTS == null) { + return -1; + } + + Token currentToken = javaTS.token(); + JavaTokenId currentId = currentToken.id(); + + if (isString(currentId)) { + switch (currentToken.partType()) { + case MIDDLE: case END: + if (currentToken.text().charAt(0) == '}') { + context.setText("", 0); // NOI18N + return context.getOffset() + 1; + } + break; + } + return -1; + } + + if (currentId != JavaTokenId.RPAREN && currentId != JavaTokenId.RBRACKET) { return -1; } @@ -141,11 +162,26 @@ static int skipClosingBracket(TypedTextInterceptor.MutableContext context) throw * @throws BadLocationException */ static void completeOpeningBracket(TypedTextInterceptor.MutableContext context) throws BadLocationException { - if (isStringOrComment(javaTokenSequence(context, false).token().id())) { + JavaTokenId currentToken = javaTokenSequence(context, false).token().id(); + + if (isComment(currentToken)) { return; } - + + if (isString(currentToken)) { + if (context.getOffset() >= 1 && context.getText().charAt(0) == '{') { + char chr = context.getDocument().getText(context.getOffset() - 1, 1).charAt(0); + + if (chr == '\\') { + context.setText("{}", 1); // NOI18N + } + } + + return ; + } + char chr = context.getDocument().getText(context.getOffset(), 1).charAt(0); + if (chr == ')' || chr == ',' || chr == '\"' || chr == '\'' || chr == ' ' || chr == ']' || chr == '}' || chr == '\n' || chr == '\t' || chr == ';') { char insChr = context.getText().charAt(0); context.setText("" + insChr + matching(insChr), 1); // NOI18N @@ -869,4 +905,16 @@ private static FileObject getFileObject(BaseDocument doc) { private static boolean isStringOrComment(JavaTokenId javaTokenId) { return STRING_AND_COMMENT_TOKENS.contains(javaTokenId); } + + private static Set STRING_TOKENS = EnumSet.of(JavaTokenId.STRING_LITERAL, JavaTokenId.CHAR_LITERAL, JavaTokenId.MULTILINE_STRING_LITERAL); + + private static boolean isString(JavaTokenId javaTokenId) { + return STRING_TOKENS.contains(javaTokenId); + } + + private static Set COMMENT_TOKENS = EnumSet.of(JavaTokenId.LINE_COMMENT, JavaTokenId.JAVADOC_COMMENT, JavaTokenId.BLOCK_COMMENT); + + private static boolean isComment(JavaTokenId javaTokenId) { + return COMMENT_TOKENS.contains(javaTokenId); + } } diff --git a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/JavaBracesMatcherTest.java b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/JavaBracesMatcherTest.java new file mode 100644 index 000000000000..bd4a621a2e26 --- /dev/null +++ b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/JavaBracesMatcherTest.java @@ -0,0 +1,90 @@ +/* + * 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.editor.java; + +import javax.swing.text.BadLocationException; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNotNull; +import org.netbeans.api.java.lexer.JavaTokenId; +import org.netbeans.editor.BaseDocument; +import org.netbeans.junit.NbTestCase; +import org.netbeans.modules.editor.bracesmatching.api.BracesMatchingTestUtils; +import org.netbeans.spi.editor.bracesmatching.BracesMatcher; +import org.netbeans.spi.editor.bracesmatching.BracesMatcherFactory; +import org.netbeans.spi.editor.bracesmatching.MatcherContext; + +/** + * + */ +public class JavaBracesMatcherTest extends NbTestCase { + + public JavaBracesMatcherTest(String name) { + super(name); + } + + public void testStringTemplateBrackets() throws Exception { + assertMatches2("\"\\^{test^}\""); + } + + //from CslTestBase: + protected void assertMatches2(String original) throws Exception { + int caretPos = original.indexOf('^'); + original = original.substring(0, caretPos) + original.substring(caretPos+1); + + int matchingCaretPos = original.indexOf('^'); + + original = original.substring(0, matchingCaretPos) + original.substring(matchingCaretPos+1); + + BaseDocument doc = getDocument(original); + + computeAndAssertMatches(doc, caretPos, false, matchingCaretPos); + computeAndAssertMatches(doc, caretPos + 1, true, matchingCaretPos); + computeAndAssertMatches(doc, matchingCaretPos, false, caretPos); + computeAndAssertMatches(doc, matchingCaretPos + 1, true, caretPos); + } + + private void computeAndAssertMatches(BaseDocument doc, int pos, boolean backwards, int matchingPos) throws BadLocationException, InterruptedException { + BracesMatcherFactory factory = new JavaBracesMatcher(); + MatcherContext context = BracesMatchingTestUtils.createMatcherContext(doc, pos, backwards, 1); + BracesMatcher matcher = factory.createMatcher(context); + int[] origin = matcher.findOrigin(); + int[] matches = matcher.findMatches(); + + assertNotNull("Did not find origin for " + " position " + pos, origin); + assertNotNull("Did not find matches for " + " position " + pos, matches); + + int expectedPos = backwards ? pos - 1 : pos; + + assertEquals("Incorrect origin", expectedPos, origin[0]); + assertEquals("Incorrect origin", expectedPos + 1, origin[1]); + assertEquals("Incorrect matches", matchingPos, matches[0]); + assertEquals("Incorrect matches", matchingPos + 1, matches[1]); + } + + private BaseDocument getDocument(String content) throws Exception { + BaseDocument doc = new BaseDocument(true, "text/x-java") { + }; + + doc.putProperty(org.netbeans.api.lexer.Language.class, JavaTokenId.language()); + + doc.insertString(0, content, null); + + return doc; + } +} diff --git a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java index 9002f7e7b9d5..1b6ca1162506 100644 --- a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java +++ b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java @@ -94,7 +94,7 @@ public void testTypeSemicolonInArgs() { // #146139 "m();|" ); } - + public void testSemicolonOnTheEnd() { // #146139 Context ctx = new Context(new JavaKit(), "m()| " @@ -114,7 +114,7 @@ public void testTypeRightParenWithinBraces() { // #146139 "{(()); }" ); } - + public void testTypeLeftParen() { Context ctx = new Context(new JavaKit(), "m|"); ctx.typeChar('('); @@ -921,7 +921,7 @@ public void testKeepBalance148878() throws Exception { "Map[]| m = new HashMap[1];" ); } - + public void testQuotes148878() throws Exception { Context ctx = new Context(new JavaKit(), "if (c == '\\\\|')" @@ -931,7 +931,7 @@ public void testQuotes148878() throws Exception { "if (c == '\\\\'|)" ); } - + public void testPositionInString() throws Exception { Context ctx = new Context(new JavaKit(), "class Test {\n" @@ -948,7 +948,7 @@ public void testPositionInString() throws Exception { + " }\n" + "}\n"); } - + public void testPositionInEmptyString() throws Exception { Context ctx = new Context(new JavaKit(), "class Test {\n" @@ -965,7 +965,7 @@ public void testPositionInEmptyString() throws Exception { + " }\n" + "}\n"); } - + public void testPositionInTextBlock() throws Exception { try { SourceVersion.valueOf("RELEASE_13"); @@ -988,7 +988,7 @@ public void testPositionInTextBlock() throws Exception { + " }\n" + "}\n"); } - + public void testPositionInEmptyTextBlock() throws Exception { try { SourceVersion.valueOf("RELEASE_13"); @@ -1035,7 +1035,7 @@ public void testCommentBlockCompletion() throws Exception { prefs.remove("enableBlockCommentFormatting"); } } - + public void testCommentBlockCompletionNotNeeded() throws Exception { Preferences prefs = MimeLookup.getLookup(JavaKit.JAVA_MIME_TYPE).lookup(Preferences.class); try { @@ -1060,7 +1060,7 @@ public void testCommentBlockCompletionNotNeeded() throws Exception { prefs.remove("enableBlockCommentFormatting"); } } - + public void testCommentBlockCompletionTwoComments () { Preferences prefs = MimeLookup.getLookup(JavaKit.JAVA_MIME_TYPE).lookup(Preferences.class); @@ -1107,7 +1107,7 @@ public void testCommentBlockCompletionTwoComments2 () { prefs.remove("enableBlockCommentFormatting"); } } - + public void testCommentBlockCompletionNoClose () { Preferences prefs = MimeLookup.getLookup(JavaKit.JAVA_MIME_TYPE).lookup(Preferences.class); try { @@ -1124,7 +1124,7 @@ public void testCommentBlockCompletionNoClose () { prefs.remove("enableBlockCommentFormatting"); } } - + public void testJavaDocCompletion() throws Exception { Context ctx = new Context(new JavaKit(), "class Test {\n" @@ -1142,7 +1142,7 @@ public void testJavaDocCompletion() throws Exception { + " }\n" + "}\n"); } - + public void testJavaDocCompletionNotNeeded() throws Exception { Context ctx = new Context(new JavaKit(), "class Test {\n" @@ -1161,7 +1161,7 @@ public void testJavaDocCompletionNotNeeded() throws Exception { + " }\n" + "}\n"); } - + public void insertBreakJavadocComplete() throws Exception { Context ctx = new Context(new JavaKit(), "class Test {\n" @@ -1185,7 +1185,7 @@ public void insertBreakJavadocComplete() throws Exception { + "}\n" ); } - + public void testRemoveBracketBackSpace() throws Exception { Context ctx = new Context(new JavaKit(), "()(|)"); @@ -1199,63 +1199,63 @@ public void testRemoveBracketDelete() throws Exception { ctx.typeChar('\f'); ctx.assertDocumentTextEquals("()|"); } - + public void testRemoveQuotesBackSpace1() throws Exception { Context ctx = new Context(new JavaKit(), "\"|\""); ctx.typeChar('\b'); ctx.assertDocumentTextEquals("|"); } - + public void testRemoveQuotesBackSpace2() throws Exception { Context ctx = new Context(new JavaKit(), "\"\"\"|\""); ctx.typeChar('\b'); ctx.assertDocumentTextEquals("\"\"|"); } - + public void testRemoveQuotesBackSpace3() throws Exception { Context ctx = new Context(new JavaKit(), "\"\"\"|\";"); ctx.typeChar('\b'); ctx.assertDocumentTextEquals("\"\"|;"); } - + public void testRemoveQuotesDelete1() throws Exception { Context ctx = new Context(new JavaKit(), "|\"\""); ctx.typeChar('\f'); ctx.assertDocumentTextEquals("|"); } - + public void testRemoveQuotesDelete2() throws Exception { Context ctx = new Context(new JavaKit(), "\"\"|\"\""); ctx.typeChar('\f'); ctx.assertDocumentTextEquals("\"\"|"); } - + public void testRemoveQuotesDelete3() throws Exception { Context ctx = new Context(new JavaKit(), "\"\"|\"\";"); ctx.typeChar('\f'); ctx.assertDocumentTextEquals("\"\"|;"); } - + public void testRemoveQuotes2BackSpace() throws Exception { Context ctx = new Context(new JavaKit(), "\'\'\'|\'"); ctx.typeChar('\b'); ctx.assertDocumentTextEquals("\'\'|"); } - + public void testRemoveQuotes2Delete() throws Exception { Context ctx = new Context(new JavaKit(), "\'\'|\'\'"); ctx.typeChar('\f'); ctx.assertDocumentTextEquals("\'\'|"); } - + public void testJumpCharacters() throws Exception { Context ctx = new Context(new JavaKit(), "m(\"p|\");"); ctx.typeChar('"'); @@ -1263,13 +1263,13 @@ public void testJumpCharacters() throws Exception { ctx.typeChar(')'); ctx.assertDocumentTextEquals("m(\"p\")|;"); } - + public void testJumpQuote() throws Exception { Context ctx = new Context(new JavaKit(), "\"|\""); ctx.typeChar('"'); ctx.assertDocumentTextEquals("\"\"|"); } - + public void testInsertSquareBracket() throws Exception { Context ctx = new Context(new JavaKit(), "|"); ctx.typeChar('['); @@ -1281,13 +1281,13 @@ public void testBackspaceSquareBracket() throws Exception { ctx.typeChar('\b'); ctx.assertDocumentTextEquals("|"); } - + public void testDeleteSquareBracket() throws Exception { Context ctx = new Context(new JavaKit(), "|[]"); ctx.typeChar('\f'); ctx.assertDocumentTextEquals("|"); } - + public void testInsertBracketInString() throws Exception { Context ctx = new Context(new JavaKit(), "\"|\""); ctx.typeChar('('); @@ -1296,19 +1296,19 @@ public void testInsertBracketInString() throws Exception { ctx.typeChar('('); ctx.assertDocumentTextEquals("\" (|\""); } - + public void testInsertBracketInChar() throws Exception { Context ctx = new Context(new JavaKit(), "\'|\'"); ctx.typeChar('('); ctx.assertDocumentTextEquals("\'(|\'"); } - + public void testInsertBracketInComment() throws Exception { Context ctx = new Context(new JavaKit(), "//|"); ctx.typeChar('('); ctx.assertDocumentTextEquals("//(|"); } - + public void testSkipBracketInComment() throws Exception { Context ctx = new Context(new JavaKit(), "//(|)"); ctx.typeChar(')'); @@ -1362,7 +1362,7 @@ public void testTextBlock4() throws Exception { ctx.typeChar('\"'); ctx.assertDocumentTextEquals("\"\"\"\n\"\"\"|"); } - + public void testTextBlock5() throws Exception { try { SourceVersion.valueOf("RELEASE_13"); @@ -1373,8 +1373,8 @@ public void testTextBlock5() throws Exception { Context ctx = new Context(new JavaKit(), "t(|\"\")"); ctx.typeChar('\"'); ctx.assertDocumentTextEquals("t(\"\"\"\n |\"\"\")"); - } - + } + public void testTextBlock6() throws Exception { try { SourceVersion.valueOf("RELEASE_13"); @@ -1385,8 +1385,8 @@ public void testTextBlock6() throws Exception { Context ctx = new Context(new JavaKit(), "t(\"\"\"\n|\"\n\"\"\")"); ctx.typeChar('\f'); ctx.assertDocumentTextEquals("t(\"\"\"\n\n\"\"\")"); - } - + } + public void testCorrectHandlingOfStringEscapes184059() throws Exception { assertTrue(isInsideString("foo\n\"bar|\"")); assertTrue(isInsideString("foo\n\"bar\\\"|\"")); @@ -1395,6 +1395,24 @@ public void testCorrectHandlingOfStringEscapes184059() throws Exception { assertTrue(isInsideString("foo\n\"|bar\\\\\"")); } + public void testCompleteTemplate1() throws Exception { + Context ctx = new Context(new JavaKit(), "\"\\|\""); + ctx.typeChar('{'); + ctx.assertDocumentTextEquals("\"\\{|}\""); + } + + public void testCompleteTemplate2() throws Exception { + Context ctx = new Context(new JavaKit(), "\"\\|"); + ctx.typeChar('{'); + ctx.assertDocumentTextEquals("\"\\{|}"); + } + + public void testSkipTemplate1() throws Exception { + Context ctx = new Context(new JavaKit(), "\"\\{|}\""); + ctx.typeChar('}'); + ctx.assertDocumentTextEquals("\"\\{}|\""); + } + private boolean isInsideString(String code) throws BadLocationException { int pos = code.indexOf('|'); diff --git a/java/java.lexer/apichanges.xml b/java/java.lexer/apichanges.xml index d337df1d9b73..05a0dd8dfa79 100644 --- a/java/java.lexer/apichanges.xml +++ b/java/java.lexer/apichanges.xml @@ -83,6 +83,18 @@ is the proper place. + + + Added TEMPLATE_START to JavaStringTokenId and JavaCharacterTokenId + + + + + + Added JavaStringTokenId.TEMPLATE_START and JavaCharacterTokenId.TEMPLATE_START. + + + Added MULTILINE_STRING_LITERAL JavaTokenKind diff --git a/java/java.lexer/manifest.mf b/java/java.lexer/manifest.mf index ccb3f5849671..c137debdd2ba 100644 --- a/java/java.lexer/manifest.mf +++ b/java/java.lexer/manifest.mf @@ -1,5 +1,5 @@ OpenIDE-Module: org.netbeans.modules.java.lexer/1 OpenIDE-Module-Localizing-Bundle: org/netbeans/lib/java/lexer/Bundle.properties -OpenIDE-Module-Specification-Version: 1.57 +OpenIDE-Module-Specification-Version: 1.58 OpenIDE-Module-Layer: org/netbeans/lib/java/lexer/layer.xml diff --git a/java/java.lexer/src/org/netbeans/api/java/lexer/JavaStringTokenId.java b/java/java.lexer/src/org/netbeans/api/java/lexer/JavaStringTokenId.java index e2739dc1a6d0..1c66b68e7e6b 100644 --- a/java/java.lexer/src/org/netbeans/api/java/lexer/JavaStringTokenId.java +++ b/java/java.lexer/src/org/netbeans/api/java/lexer/JavaStringTokenId.java @@ -51,7 +51,11 @@ public enum JavaStringTokenId implements TokenId { OCTAL_ESCAPE_INVALID("string-escape-invalid"), //NOI18N UNICODE_ESCAPE("string-escape"), //NOI18N UNICODE_ESCAPE_INVALID("string-escape-invalid"), //NOI18N - ESCAPE_SEQUENCE_INVALID("string-escape-invalid"); //NOI18N + ESCAPE_SEQUENCE_INVALID("string-escape-invalid"), //NOI18N + /** + * @since 1.58 + */ + TEMPLATE_START("string"); //NOI18N private final String primaryCategory; diff --git a/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaCharacterTokenId.java b/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaCharacterTokenId.java index d4a2437af85a..98c894a40740 100644 --- a/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaCharacterTokenId.java +++ b/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaCharacterTokenId.java @@ -51,7 +51,11 @@ public enum JavaCharacterTokenId implements TokenId { OCTAL_ESCAPE_INVALID("character-escape-invalid"), //NOI18N UNICODE_ESCAPE("character-escape"), //NOI18N UNICODE_ESCAPE_INVALID("character-escape-invalid"), //NOI18N - ESCAPE_SEQUENCE_INVALID("character-escape-invalid"); //NOI18N + ESCAPE_SEQUENCE_INVALID("character-escape-invalid"), //NOI18N + /** + * @since 1.58 + */ + TEMPLATE_START("character"); //NOI18N private final String primaryCategory; diff --git a/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaLexer.java b/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaLexer.java index ec27b8e435ad..49c32619b467 100644 --- a/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaLexer.java +++ b/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaLexer.java @@ -19,7 +19,10 @@ package org.netbeans.lib.java.lexer; +import java.util.ArrayList; import java.util.EnumSet; +import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.function.Supplier; import org.netbeans.api.java.lexer.JavaTokenId; @@ -60,7 +63,15 @@ public class JavaLexer implements Lexer { public JavaLexer(LexerRestartInfo info) { this.input = info.input(); this.tokenFactory = info.tokenFactory(); - this.state = (Integer) info.state(); + if (info.state() instanceof ComplexState) { + ComplexState complex = (ComplexState) info.state(); + this.pendingStringLiteral = complex.pendingStringLiteral; + this.pendingBraces = complex.pendingBraces; + this.literalHistory = complex.literalHistory; + this.state = complex.state; + } else { + this.state = (Integer) info.state(); + } if (state == null) { Supplier fileName = (Supplier)info.getAttributeValue("fileName"); //NOI18N if (fileName != null && "module-info.java".equals(fileName.get())) { //NOI18N @@ -80,8 +91,60 @@ public JavaLexer(LexerRestartInfo info) { } this.version = (ver != null) ? ver.intValue() : 10; // TODO: Java 1.8 used by default } - + + private static final class ComplexState { + public final JavaTokenId pendingStringLiteral; + public final int pendingBraces; + public final LiteralHistoryNode literalHistory; + public final Integer state; + + public ComplexState(JavaTokenId pendingStringLiteral, int pendingBraces, + LiteralHistoryNode literalHistory, Integer state) { + this.pendingStringLiteral = pendingStringLiteral; + this.pendingBraces = pendingBraces; + this.literalHistory = literalHistory; + this.state = state; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 97 * hash + Objects.hashCode(this.pendingStringLiteral); + hash = 97 * hash + this.pendingBraces; + hash = 97 * hash + Objects.hashCode(this.literalHistory); + hash = 97 * hash + Objects.hashCode(this.state); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final ComplexState other = (ComplexState) obj; + if (this.pendingBraces != other.pendingBraces) { + return false; + } + if (this.pendingStringLiteral != other.pendingStringLiteral) { + return false; + } + if (!Objects.equals(this.literalHistory, other.literalHistory)) { + return false; + } + return Objects.equals(this.state, other.state); + } + + } public Object state() { + if (pendingStringLiteral != null) { + return new ComplexState(pendingStringLiteral, 0, literalHistory, state); + } return state; } @@ -159,11 +222,30 @@ public void backup(int howMany) { public void consumeNewline() { if (nextChar() != '\n') backup(1); } - + + private JavaTokenId pendingStringLiteral; + private int pendingBraces; + + private class LiteralHistoryNode { + public final JavaTokenId pendingStringLiteral; + public final int pendingBraces; + public final LiteralHistoryNode next; + + public LiteralHistoryNode(JavaTokenId pendingStringLiteral, int pendingBraces, LiteralHistoryNode next) { + this.pendingStringLiteral = pendingStringLiteral; + this.pendingBraces = pendingBraces; + this.next = next; + } + + } + + LiteralHistoryNode literalHistory = null; + public Token nextToken() { + boolean stringLiteralContinuation = false; + JavaTokenId lookupId = null; while(true) { - int c = nextChar(); - JavaTokenId lookupId = null; + int c = stringLiteralContinuation ? '"' : nextChar(); switch (c) { case '#': //Support for exotic identifiers has been removed 6999438 @@ -174,7 +256,7 @@ public Token nextToken() { switch (nextChar()) { case '"': // NOI18N String text = input.readText().toString(); - if (text.length() == 2) { + if (text.length() == 2 && !stringLiteralContinuation) { int mark = input.readLength(); if (nextChar() != '"') { input.backup(1); //TODO: EOF??? @@ -191,16 +273,24 @@ public Token nextToken() { lookupId = JavaTokenId.MULTILINE_STRING_LITERAL; } if (lookupId == JavaTokenId.MULTILINE_STRING_LITERAL) { - if (text.endsWith("\"\"\"") && !text.endsWith("\\\"\"\"") && text.length() > 6) { - return token(lookupId); + if (text.endsWith("\"\"\"") && !text.endsWith("\\\"\"\"") && (text.length() > 6 || stringLiteralContinuation)) { + return token(lookupId, stringLiteralContinuation ? PartType.END : PartType.COMPLETE); } else { break; } } - return token(lookupId); + return token(lookupId, stringLiteralContinuation ? PartType.END : PartType.COMPLETE); case '\\': - nextChar(); + switch (nextChar()) { + case '{': + if (pendingStringLiteral != null) { + literalHistory = new LiteralHistoryNode(pendingStringLiteral, pendingBraces, literalHistory); + } + pendingStringLiteral = lookupId; + pendingBraces = 0; + return token(lookupId, stringLiteralContinuation ? PartType.MIDDLE : PartType.START); + } break; case '\r': consumeNewline(); case '\n': @@ -441,11 +531,27 @@ else if ('0' <= c && c <= '9') { // float literal case ']': return token(JavaTokenId.RBRACKET); case '{': + if (pendingStringLiteral != null ) { + pendingBraces++; + } if (state != null && state == 2) { state = 3; // inside module decl } return token(JavaTokenId.LBRACE); case '}': + if (pendingStringLiteral != null && pendingBraces-- == 0) { + lookupId = pendingStringLiteral; + if (literalHistory == null) { + pendingStringLiteral = null; + pendingBraces = 0; + } else { + pendingStringLiteral = literalHistory.pendingStringLiteral; + pendingBraces = literalHistory.pendingBraces; + literalHistory = literalHistory.next; + } + stringLiteralContinuation = true; + break; + } state = null; return token(JavaTokenId.RBRACE); case '@': @@ -1324,10 +1430,15 @@ private Token finishFloatExponent() { } private Token token(JavaTokenId id) { + return token(id, PartType.COMPLETE); + } + + private Token token(JavaTokenId id, PartType partType) { String fixedText = id.fixedText(); - return (fixedText != null && fixedText.length() == input.readLength()) + return (fixedText != null && fixedText.length() == input.readLength() && partType == PartType.COMPLETE) ? tokenFactory.getFlyweightToken(id, fixedText) - : tokenFactory.createToken(id); + : partType == PartType.COMPLETE ? tokenFactory.createToken(id) + : tokenFactory.createToken(id, input.readLength(), partType); } private static final Set AFTER_VAR_TOKENS = EnumSet.of( diff --git a/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaStringLexer.java b/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaStringLexer.java index 20be6d327e88..904ce8d4151d 100644 --- a/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaStringLexer.java +++ b/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaStringLexer.java @@ -85,6 +85,8 @@ public Token nextToken() { return token((T) (isStringTokenId() ? JavaStringTokenId.DOUBLE_QUOTE : JavaCharacterTokenId.DOUBLE_QUOTE)); case '\\': //NOI18N return token((T) (isStringTokenId() ? JavaStringTokenId.BACKSLASH : JavaCharacterTokenId.BACKSLASH)); + case '{': //NOI18N + return token((T) (isStringTokenId() ? JavaStringTokenId.TEMPLATE_START : JavaCharacterTokenId.TEMPLATE_START)); case 'u': //NOI18N while ('u' == (ch = input.read())) {}; //NOI18N diff --git a/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerBatchTest.java b/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerBatchTest.java index ecf2181c9489..6402fc5c348f 100644 --- a/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerBatchTest.java +++ b/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerBatchTest.java @@ -63,7 +63,7 @@ public void testComments() { LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.BLOCK_COMMENT, "/* a"); assertEquals(PartType.START, ts.token().partType()); } - + public void testIdentifiers() { String text = "a ab aB2 2a x\nyZ\r\nz"; TokenHierarchy hi = TokenHierarchy.create(text, JavaTokenId.language()); @@ -83,7 +83,7 @@ public void testIdentifiers() { LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, "\r\n"); LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.IDENTIFIER, "z"); } - + public void testCharLiterals() { String text = "'' 'a''' '\\'' '\\\\' '\\\\\\'' '\\n' 'a"; TokenHierarchy hi = TokenHierarchy.create(text, JavaTokenId.language()); @@ -104,7 +104,7 @@ public void testCharLiterals() { LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.CHAR_LITERAL, "'a"); assertEquals(PartType.START, ts.token().partType()); } - + public void testStringLiterals() { String text = "\"\" \"a\" \"\" \"\\\"\" \"\\\\\" \"\\\\\\\"\" \"\\n\" \"a"; TokenHierarchy hi = TokenHierarchy.create(text, JavaTokenId.language()); @@ -126,9 +126,9 @@ public void testStringLiterals() { LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.STRING_LITERAL, "\"a"); assertEquals(PartType.START, ts.token().partType()); } - + public void testNumberLiterals() { - String text = "0 00 09 1 12 0L 1l 12L 0x1 0xf 0XdE 0Xbcy" + + String text = "0 00 09 1 12 0L 1l 12L 0x1 0xf 0XdE 0Xbcy" + " 09.5 1.5f 2.5d 6d 7e3 6.1E-7f 0xa.5dp+12d .3 0x4l 0x5L"; TokenHierarchy hi = TokenHierarchy.create(text, JavaTokenId.language()); TokenSequence ts = hi.tokenSequence(); @@ -177,7 +177,7 @@ public void testNumberLiterals() { LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " "); LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.LONG_LITERAL, "0x5L"); } - + public void testOperators() { String text = "^ ^= % %= * *= / /= = =="; TokenHierarchy hi = TokenHierarchy.create(text, JavaTokenId.language()); @@ -352,22 +352,22 @@ public void testNonKeywords() { LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " "); LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.IDENTIFIER, "throwsx"); } - + public void testEmbedding() { String text = "ddx \"d\\t\\br\" /** @see X */"; - + TokenHierarchy hi = TokenHierarchy.create(text, JavaTokenId.language()); TokenSequence ts = hi.tokenSequence(); - + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.IDENTIFIER, "ddx"); assertEquals(0, ts.offset()); LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " "); assertEquals(3, ts.offset()); LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.STRING_LITERAL, "\"d\\t\\br\""); assertEquals(4, ts.offset()); - + TokenSequence es = ts.embedded(); - + LexerTestUtilities.assertNextTokenEquals(es, JavaStringTokenId.TEXT, "d"); assertEquals(5, es.offset()); LexerTestUtilities.assertNextTokenEquals(es, JavaStringTokenId.TAB, "\\t"); @@ -376,16 +376,16 @@ public void testEmbedding() { assertEquals(8, es.offset()); LexerTestUtilities.assertNextTokenEquals(es, JavaStringTokenId.TEXT, "r"); assertEquals(10, es.offset()); - + assertFalse(es.moveNext()); - + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " "); assertEquals(12, ts.offset()); LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.JAVADOC_COMMENT, "/** @see X */"); assertEquals(13, ts.offset()); - + TokenSequence ds = ts.embedded(); - + LexerTestUtilities.assertNextTokenEquals(ds, JavadocTokenId.OTHER_TEXT, " "); assertEquals(16, ds.offset()); LexerTestUtilities.assertNextTokenEquals(ds, JavadocTokenId.TAG, "@see"); @@ -396,9 +396,9 @@ public void testEmbedding() { assertEquals(22, ds.offset()); LexerTestUtilities.assertNextTokenEquals(ds, JavadocTokenId.OTHER_TEXT, " "); assertEquals(23, ds.offset()); - + assertFalse(ds.moveNext()); - + assertFalse(ts.moveNext()); } @@ -493,7 +493,7 @@ public void testUnderscoresInLiterals() { LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.INT_LITERAL, "01_2"); LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.INT_LITERAL, "0x1_2"); } - + public void testUnicode() { String text = "//\\u000Aint\\u0020\\u002E\\uuuuuu002E\\u000A"; InputAttributes attr = new InputAttributes(); @@ -508,7 +508,7 @@ public void testUnicode() { LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.DOT, "\\uuuuuu002E"); LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, "\\u000A"); } - + public void testBrokenUnicode() { String text = "\\u000X\\u00"; InputAttributes attr = new InputAttributes(); @@ -597,7 +597,7 @@ public void testVarWeird() { LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.RPAREN, ")"); LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.SEMICOLON, ";"); } - + public void testVarKeywordWithStringVersion() { String text = "var /*comment*/ /**comment*/ var = 0;"; InputAttributes attr = new InputAttributes(); @@ -766,4 +766,50 @@ public void testTrailing5() { assertFalse(ts.moveNext()); } + public void testTemplates1() { + String text = "\"\\{1 + \"\\{a}\".length()}\";"; + InputAttributes attr = new InputAttributes(); + TokenHierarchy hi = TokenHierarchy.create(text, false, JavaTokenId.language(), EnumSet.noneOf(JavaTokenId.class), attr); + TokenSequence ts = hi.tokenSequence(); + + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.STRING_LITERAL, "\"\\{"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.INT_LITERAL, "1"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " "); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.PLUS, "+"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " "); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.STRING_LITERAL, "\"\\{"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.IDENTIFIER, "a"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.STRING_LITERAL, "}\""); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.DOT, "."); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.IDENTIFIER, "length"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.LPAREN, "("); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.RPAREN, ")"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.STRING_LITERAL, "}\""); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.SEMICOLON, ";"); + assertFalse(ts.moveNext()); + } + + public void testTemplates2() { + String text = "\"\"\"\n\\{1 + \"\\{a}\".length()}\"\"\";"; + InputAttributes attr = new InputAttributes(); + TokenHierarchy hi = TokenHierarchy.create(text, false, JavaTokenId.language(), EnumSet.noneOf(JavaTokenId.class), attr); + TokenSequence ts = hi.tokenSequence(); + + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.MULTILINE_STRING_LITERAL, "\"\"\"\n\\{"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.INT_LITERAL, "1"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " "); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.PLUS, "+"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " "); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.STRING_LITERAL, "\"\\{"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.IDENTIFIER, "a"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.STRING_LITERAL, "}\""); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.DOT, "."); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.IDENTIFIER, "length"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.LPAREN, "("); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.RPAREN, ")"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.MULTILINE_STRING_LITERAL, "}\"\"\""); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.SEMICOLON, ";"); + assertFalse(ts.moveNext()); + } + } diff --git a/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerStateTest.java b/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerStateTest.java new file mode 100644 index 000000000000..2a10bdab30e4 --- /dev/null +++ b/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerStateTest.java @@ -0,0 +1,85 @@ +/* + * 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.lib.java.lexer; + +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.PlainDocument; +import junit.framework.TestCase; +import org.netbeans.api.java.lexer.JavaTokenId; +import org.netbeans.api.lexer.Language; +import org.netbeans.api.lexer.TokenHierarchy; +import org.netbeans.api.lexer.TokenSequence; +import org.netbeans.lib.lexer.test.LexerTestUtilities; + +/** + * Test several simple lexer impls. + * + * @author mmetelka + */ +public class JavaLexerStateTest extends TestCase { + + public JavaLexerStateTest(String testName) { + super(testName); + } + + @Override + protected void setUp() throws java.lang.Exception { + // Set-up testing environment + LexerTestUtilities.setTesting(true); + } + + public void testTemplates1() throws BadLocationException { + Document doc = new PlainDocument(); + + doc.putProperty(Language.class, JavaTokenId.language()); + doc.insertString(0, "\"\";", null); + + String text = "\\{1 + \"\\{a}\".length()}"; + TokenHierarchy hi = TokenHierarchy.get(doc); + + for (int i = 0; i < text.length(); i++) { + TokenSequence ts = hi.tokenSequence(); + + while (ts.moveNext()); + doc.insertString(1 + i, "" + text.charAt(i), null); + } + + TokenSequence ts = hi.tokenSequence(); + + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.STRING_LITERAL, "\"\\{"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.INT_LITERAL, "1"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " "); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.PLUS, "+"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " "); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.STRING_LITERAL, "\"\\{"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.IDENTIFIER, "a"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.STRING_LITERAL, "}\""); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.DOT, "."); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.IDENTIFIER, "length"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.LPAREN, "("); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.RPAREN, ")"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.STRING_LITERAL, "}\""); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.SEMICOLON, ";"); + LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, "\n"); + assertFalse(ts.moveNext()); + } + +} diff --git a/java/maven.embedder/external/apache-maven-3.9.4-bin-license.txt b/java/maven.embedder/external/apache-maven-3.9.5-bin-license.txt similarity index 99% rename from java/maven.embedder/external/apache-maven-3.9.4-bin-license.txt rename to java/maven.embedder/external/apache-maven-3.9.5-bin-license.txt index 801239a0553f..13f5c2d2cbca 100644 --- a/java/maven.embedder/external/apache-maven-3.9.4-bin-license.txt +++ b/java/maven.embedder/external/apache-maven-3.9.5-bin-license.txt @@ -1,6 +1,6 @@ Name: Apache Maven Distribution Description: Apache Maven Distribution -Version: 3.9.4 +Version: 3.9.5 License: Apache-2.0 Origin: Apache Software Foundation URL: https://maven.apache.org/ diff --git a/java/maven.embedder/external/apache-maven-3.9.4-bin-notice.txt b/java/maven.embedder/external/apache-maven-3.9.5-bin-notice.txt similarity index 100% rename from java/maven.embedder/external/apache-maven-3.9.4-bin-notice.txt rename to java/maven.embedder/external/apache-maven-3.9.5-bin-notice.txt diff --git a/java/maven.embedder/external/apache-maven-3.9.4-epl-license.txt b/java/maven.embedder/external/apache-maven-3.9.5-epl-license.txt similarity index 98% rename from java/maven.embedder/external/apache-maven-3.9.4-epl-license.txt rename to java/maven.embedder/external/apache-maven-3.9.5-epl-license.txt index 854ce6c050f4..8f40876eb378 100644 --- a/java/maven.embedder/external/apache-maven-3.9.4-epl-license.txt +++ b/java/maven.embedder/external/apache-maven-3.9.5-epl-license.txt @@ -1,9 +1,9 @@ Name: Apache Maven components under EPL v1.0 Description: These Apache Maven components are under EPL v1.0: org.eclipse.sisu.inject-0.3.5.jar org.eclipse.sisu.plexus-0.3.5.jar -Version: 3.9.4 +Version: 3.9.5 License: Maven-EPL-v10 Origin: Apache Software Foundation -Files: apache-maven-3.9.4-bin.zip!/apache-maven-3.9.4/lib/org.eclipse.sisu.inject-0.3.5.jar apache-maven-3.9.4-bin.zip!/apache-maven-3.9.4/lib/org.eclipse.sisu.plexus-0.3.5.jar +Files: apache-maven-3.9.5-bin.zip!/apache-maven-3.9.5/lib/org.eclipse.sisu.inject-0.3.5.jar apache-maven-3.9.5-bin.zip!/apache-maven-3.9.5/lib/org.eclipse.sisu.plexus-0.3.5.jar Eclipse Public License - v 1.0 diff --git a/java/maven.embedder/external/apache-maven-3.9.4-javax.annotation-api-license.txt b/java/maven.embedder/external/apache-maven-3.9.5-javax.annotation-api-license.txt similarity index 99% rename from java/maven.embedder/external/apache-maven-3.9.4-javax.annotation-api-license.txt rename to java/maven.embedder/external/apache-maven-3.9.5-javax.annotation-api-license.txt index 58edc45000c4..50007c49393e 100644 --- a/java/maven.embedder/external/apache-maven-3.9.4-javax.annotation-api-license.txt +++ b/java/maven.embedder/external/apache-maven-3.9.5-javax.annotation-api-license.txt @@ -1,9 +1,9 @@ Name: Javax Annotation API -Version: 3.9.4 +Version: 3.9.5 Description: Part of Apache Maven Distribution License: CDDL-1.1 Origin: Apache Maven -Files: apache-maven-3.9.4-bin.zip!/apache-maven-3.9.4/lib/javax.annotation-api-1.3.2.jar +Files: apache-maven-3.9.5-bin.zip!/apache-maven-3.9.5/lib/javax.annotation-api-1.3.2.jar COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.1 diff --git a/java/maven.embedder/external/apache-maven-3.9.4-slf4j-license.txt b/java/maven.embedder/external/apache-maven-3.9.5-slf4j-license.txt similarity index 94% rename from java/maven.embedder/external/apache-maven-3.9.4-slf4j-license.txt rename to java/maven.embedder/external/apache-maven-3.9.5-slf4j-license.txt index 281cd298fc60..29bfe194e53f 100644 --- a/java/maven.embedder/external/apache-maven-3.9.4-slf4j-license.txt +++ b/java/maven.embedder/external/apache-maven-3.9.5-slf4j-license.txt @@ -1,9 +1,9 @@ Name: slf4j Description: Part of Apache Maven Distribution -Version: 3.9.4 +Version: 3.9.5 License: MIT-slf4j-22 Origin: Apache Software Foundation -Files: apache-maven-3.9.4-bin.zip!/apache-maven-3.9.4/lib/slf4j-api-1.7.36.jar +Files: apache-maven-3.9.5-bin.zip!/apache-maven-3.9.5/lib/slf4j-api-1.7.36.jar Copyright (c) 2004-2022 QOS.ch Sarl (Switzerland) All rights reserved. diff --git a/java/maven.embedder/external/binaries-list b/java/maven.embedder/external/binaries-list index f88222868216..6000cd52f391 100644 --- a/java/maven.embedder/external/binaries-list +++ b/java/maven.embedder/external/binaries-list @@ -16,4 +16,4 @@ # under the License. DC15DFF8F701B227EE523EEB7A17F77C10EAFE2F org.jdom:jdom2:2.0.6.1 5D9CE6ADD7B714B8095F0E3E396C5E9F8C5DCFEF org.apache.maven.shared:maven-dependency-tree:2.2 -5501C83302757A1407C0546E68EEDBE78EF4C802 org.apache.maven:apache-maven:3.9.4:bin@zip +448660E65018FF4354574800D0EFA831C7F5F469 org.apache.maven:apache-maven:3.9.5:bin@zip diff --git a/java/maven.embedder/external/binariesembedded-list b/java/maven.embedder/external/binariesembedded-list index e5384dd6f93c..4f026dde72c5 100644 --- a/java/maven.embedder/external/binariesembedded-list +++ b/java/maven.embedder/external/binariesembedded-list @@ -20,7 +20,7 @@ 51CF043C87253C9F58B539C9F7E44C8894223850;org.apache.httpcomponents:httpcore:4.4.16 1DCF1DE382A0BF95A3D8B0849546C88BAC1292C9;com.google.guava:failureaccess:1.0.1 DC98BE5D5390230684A092589D70EA76A147925C;commons-cli:commons-cli:1.5.0 -3ACB4705652E16236558F0F4F2192CC33C3BD189;commons-codec:commons-codec:1.11 +4E3EB3D79888D76B54E28B350915B5DC3919C9DE;commons-codec:commons-codec:1.16.0 C6842C86792FF03B9F1D1FE2AAB8DC23AA6C6F0E;org.apache.commons:commons-lang3:3.12.0 6E5D51A72D142F2D40A57DFB897188B36A95B489;com.google.guava:guava:32.0.1-jre DA25056C694C54BA16E78E4FC35F17FC60F0D1B4;com.google.inject:guice:5.1.0 @@ -28,29 +28,29 @@ DA25056C694C54BA16E78E4FC35F17FC60F0D1B4;com.google.inject:guice:5.1.0 6975DA39A7040257BD51D21A231B76C915872D38;javax.inject:javax.inject:1 D877E195A05ACA4A2F1AD2FF14BFEC1393AF4B5E;org.slf4j:jcl-over-slf4j:1.7.36 934C04D3CFEF185A8008E7BF34331B79730A9D43;javax.annotation:javax.annotation-api:1.3.2 -9738999A0459221E758EBE728449C43567D7FECC;org.apache.maven:maven-artifact:3.9.4 -671110E56110D5C89EDA904F198719A2B5FA4A21;org.apache.maven:maven-builder-support:3.9.4 -938A854093350D7BF6E0319739C1A320ADB6EAFD;org.apache.maven:maven-compat:3.9.4 -C1585EE55FCA8573E81F5AFFCF8D31578218CAC8;org.apache.maven:maven-core:3.9.4 -E35834A85B46A7CF99C517076DA20B7E7029EDDD;org.apache.maven:maven-embedder:3.9.4 -5B79D873CF6D13B3FC4020EAC04E2A62EBBFA0AA;org.apache.maven:maven-model:3.9.4 -B12E45736DDFB51F648E1579877A293659E5A96E;org.apache.maven:maven-model-builder:3.9.4 -54A5E32A3ECF77B09BE683CBA3067EA76E073D06;org.apache.maven:maven-plugin-api:3.9.4 -EF368D45A2CAA54634DE221540994CA2D810C4C9;org.apache.maven:maven-repository-metadata:3.9.4 -BD5B7CD9D15C2EFCAB4D8C8215E769523E8843E4;org.apache.maven.resolver:maven-resolver-api:1.9.14 -FFEB368F5587513B29EF9771514EC36D246E65F5;org.apache.maven.resolver:maven-resolver-connector-basic:1.9.14 -2AA090ACA572F7061E5C57F714EF0445BBB4555F;org.apache.maven.resolver:maven-resolver-impl:1.9.14 -71CF74D91B4F6DE1BFF8FC1FAFB401D9AC42B1B8;org.apache.maven.resolver:maven-resolver-named-locks:1.9.14 -D5E38634C1251E000F7718437973A730346BC336;org.apache.maven:maven-resolver-provider:3.9.4 -A190C3D49791240C87799F29848505FC9FD8BE11;org.apache.maven.resolver:maven-resolver-spi:1.9.14 -1EB4ACDCE7F21526BD06654B3D7B1EDF80370CE8;org.apache.maven.resolver:maven-resolver-transport-http:1.9.14 -47965D035A34E16FAC73F77058199FE8A16719A8;org.apache.maven.resolver:maven-resolver-transport-wagon:1.9.14 -E2FAD53903C29FA4E8603FF8DA09F68D96D9F80E;org.apache.maven.resolver:maven-resolver-transport-file:1.9.14 -EA6FD2997903700191711DEE4448746ED30FE4B9;org.apache.maven.resolver:maven-resolver-util:1.9.14 -F0553A72454ED3160CCA729B75166077D8F3D499;org.apache.maven:maven-settings:3.9.4 -B3F6479C00E9182B9B731CAF69AC6F4F6F2A373F;org.apache.maven:maven-settings-builder:3.9.4 +B956B64636F8D6ED082C7722C611231323BEEF2D;org.apache.maven:maven-artifact:3.9.5 +69D4343AF7C187465ADAB8232E1DEC2350CA3E58;org.apache.maven:maven-builder-support:3.9.5 +EE7C2FEE7FDC35E99A52001719AF75C5ADFE398C;org.apache.maven:maven-compat:3.9.5 +1ADD056215DD886528BEE60204FE1D41F10568B0;org.apache.maven:maven-core:3.9.5 +BE218DCCBD69A9ABDDCEEAC31CED774D626AA515;org.apache.maven:maven-embedder:3.9.5 +B7BE7E049231443F6A15FD16F335BA0953B328F3;org.apache.maven:maven-model:3.9.5 +7017216902225FC9E1A7EB5E06D337AC5AF952CF;org.apache.maven:maven-model-builder:3.9.5 +A778605A92802105E160358A94D508D3C0152A5A;org.apache.maven:maven-plugin-api:3.9.5 +9D5D85E892BB14E81A66426AC97955AD32191FE7;org.apache.maven:maven-repository-metadata:3.9.5 +A3A0BC37BA32DED01484B7DC20AEA36FC3FF3A77;org.apache.maven.resolver:maven-resolver-api:1.9.16 +4F465C03600ACABBCEF4E2B591F52E5C11710C22;org.apache.maven.resolver:maven-resolver-connector-basic:1.9.16 +C17DF48C1F27A529067C7B11D575DCDD538D479A;org.apache.maven.resolver:maven-resolver-impl:1.9.16 +87B0E0176A169A6B2FAFD11CCBB7B59FB769B57C;org.apache.maven.resolver:maven-resolver-named-locks:1.9.16 +8589D768CCD5F6ED6D818F38EFC301F3FADCDE53;org.apache.maven:maven-resolver-provider:3.9.5 +12222DCA88A4812560AE2FA59E8BD47871FF096A;org.apache.maven.resolver:maven-resolver-spi:1.9.16 +26FD3EED40CD7D09E5A845C8C6D66F6DC8961020;org.apache.maven.resolver:maven-resolver-transport-http:1.9.16 +1353EEBB7561C9082349FC1716120B3880EB0CA6;org.apache.maven.resolver:maven-resolver-transport-wagon:1.9.16 +E42F467A34595A7CBB25C63DE8172E6206AD0BE8;org.apache.maven.resolver:maven-resolver-transport-file:1.9.16 +FB6CB68C4593DE6AF6F96FA4F5DBA3E6D30B8EC3;org.apache.maven.resolver:maven-resolver-util:1.9.16 +36C414D6CFC4F0140E6261B71C4D3141EF6A155C;org.apache.maven:maven-settings:3.9.5 +3ADBF920F32CA7FC8760E13791271EE2A712BD98;org.apache.maven:maven-settings-builder:3.9.5 F87A61ADB1E12A00DCC6CC6005A51E693AA7C4AC;org.apache.maven.shared:maven-shared-utils:3.3.4 -14D05A34AC800E8446EE58754308E7DEF6225383;org.apache.maven:maven-slf4j-provider:3.9.4 +C1A35A7FA47B91387CCAF81EB3BB317D24DA86A8;org.apache.maven:maven-slf4j-provider:3.9.5 D4265DD4F0F1D7A06D80DF5A5F475D5FF9C17140;org.eclipse.sisu:org.eclipse.sisu.inject:0.3.5 D71996BB2E536F966B3B70E647067FFF3B73D32F;org.eclipse.sisu:org.eclipse.sisu.plexus:0.3.5 425EA8E534716B4BFF1EA90F39BD76BE951D651B;org.codehaus.plexus:plexus-cipher:2.0 diff --git a/java/maven.embedder/nbproject/project.properties b/java/maven.embedder/nbproject/project.properties index 083823db940e..d8f0a1aea90a 100644 --- a/java/maven.embedder/nbproject/project.properties +++ b/java/maven.embedder/nbproject/project.properties @@ -20,7 +20,7 @@ javac.source=1.8 javac.compilerargs=-Xlint -Xlint:-serial release.external/jdom2-2.0.6.1.jar=modules/ext/maven/jdom2-2.0.6.1.jar release.external/maven-dependency-tree-2.2.jar=modules/ext/maven/maven-dependency-tree-2.2.jar -bundled.maven=apache-maven-3.9.4 +bundled.maven=apache-maven-3.9.5 extra.module.files=maven/ nbm.executable.files=maven/bin/mvn,maven/bin/mvnDebug,maven/bin/mvnyjp extra.license.files=${cluster}/maven/LICENSE.txt,${cluster}/maven/NOTICE.txt diff --git a/java/maven.embedder/nbproject/project.xml b/java/maven.embedder/nbproject/project.xml index 8ccd45c8bf27..a2020eb4a6f9 100644 --- a/java/maven.embedder/nbproject/project.xml +++ b/java/maven.embedder/nbproject/project.xml @@ -299,7 +299,7 @@ ../maven/lib/commons-cli-1.5.0.jar - ../maven/lib/commons-codec-1.11.jar + ../maven/lib/commons-codec-1.16.0.jar ../maven/lib/commons-lang3-3.12.0.jar @@ -332,73 +332,73 @@ ../maven/lib/jcl-over-slf4j-1.7.36.jar - ../maven/lib/maven-artifact-3.9.4.jar + ../maven/lib/maven-artifact-3.9.5.jar - ../maven/lib/maven-builder-support-3.9.4.jar + ../maven/lib/maven-builder-support-3.9.5.jar - ../maven/lib/maven-compat-3.9.4.jar + ../maven/lib/maven-compat-3.9.5.jar - ../maven/lib/maven-core-3.9.4.jar + ../maven/lib/maven-core-3.9.5.jar - ../maven/lib/maven-embedder-3.9.4.jar + ../maven/lib/maven-embedder-3.9.5.jar - ../maven/lib/maven-model-3.9.4.jar + ../maven/lib/maven-model-3.9.5.jar - ../maven/lib/maven-model-builder-3.9.4.jar + ../maven/lib/maven-model-builder-3.9.5.jar - ../maven/lib/maven-plugin-api-3.9.4.jar + ../maven/lib/maven-plugin-api-3.9.5.jar - ../maven/lib/maven-repository-metadata-3.9.4.jar + ../maven/lib/maven-repository-metadata-3.9.5.jar - ../maven/lib/maven-resolver-api-1.9.14.jar + ../maven/lib/maven-resolver-api-1.9.16.jar - ../maven/lib/maven-resolver-connector-basic-1.9.14.jar + ../maven/lib/maven-resolver-connector-basic-1.9.16.jar - ../maven/lib/maven-resolver-impl-1.9.14.jar + ../maven/lib/maven-resolver-impl-1.9.16.jar - ../maven/lib/maven-resolver-named-locks-1.9.14.jar + ../maven/lib/maven-resolver-named-locks-1.9.16.jar - ../maven/lib/maven-resolver-provider-3.9.4.jar + ../maven/lib/maven-resolver-provider-3.9.5.jar - ../maven/lib/maven-resolver-spi-1.9.14.jar + ../maven/lib/maven-resolver-spi-1.9.16.jar - ../maven/lib/maven-resolver-transport-file-1.9.14.jar + ../maven/lib/maven-resolver-transport-file-1.9.16.jar - ../maven/lib/maven-resolver-transport-http-1.9.14.jar + ../maven/lib/maven-resolver-transport-http-1.9.16.jar - ../maven/lib/maven-resolver-transport-wagon-1.9.14.jar + ../maven/lib/maven-resolver-transport-wagon-1.9.16.jar - ../maven/lib/maven-resolver-util-1.9.14.jar + ../maven/lib/maven-resolver-util-1.9.16.jar - ../maven/lib/maven-settings-3.9.4.jar + ../maven/lib/maven-settings-3.9.5.jar - ../maven/lib/maven-settings-builder-3.9.4.jar + ../maven/lib/maven-settings-builder-3.9.5.jar ../maven/lib/maven-shared-utils-3.3.4.jar - ../maven/lib/maven-slf4j-provider-3.9.4.jar + ../maven/lib/maven-slf4j-provider-3.9.5.jar ../maven/lib/org.eclipse.sisu.inject-0.3.5.jar diff --git a/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/ignored-overlaps b/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/ignored-overlaps index b079a4c0b6a5..eb4b13b21bfa 100644 --- a/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/ignored-overlaps +++ b/nbbuild/antsrc/org/netbeans/nbbuild/extlibs/ignored-overlaps @@ -23,9 +23,9 @@ ide/db.sql.visualeditor/external/javacc-7.0.10.jar java/performance/external/javacc-7.0.10.jar # bundled maven conflicts with other libraries -java/maven.embedder/external/apache-maven-3.9.4-bin.zip ide/slf4j.api/external/slf4j-api-1.7.36.jar -java/maven.embedder/external/apache-maven-3.9.4-bin.zip platform/o.apache.commons.lang3/external/commons-lang3-3.12.0.jar -java/maven.embedder/external/apache-maven-3.9.4-bin.zip ide/c.google.guava.failureaccess/external/failureaccess-1.0.1.jar +java/maven.embedder/external/apache-maven-3.9.5-bin.zip ide/slf4j.api/external/slf4j-api-1.7.36.jar +java/maven.embedder/external/apache-maven-3.9.5-bin.zip platform/o.apache.commons.lang3/external/commons-lang3-3.12.0.jar +java/maven.embedder/external/apache-maven-3.9.5-bin.zip ide/c.google.guava.failureaccess/external/failureaccess-1.0.1.jar # Used to parse data during build, but need to as a lib for ide cluster nbbuild/external/json-simple-1.1.1.jar ide/libs.json_simple/external/json-simple-1.1.1.jar @@ -35,9 +35,9 @@ webcommon/javascript2.jade/external/jflex-1.4.3.jar webcommon/javascript2.lexer/ # javax.annotation-api is used by multiple modules. enterprise/javaee.api/external/javax.annotation-api-1.2.jar java/maven.indexer/external/javax.annotation-api-1.2.jar -enterprise/javaee8.api/external/javax.annotation-api-1.3.2.jar java/maven.embedder/external/apache-maven-3.9.4-bin.zip +enterprise/javaee8.api/external/javax.annotation-api-1.3.2.jar java/maven.embedder/external/apache-maven-3.9.5-bin.zip enterprise/javaee8.api/external/javax.annotation-api-1.3.2.jar enterprise/websvc.restlib/external/javax.annotation-api-1.3.2.jar -enterprise/websvc.restlib/external/javax.annotation-api-1.3.2.jar java/maven.embedder/external/apache-maven-3.9.4-bin.zip +enterprise/websvc.restlib/external/javax.annotation-api-1.3.2.jar java/maven.embedder/external/apache-maven-3.9.5-bin.zip # jaxb-api-osgi is used by multiple modules. enterprise/javaee.api/external/jaxb-api-osgi-2.2.7.jar enterprise/javaee7.api/external/jaxb-api-osgi-2.2.7.jar @@ -62,7 +62,7 @@ extide/gradle/external/gradle-7.4-bin.zip ide/libs.commons_compress/external/com extide/gradle/external/gradle-7.4-bin.zip ide/o.apache.commons.lang/external/commons-lang-2.6.jar extide/gradle/external/gradle-7.4-bin.zip ide/o.eclipse.jgit/external/org.eclipse.jgit-5.7.0.202003110725-r.jar extide/gradle/external/gradle-7.4-bin.zip java/debugger.jpda.truffle/external/antlr4-runtime-4.7.2.jar -extide/gradle/external/gradle-7.4-bin.zip java/maven.embedder/external/apache-maven-3.9.4-bin.zip +extide/gradle/external/gradle-7.4-bin.zip java/maven.embedder/external/apache-maven-3.9.5-bin.zip extide/gradle/external/gradle-7.4-bin.zip platform/libs.junit4/external/hamcrest-core-1.3.jar extide/gradle/external/gradle-7.4-bin.zip platform/libs.junit4/external/junit-4.13.2.jar extide/gradle/external/gradle-7.4-bin.zip platform/libs.testng/external/jcommander-1.78.jar diff --git a/php/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.form b/php/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.form index 73450cbf7c67..71d38a15db54 100644 --- a/php/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.form +++ b/php/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.form @@ -83,7 +83,7 @@ - + @@ -100,19 +100,19 @@ - + - + - + - + @@ -153,9 +153,9 @@ - + - + diff --git a/php/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.java b/php/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.java index 2c37ebf34f5e..f52dd8ea21be 100644 --- a/php/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.java +++ b/php/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.java @@ -473,7 +473,7 @@ private void initComponents() { .addComponent(autoStringConcatenationCheckBox) .addComponent(codeCompletionFirstClassCallableCheckBox))) .addGroup(layout.createSequentialGroup() - .addContainerGap() + .addGap(12, 12, 12) .addGroup(layout.createParallelGroup(Alignment.LEADING) .addComponent(codeCompletionTypeLabel) .addComponent(smartRadioButton) @@ -486,16 +486,16 @@ private void initComponents() { .addComponent(fullyQualifiedInfoLabel) .addComponent(unqualifiedInfoLabel))))) .addGroup(layout.createSequentialGroup() - .addContainerGap() + .addGap(12, 12, 12) .addComponent(useLowercaseLabel)) .addGroup(layout.createSequentialGroup() - .addContainerGap() + .addGap(12, 12, 12) .addComponent(trueFalseNullCheckBox)) .addGroup(layout.createSequentialGroup() - .addContainerGap() + .addGap(12, 12, 12) .addComponent(autoCompletionCommentAsteriskLabel)) .addGroup(layout.createSequentialGroup() - .addContainerGap() + .addGap(12, 12, 12) .addComponent(autoCompletionCommentAsteriskCheckBox))) .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); diff --git a/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLFCustoms.java b/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLFCustoms.java index 5cf17babcb2a..9411ce9a8956 100644 --- a/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLFCustoms.java +++ b/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLFCustoms.java @@ -19,6 +19,7 @@ package org.netbeans.swing.laf.flatlaf; +import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.UIScale; import java.awt.Color; import java.awt.Font; @@ -26,8 +27,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.Callable; import javax.swing.BorderFactory; import javax.swing.InputMap; +import javax.swing.JFrame; import javax.swing.KeyStroke; import javax.swing.UIDefaults; import javax.swing.UIDefaults.LazyValue; @@ -151,6 +154,10 @@ EDITOR_TOOLBAR_BORDER, new CompoundBorder(DPISafeBorder.matte(0, 0, 1, 0, editor } } } + if (SystemInfo.isLinux) { + result.add("windowDefaultLookAndFeelDecorated"); + result.add(FlatLafPrefs.isUseWindowDecorations()); + } return result.toArray(); } diff --git a/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLafOptionsPanel.java b/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLafOptionsPanel.java index f95768a9d68a..553a910c8951 100644 --- a/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLafOptionsPanel.java +++ b/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLafOptionsPanel.java @@ -19,6 +19,7 @@ package org.netbeans.swing.laf.flatlaf; import com.formdev.flatlaf.FlatLaf; +import com.formdev.flatlaf.FlatLightLaf; import com.formdev.flatlaf.util.SystemInfo; import java.awt.Color; import java.io.BufferedWriter; @@ -52,7 +53,8 @@ public class FlatLafOptionsPanel extends javax.swing.JPanel { private static final Color DEFAULT = new Color(0, true); - private static final Color currentAccentColor = FlatLafPrefs.getAccentColor(); + private static final Color currentAccentColor = getPrefsAccentColorOrDefault(); + private static final boolean currentUseWindowDecorations = FlatLafPrefs.isUseWindowDecorations(); private static final RequestProcessor RP = new RequestProcessor(FlatLafOptionsPanel.class); @@ -108,7 +110,7 @@ private void initAccentColor() { } private void updateEnabled() { - boolean supportsWindowDecorations = FlatLaf.supportsNativeWindowDecorations(); + boolean supportsWindowDecorations = FlatLaf.supportsNativeWindowDecorations() || new FlatLightLaf().getSupportsWindowDecorations(); useWindowDecorationsCheckBox.setEnabled(supportsWindowDecorations); unifiedTitleBarCheckBox.setEnabled(supportsWindowDecorations && useWindowDecorationsCheckBox.isSelected()); menuBarEmbeddedCheckBox.setEnabled(supportsWindowDecorations && useWindowDecorationsCheckBox.isSelected()); @@ -341,7 +343,8 @@ protected boolean store() { FlatLafPrefs.setUnderlineMenuSelection(underlineMenuSelectionCheckBox.isSelected()); FlatLafPrefs.setAlwaysShowMnemonics(alwaysShowMnemonicsCheckBox.isSelected()); - if (!Objects.equals(accentColor, currentAccentColor)) { + if (!Objects.equals(accentColor, currentAccentColor) + || SystemInfo.isLinux && useWindowDecorationsCheckBox.isSelected() != currentUseWindowDecorations) { askForRestart(); } return false; @@ -368,7 +371,7 @@ private void askForRestart() { NotificationDisplayer.Priority.NORMAL, NotificationDisplayer.Category.INFO); } - private Color getPrefsAccentColorOrDefault() { + private static Color getPrefsAccentColorOrDefault() { Color accentColor = FlatLafPrefs.getAccentColor(); return accentColor != null ? accentColor : DEFAULT; } diff --git a/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLafPrefs.java b/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLafPrefs.java index 19f894bba14a..9a7220232687 100644 --- a/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLafPrefs.java +++ b/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLafPrefs.java @@ -18,6 +18,7 @@ */ package org.netbeans.swing.laf.flatlaf; +import com.formdev.flatlaf.util.SystemInfo; import java.awt.Color; import java.util.prefs.Preferences; import org.openide.util.NbPreferences; @@ -37,6 +38,8 @@ class FlatLafPrefs { private static final Preferences prefs = NbPreferences.forModule(FlatLafPrefs.class); + private static final boolean DEF_USE_WINDOW_DECORATIONS = SystemInfo.isWindows_10_orLater; + static Color getAccentColor() { return parseColor(prefs.get(ACCENT_COLOR, null)); } @@ -60,11 +63,11 @@ static void setAccentColor(Color accentColor) { } static boolean isUseWindowDecorations() { - return prefs.getBoolean(USE_WINDOW_DECORATIONS, true); + return prefs.getBoolean(USE_WINDOW_DECORATIONS, DEF_USE_WINDOW_DECORATIONS); } static void setUseWindowDecorations(boolean value) { - putBoolean(USE_WINDOW_DECORATIONS, value, true); + putBoolean(USE_WINDOW_DECORATIONS, value, DEF_USE_WINDOW_DECORATIONS); } static boolean isUnifiedTitleBar() { diff --git a/platform/o.n.swing.plaf/src/org/netbeans/swing/plaf/Startup.java b/platform/o.n.swing.plaf/src/org/netbeans/swing/plaf/Startup.java index 51194820261c..8ab286991a4f 100644 --- a/platform/o.n.swing.plaf/src/org/netbeans/swing/plaf/Startup.java +++ b/platform/o.n.swing.plaf/src/org/netbeans/swing/plaf/Startup.java @@ -334,6 +334,9 @@ private void installLFCustoms (LFCustoms customs) { defaults.putDefaults (customs.getLookAndFeelCustomizationKeysAndValues()); } + if (defaults.getBoolean("windowDefaultLookAndFeelDecorated")) { + JFrame.setDefaultLookAndFeelDecorated(true); + } } private void runPostInstall() {