diff --git a/php.editor/src/org/netbeans/modules/php/editor/options/Bundle.properties b/php.editor/src/org/netbeans/modules/php/editor/options/Bundle.properties --- a/php.editor/src/org/netbeans/modules/php/editor/options/Bundle.properties +++ b/php.editor/src/org/netbeans/modules/php/editor/options/Bundle.properties @@ -112,3 +112,5 @@ CodeCompletionPanel.autoStringConcatenationCheckBox.text=Use Strin&g Auto-Concatenation after Typed Break CodeCompletionPanel.useLowercaseLabel.text=Use Lo&wercase: CodeCompletionPanel.trueFalseNullCheckBox.text="TRUE", "FALSE", "NULL" C&onstants +CodeCompletionPanel.autoCompletionCommentAsteriskLabel.text=C&omment Completion: +CodeCompletionPanel.autoCompletionCommentAsteriskCheckBox.text=&Insert " * " after Typed Break (Multi Line Comment /* */ only) diff --git a/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.form b/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.form --- a/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.form +++ b/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.form @@ -85,6 +85,14 @@ + + + + + + + + @@ -143,6 +151,10 @@ + + + + @@ -520,5 +532,19 @@ + + + + + + + + + + + + + + diff --git a/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.java b/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.java --- a/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.java +++ b/php.editor/src/org/netbeans/modules/php/editor/options/CodeCompletionPanel.java @@ -114,6 +114,7 @@ static final String PHP_AUTO_COMPLETION_SMART_QUOTES = "phpCodeCompletionSmartQuotes"; //NOI18N static final String PHP_AUTO_STRING_CONCATINATION = "phpCodeCompletionStringAutoConcatination"; //NOI18N static final String PHP_AUTO_COMPLETION_USE_LOWERCASE_TRUE_FALSE_NULL = "phpAutoCompletionUseLowercaseTrueFalseNull"; //NOI18N + static final String PHP_AUTO_COMPLETION_COMMENT_ASTERISK = "phpAutoCompletionCommentAsterisk"; // NOI18N // default values static final boolean PHP_AUTO_COMPLETION_FULL_DEFAULT = true; @@ -126,6 +127,7 @@ static final boolean PHP_AUTO_COMPLETION_SMART_QUOTES_DEFAULT = true; static final boolean PHP_AUTO_STRING_CONCATINATION_DEFAULT = true; static final boolean PHP_AUTO_COMPLETION_USE_LOWERCASE_TRUE_FALSE_NULL_DEFAULT = true; + static final boolean PHP_AUTO_COMPLETION_COMMENT_ASTERISK_DEFAULT = true; private final Preferences preferences; private final ItemListener defaultCheckBoxListener = new DefaultCheckBoxListener(); @@ -156,6 +158,7 @@ id2Saved.put(PHP_AUTO_COMPLETION_SMART_QUOTES, autoCompletionSmartQuotesCheckBox.isSelected()); id2Saved.put(PHP_AUTO_STRING_CONCATINATION, autoStringConcatenationCheckBox.isSelected()); id2Saved.put(PHP_AUTO_COMPLETION_USE_LOWERCASE_TRUE_FALSE_NULL, trueFalseNullCheckBox.isSelected()); + id2Saved.put(PHP_AUTO_COMPLETION_COMMENT_ASTERISK, autoCompletionCommentAsteriskCheckBox.isSelected()); } public static PreferencesCustomizer.Factory getCustomizerFactory() { @@ -233,6 +236,12 @@ PHP_AUTO_COMPLETION_USE_LOWERCASE_TRUE_FALSE_NULL_DEFAULT); trueFalseNullCheckBox.setSelected(codeCompletionUseLowercaseTrueFalseNull); trueFalseNullCheckBox.addItemListener(defaultCheckBoxListener); + + boolean codeCompletionCommentAsterisk = preferences.getBoolean( + PHP_AUTO_COMPLETION_COMMENT_ASTERISK, + PHP_AUTO_COMPLETION_COMMENT_ASTERISK_DEFAULT); + autoCompletionCommentAsteriskCheckBox.setSelected(codeCompletionCommentAsterisk); + autoCompletionCommentAsteriskCheckBox.addItemListener(defaultCheckBoxListener); } private void initCodeCompletionForMethods() { @@ -303,6 +312,7 @@ preferences.putBoolean(PHP_AUTO_COMPLETION_SMART_QUOTES, autoCompletionSmartQuotesCheckBox.isSelected()); preferences.putBoolean(PHP_AUTO_STRING_CONCATINATION, autoStringConcatenationCheckBox.isSelected()); preferences.putBoolean(PHP_AUTO_COMPLETION_USE_LOWERCASE_TRUE_FALSE_NULL, trueFalseNullCheckBox.isSelected()); + preferences.putBoolean(PHP_AUTO_COMPLETION_COMMENT_ASTERISK, autoCompletionCommentAsteriskCheckBox.isSelected()); VariablesScope variablesScope = null; if (allVariablesRadioButton.isSelected()) { @@ -368,6 +378,8 @@ autoStringConcatenationCheckBox = new JCheckBox(); useLowercaseLabel = new JLabel(); trueFalseNullCheckBox = new JCheckBox(); + autoCompletionCommentAsteriskLabel = new JLabel(); + autoCompletionCommentAsteriskCheckBox = new JCheckBox(); enableAutocompletionLabel.setLabelFor(autoCompletionFullRadioButton); Mnemonics.setLocalizedText(enableAutocompletionLabel, NbBundle.getMessage(CodeCompletionPanel.class, "CodeCompletionPanel.enableAutocompletionLabel.text")); // NOI18N @@ -437,6 +449,10 @@ Mnemonics.setLocalizedText(trueFalseNullCheckBox, NbBundle.getMessage(CodeCompletionPanel.class, "CodeCompletionPanel.trueFalseNullCheckBox.text")); // NOI18N + Mnemonics.setLocalizedText(autoCompletionCommentAsteriskLabel, NbBundle.getMessage(CodeCompletionPanel.class, "CodeCompletionPanel.autoCompletionCommentAsteriskLabel.text")); // NOI18N + + Mnemonics.setLocalizedText(autoCompletionCommentAsteriskCheckBox, NbBundle.getMessage(CodeCompletionPanel.class, "CodeCompletionPanel.autoCompletionCommentAsteriskCheckBox.text")); // NOI18N + GroupLayout layout = new GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING) @@ -482,7 +498,13 @@ .addComponent(useLowercaseLabel)) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addComponent(trueFalseNullCheckBox))) + .addComponent(trueFalseNullCheckBox)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(autoCompletionCommentAsteriskLabel)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(autoCompletionCommentAsteriskCheckBox))) .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup(layout.createParallelGroup(Alignment.LEADING) @@ -537,6 +559,10 @@ .addComponent(useLowercaseLabel) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(trueFalseNullCheckBox) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(autoCompletionCommentAsteriskLabel) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(autoCompletionCommentAsteriskCheckBox) .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); @@ -583,6 +609,8 @@ // Variables declaration - do not modify//GEN-BEGIN:variables private JRadioButton allVariablesRadioButton; private ButtonGroup autoCompletionButtonGroup; + private JCheckBox autoCompletionCommentAsteriskCheckBox; + private JLabel autoCompletionCommentAsteriskLabel; private JRadioButton autoCompletionCustomizeRadioButton; private JRadioButton autoCompletionFullRadioButton; private JCheckBox autoCompletionNamespacesCheckBox; diff --git a/php.editor/src/org/netbeans/modules/php/editor/options/OptionsUtils.java b/php.editor/src/org/netbeans/modules/php/editor/options/OptionsUtils.java --- a/php.editor/src/org/netbeans/modules/php/editor/options/OptionsUtils.java +++ b/php.editor/src/org/netbeans/modules/php/editor/options/OptionsUtils.java @@ -99,6 +99,12 @@ CodeCompletionPanel.PHP_AUTO_COMPLETION_USE_LOWERCASE_TRUE_FALSE_NULL_DEFAULT); } + if (settingName == null || CodeCompletionPanel.PHP_AUTO_COMPLETION_COMMENT_ASTERISK.equals(settingName)) { + autoCompletionCommentAsterisk = preferences.getBoolean( + CodeCompletionPanel.PHP_AUTO_COMPLETION_COMMENT_ASTERISK, + CodeCompletionPanel.PHP_AUTO_COMPLETION_COMMENT_ASTERISK_DEFAULT); + } + if (settingName == null || CodeCompletionPanel.PHP_CODE_COMPLETION_STATIC_METHODS.equals(settingName)) { codeCompletionStaticMethods = preferences.getBoolean( CodeCompletionPanel.PHP_CODE_COMPLETION_STATIC_METHODS, @@ -134,6 +140,7 @@ private static Boolean autoCompletionSmartQuotes = null; private static Boolean autoStringConcatination = null; private static Boolean autoCompletionUseLowercaseTrueFalseNull = null; + private static Boolean autoCompletionCommentAsterisk = null; private static Boolean codeCompletionStaticMethods = null; private static Boolean codeCompletionNonStaticMethods = null; @@ -245,6 +252,17 @@ } /** + * Multi line comment only. + * + * @return {@code true} if insert " * ", otherwise {@code false} + */ + public static boolean autoCompletionCommentAsterisk() { + lazyInit(); + assert autoCompletionCommentAsterisk != null; + return autoCompletionCommentAsterisk; + } + + /** * All variables or only from current file. */ public static CodeCompletionPanel.VariablesScope codeCompletionVariablesScope() { diff --git a/php.editor/src/org/netbeans/modules/php/editor/typinghooks/PhpTypedBreakInterceptor.java b/php.editor/src/org/netbeans/modules/php/editor/typinghooks/PhpTypedBreakInterceptor.java --- a/php.editor/src/org/netbeans/modules/php/editor/typinghooks/PhpTypedBreakInterceptor.java +++ b/php.editor/src/org/netbeans/modules/php/editor/typinghooks/PhpTypedBreakInterceptor.java @@ -76,9 +76,15 @@ * does not also have code on the same line). */ static final boolean CONTINUE_COMMENTS = Boolean.getBoolean("php.cont.comment"); // NOI18N + // for unit tests + private static Boolean INSERT_ASTERISK_TO_PHP_COMMENT = null; private PhpDocBodyGenerator phpDocBodyGenerator = PhpDocBodyGenerator.NONE; + static void setInsertAsteriskToPHPComment(Boolean insert) { + PhpTypedBreakInterceptor.INSERT_ASTERISK_TO_PHP_COMMENT = insert; + } + @Override public void insert(MutableContext context) throws BadLocationException { final BaseDocument doc = (BaseDocument) context.getDocument(); @@ -621,6 +627,7 @@ PHPTokenId commentEnd, MutableContext context) throws BadLocationException { PHPTokenId id = ts.token().id(); + boolean insertAsterisk = insertAsterisk(commentStart); if (id == commentBody || id == commentStart) { int insertOffset; if (id == commentStart) { @@ -642,14 +649,18 @@ StringBuilder sb = new StringBuilder("\n"); if (offset > afterLastNonWhite) { sb.append(org.netbeans.modules.editor.indent.api.IndentUtils.createIndentString(doc, indent)); - sb.append(" * "); // NOI18N + if (insertAsterisk) { + sb.append(" * "); // NOI18N + } newCaretOffset = sb.length(); } else { // I'm inserting a newline in the middle of a sentence, such as the scenario in #118656 // I should insert the end AFTER the text on the line String restOfLine = doc.getText(insertOffset, LineDocumentUtils.getLineEnd(doc, afterLastNonWhite) - insertOffset); sb.append(org.netbeans.modules.editor.indent.api.IndentUtils.createIndentString(doc, indent)); - sb.append(" * "); // NOI18N + if (insertAsterisk) { + sb.append(" * "); // NOI18N + } newCaretOffset = sb.length(); sb.append(restOfLine); doc.remove(insertOffset, restOfLine.length()); @@ -658,7 +669,11 @@ // add the closing tag sb.append("\n"); sb.append(org.netbeans.modules.editor.indent.api.IndentUtils.createIndentString(doc, indent)); - sb.append(" */"); // NOI18N + if (insertAsterisk) { + sb.append(" */"); // NOI18N + } else { + sb.append("*/"); // NOI18N + } } context.setText(sb.toString(), 0, newCaretOffset); return new Object[]{insertOffset + newCaretOffset, addClosingTag}; @@ -681,7 +696,9 @@ if (beforeFirstNonWhite >= insertOffset) { // only whitespace in front of */ sb.append(org.netbeans.modules.editor.indent.api.IndentUtils.createIndentString(doc, indent)); - sb.append(" * "); + if (insertAsterisk) { + sb.append(" * "); // NOI18N + } newCaretOffset = sb.length(); newCaretOffset2 = rowStart + newCaretOffset; sb.append(org.netbeans.modules.editor.indent.api.IndentUtils.createIndentString(doc, indent)); @@ -697,6 +714,18 @@ return new Object[]{-1, false}; } + private static boolean insertAsterisk(PHPTokenId commentStart) { + return commentStart == PHPTokenId.PHPDOC_COMMENT_START + || (commentStart == PHPTokenId.PHP_COMMENT_START && insertAsteriskToPHPComment()); + } + + private static boolean insertAsteriskToPHPComment() { + if (INSERT_ASTERISK_TO_PHP_COMMENT != null) { + return INSERT_ASTERISK_TO_PHP_COMMENT; + } + return OptionsUtils.autoCompletionCommentAsterisk(); + } + // XXX: stolen from JavaKit.JavaInsertBreakAction, we should extend it to support heredoc private static boolean isClosedComment(CharSequence txt, int pos) { int length = txt.length(); diff --git a/php.editor/test/unit/src/org/netbeans/modules/php/editor/typinghooks/PhpTypedBreakInterceptorTest.java b/php.editor/test/unit/src/org/netbeans/modules/php/editor/typinghooks/PhpTypedBreakInterceptorTest.java --- a/php.editor/test/unit/src/org/netbeans/modules/php/editor/typinghooks/PhpTypedBreakInterceptorTest.java +++ b/php.editor/test/unit/src/org/netbeans/modules/php/editor/typinghooks/PhpTypedBreakInterceptorTest.java @@ -72,6 +72,15 @@ super.insertBreak(wrapAsPhp(original), wrapAsPhp(expected)); } + private void insertBreakMultiLineComment(String original, String expected, boolean insertAsterisk) throws Exception { + PhpTypedBreakInterceptor.setInsertAsteriskToPHPComment(insertAsterisk); + try { + insertBreak(original, expected); + } finally { + PhpTypedBreakInterceptor.setInsertAsteriskToPHPComment(null); + } + } + public void testInsertBreakAfterClass2() throws Exception { insertBreak("class Foo {^\n \n}", "class Foo {\n ^\n \n}"); } @@ -815,5 +824,304 @@ ); } + // #230814 + public void testDoNotInsertCommentAsterisk_01() throws Exception { + insertBreakMultiLineComment( + "/*^", + "/*\n" + + "^\n" + + "*/", + false + ); + } + + public void testDoNotInsertCommentAsterisk_02() throws Exception { + insertBreakMultiLineComment( + "/*\n" + + "^\n" + + "*/", + "/*\n" + + "\n" + + "^\n" + + "*/", + false + ); + } + + public void testDoNotInsertCommentAsterisk_03() throws Exception { + insertBreakMultiLineComment( + "/*\n" + + " * ^\n" + + "*/", + "/*\n" + + " * \n" + + "^\n" + + "*/", + false + ); + } + + public void testDoNotInsertCommentAsterisk_04() throws Exception { + insertBreakMultiLineComment( + "/*\n" + + "something^\n" + + "*/", + "/*\n" + + "something\n" + + "^\n" + + "*/", + false + ); + } + + public void testDoNotInsertCommentAsterisk_05() throws Exception { + insertBreakMultiLineComment( + "class MyClass {\n" + + "\n" + + " /*^\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + "class MyClass {\n" + + "\n" + + " /*\n" + + " ^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + false + ); + } + + public void testDoNotInsertCommentAsterisk_06() throws Exception { + insertBreakMultiLineComment( + "class MyClass {\n" + + "\n" + + " /*^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + "class MyClass {\n" + + "\n" + + " /*\n" + + " ^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + false + ); + } + + public void testDoNotInsertCommentAsterisk_07() throws Exception { + insertBreakMultiLineComment( + "class MyClass {\n" + + "\n" + + " /*\n" + + " ^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + "class MyClass {\n" + + "\n" + + " /*\n" + + " \n" + + " ^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + false + ); + } + + public void testDoNotInsertCommentAsterisk_08() throws Exception { + insertBreakMultiLineComment( + "class MyClass {\n" + + "\n" + + " /*\n" + + " something^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + "class MyClass {\n" + + "\n" + + " /*\n" + + " something\n" + + " ^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + false + ); + } + + public void testDoNotInsertCommentAsterisk_09() throws Exception { + // PHPDoc + insertBreakMultiLineComment( + "class MyClass {\n" + + "\n" + + " /**^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + "class MyClass {\n" + + "\n" + + " /**\n" + + " * ^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + false + ); + } + + public void testInsertCommentAsterisk_01() throws Exception { + insertBreakMultiLineComment( + "/*^", + "/*\n" + + " * ^\n" + + " */", + true + ); + } + + public void testInsertCommentAsterisk_02() throws Exception { + insertBreakMultiLineComment( + "/*\n" + + " * ^\n" + + " */", + "/*\n" + + " * \n" + + " * ^\n" + + " */", + true + ); + } + + public void testInsertCommentAsterisk_03() throws Exception { + insertBreakMultiLineComment( + "/*\n" + + " * something^\n" + + " */", + "/*\n" + + " * something\n" + + " * ^\n" + + " */", + true + ); + } + + public void testInsertCommentAsterisk_04() throws Exception { + insertBreakMultiLineComment( + "class MyClass {\n" + + "\n" + + " /*^\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + "class MyClass {\n" + + "\n" + + " /*\n" + + " * ^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + true + ); + } + + public void testInsertCommentAsterisk_05() throws Exception { + insertBreakMultiLineComment( + "class MyClass {\n" + + "\n" + + " /*^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + "class MyClass {\n" + + "\n" + + " /*\n" + + " * ^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + true + ); + } + + public void testInsertCommentAsterisk_06() throws Exception { + insertBreakMultiLineComment( + "class MyClass {\n" + + "\n" + + " /*\n" + + " * ^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + "class MyClass {\n" + + "\n" + + " /*\n" + + " * \n" + + " * ^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + true + ); + } + + public void testInsertCommentAsterisk_07() throws Exception { + insertBreakMultiLineComment( + "class MyClass {\n" + + "\n" + + " /*\n" + + " * something^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + "class MyClass {\n" + + "\n" + + " /*\n" + + " * something\n" + + " * ^\n" + + " */\n" + + " public function test() {\n" + + " \n" + + " }\n" + + "}\n", + true + ); + } }