This is an automated email from the ASF dual-hosted git repository.
matthiasblaesing pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push:
new 94fa014 Exclude less (@{}) and scss (#{}) string interpolation from
formatting
new a92befa Merge pull request #3314 from matthiasblaesing/css_formatting2
94fa014 is described below
commit 94fa014e810fe0f153bb951a3a0ac1bfe6f3b2cf
Author: Matthias Bläsing <[email protected]>
AuthorDate: Wed Nov 10 21:12:02 2021 +0100
Exclude less (@{}) and scss (#{}) string interpolation from formatting
---
ide/css.editor/nbproject/project.properties | 4 +-
.../modules/css/editor/indent/CssIndentTask.java | 124 ++++++++++++---------
.../test/unit/data/testfiles/case005.less | 1 +
.../unit/data/testfiles/case005.less.formatted | 5 +
.../test/unit/data/testfiles/case006.scss | 6 +
.../unit/data/testfiles/case006.scss.formatted | 8 ++
.../modules/css/editor/indent/CssIndenterTest.java | 6 +-
.../css/editor/indent/LessIndenterTest.java | 55 +++++++++
.../css/editor/indent/ScssIndenterTest.java | 58 ++++++++++
9 files changed, 213 insertions(+), 54 deletions(-)
diff --git a/ide/css.editor/nbproject/project.properties
b/ide/css.editor/nbproject/project.properties
index ca4bfda..91a7d02 100644
--- a/ide/css.editor/nbproject/project.properties
+++ b/ide/css.editor/nbproject/project.properties
@@ -15,6 +15,8 @@
# specific language governing permissions and limitations
# under the License.
+auxiliary.org-netbeans-modules-css-prep.less_2e_configured=true
+auxiliary.org-netbeans-modules-css-prep.sass_2e_configured=true
release.external/css21-spec.zip=docs/css21-spec.zip
release.external/css3-spec.zip=docs/css3-spec.zip
@@ -33,4 +35,4 @@ test.config.stableBTD.excludes=\
**/properties/parser/PropertyValueTest.class,\
**/CssBracketCompleterTest.class
-test-unit-sys-prop.netbeans.dirs=${netbeans.dest.dir}/${nb.cluster.ide.dir}
\ No newline at end of file
+test-unit-sys-prop.netbeans.dirs=${netbeans.dest.dir}/${nb.cluster.ide.dir}
diff --git
a/ide/css.editor/src/org/netbeans/modules/css/editor/indent/CssIndentTask.java
b/ide/css.editor/src/org/netbeans/modules/css/editor/indent/CssIndentTask.java
index e6bf851..dfb9977 100644
---
a/ide/css.editor/src/org/netbeans/modules/css/editor/indent/CssIndentTask.java
+++
b/ide/css.editor/src/org/netbeans/modules/css/editor/indent/CssIndentTask.java
@@ -21,6 +21,7 @@ package org.netbeans.modules.css.editor.indent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.LinkedList;
import javax.swing.text.BadLocationException;
import org.netbeans.api.lexer.Token;
import org.netbeans.api.lexer.TokenHierarchy;
@@ -94,37 +95,76 @@ public class CssIndentTask implements IndentTask,
Lookup.Provider {
.get(context.document())
.embeddedTokenSequences(reg.getStartOffset(), false);
TokenSequence<?> ts = tslist.get(tslist.size() - 1);
- int blockLevel = determineBlocklevel(ts);
+
+ LinkedList<IndentType> blockLevel = new LinkedList<>();
+
+ // Initialize blockLevel with the indentions created by the
+ // outside context
+ ts.moveStart();
+ Token lastToken = null;
+ if (ts.moveNext()) {
+ List<TokenSequence<?>> tokenSequences = TokenHierarchy
+ .get(context.document())
+ .tokenSequenceList(ts.languagePath(), 0, ts.offset());
+ OUTER:
+ for (TokenSequence tsX : tokenSequences) {
+ tsX.moveStart();
+ while (tsX.moveNext()) {
+ if (tsX.offset() >= ts.offset()) {
+ break OUTER;
+ }
+ if (tsX.token().id() == CssTokenId.LBRACE) {
+ if (isStringInterpolation(lastToken)) {
+ // The sequence "@{" and "#{" lead in a strong
interpolation
+ // in LESS (former) and SCSS (latter).
+ blockLevel.addLast(IndentType.NONE);
+ } else {
+ blockLevel.addLast(IndentType.BLOCK);
+ }
+ } else if (tsX.token().id() == CssTokenId.RBRACE) {
+ blockLevel.pollLast();
+ }
+ lastToken = tsX.token();
+ }
+ }
+ }
+
ts.moveStart();
while(ts.moveNext()) {
if(ts.token().id() == CssTokenId.LBRACE) {
- blockLevel++;
- // Ensure, that there is a newline after an block opening
- // brace "{"
- if(LexerUtils.followsToken(ts, CssTokenId.NL, false, true,
CssTokenId.WS, CssTokenId.COMMENT) == null) {
- while(ts.moveNext()) {
- if (ts.token().id() != CssTokenId.WS &&
ts.token().id() != CssTokenId.COMMENT) {
- newlinesMissing.add(ts.offset());
- ts.movePrevious();
- break;
+ if(! isStringInterpolation(lastToken)) {
+ blockLevel.add(IndentType.BLOCK);
+ // Ensure, that there is a newline after an block
opening
+ // brace "{"
+ if(LexerUtils.followsToken(ts, CssTokenId.NL, false,
true, CssTokenId.WS, CssTokenId.COMMENT) == null) {
+ while(ts.moveNext()) {
+ if (ts.token().id() != CssTokenId.WS &&
ts.token().id() != CssTokenId.COMMENT) {
+ newlinesMissing.add(ts.offset());
+ ts.movePrevious();
+ break;
+ }
}
}
+ } else {
+ blockLevel.add(IndentType.NONE);
}
} else if (ts.token().id() == CssTokenId.RBRACE) {
- blockLevel--;
- // Ensure, that there is a newline before an block closing
- // brace "}"
- if (LexerUtils.followsToken(ts, CssTokenId.NL, true, true,
CssTokenId.WS, CssTokenId.COMMENT) == null) {
- newlinesMissing.add(ts.offset());
- }
- // Ensure, that there is a newline after an block closing
- // brace "}"
- if (LexerUtils.followsToken(ts, CssTokenId.NL, false,
true, CssTokenId.WS, CssTokenId.COMMENT) == null) {
- while(ts.moveNext()) {
- if (ts.token().id() != CssTokenId.WS &&
ts.token().id() != CssTokenId.COMMENT) {
- newlinesMissing.add(ts.offset());
- ts.movePrevious();
- break;
+ IndentType it = blockLevel.removeLast();
+ if (it == IndentType.BLOCK) {
+ // Ensure, that there is a newline before an block
closing
+ // brace "}"
+ if (LexerUtils.followsToken(ts, CssTokenId.NL, true,
true, CssTokenId.WS, CssTokenId.COMMENT) == null) {
+ newlinesMissing.add(ts.offset());
+ }
+ // Ensure, that there is a newline after an block
closing
+ // brace "}"
+ if (LexerUtils.followsToken(ts, CssTokenId.NL, false,
true, CssTokenId.WS, CssTokenId.COMMENT) == null) {
+ while (ts.moveNext()) {
+ if (ts.token().id() != CssTokenId.WS &&
ts.token().id() != CssTokenId.COMMENT) {
+ newlinesMissing.add(ts.offset());
+ ts.movePrevious();
+ break;
+ }
}
}
}
@@ -133,7 +173,7 @@ public class CssIndentTask implements IndentTask,
Lookup.Provider {
// (between property definitions). This should only be done
// in regular CSS definitions (rules), but not in inline
// style definitions
- if (blockLevel > 0 && LexerUtils.followsToken(ts,
asList(CssTokenId.NL, CssTokenId.RBRACE), false, true, CssTokenId.WS,
CssTokenId.COMMENT) == null) {
+ if (!blockLevel.isEmpty() && LexerUtils.followsToken(ts,
asList(CssTokenId.NL, CssTokenId.RBRACE), false, true, CssTokenId.WS,
CssTokenId.COMMENT) == null) {
while (ts.moveNext()) {
if (ts.token().id() != CssTokenId.WS &&
ts.token().id() != CssTokenId.COMMENT) {
newlinesMissing.add(ts.offset());
@@ -143,6 +183,7 @@ public class CssIndentTask implements IndentTask,
Lookup.Provider {
}
}
}
+ lastToken = ts.token();
}
}
// Remove newline insertions if
@@ -162,6 +203,10 @@ public class CssIndentTask implements IndentTask,
Lookup.Provider {
}
}
+ private static boolean isStringInterpolation(Token lastToken) {
+ return lastToken != null && (lastToken.id() == CssTokenId.AT_SIGN ||
lastToken.id() == CssTokenId.HASH_SYMBOL);
+ }
+
private boolean isPositionInFormatRegions(int pos) {
for(Region r: context.indentRegions()) {
if(r.getStartOffset() <= pos && r.getEndOffset() > pos) {
@@ -170,31 +215,6 @@ public class CssIndentTask implements IndentTask,
Lookup.Provider {
}
return false;
}
-
- private int determineBlocklevel(TokenSequence<?> ts) {
- int blockLevel = 0;
- ts.moveStart();
- if (!ts.moveNext()) {
- return 0;
- }
- List<TokenSequence<?>> tokenSequences = TokenHierarchy
- .get(context.document())
- .tokenSequenceList(ts.languagePath(), 0, ts.offset());
- OUTER: for(TokenSequence tsX: tokenSequences) {
- tsX.moveStart();
- while(tsX.moveNext()) {
- if(tsX.offset() >= ts.offset()) {
- break OUTER;
- }
- if(tsX.token().id() == CssTokenId.LBRACE) {
- blockLevel++;
- } else if (tsX.token().id() == CssTokenId.RBRACE) {
- blockLevel--;
- }
- }
- }
- return blockLevel;
- }
@Override
public ExtraLock indentLock() {
@@ -206,4 +226,8 @@ public class CssIndentTask implements IndentTask,
Lookup.Provider {
return lookup;
}
+ private static enum IndentType {
+ NONE,
+ BLOCK
+ }
}
diff --git a/ide/css.editor/test/unit/data/testfiles/case005.less
b/ide/css.editor/test/unit/data/testfiles/case005.less
new file mode 100644
index 0000000..88439f0
--- /dev/null
+++ b/ide/css.editor/test/unit/data/testfiles/case005.less
@@ -0,0 +1 @@
+.@{my-selector} { font-weight: bold; line-height: 40px; margin: 0 auto; }
diff --git a/ide/css.editor/test/unit/data/testfiles/case005.less.formatted
b/ide/css.editor/test/unit/data/testfiles/case005.less.formatted
new file mode 100644
index 0000000..f6648e6
--- /dev/null
+++ b/ide/css.editor/test/unit/data/testfiles/case005.less.formatted
@@ -0,0 +1,5 @@
+.@{my-selector} {
+ font-weight: bold;
+ line-height: 40px;
+ margin: 0 auto;
+}
\ No newline at end of file
diff --git a/ide/css.editor/test/unit/data/testfiles/case006.scss
b/ide/css.editor/test/unit/data/testfiles/case006.scss
new file mode 100644
index 0000000..5abfb9a
--- /dev/null
+++ b/ide/css.editor/test/unit/data/testfiles/case006.scss
@@ -0,0 +1,6 @@
+@mixin corner-icon($name, $top-or-bottom, $left-or-right) {
+ .icon-#{$name} {
+ background-image: url("/icons/#{$name}.svg"); position: absolute;
+ #{$top-or-bottom}: 0; #{$left-or-right}: 0;
+ }
+}
\ No newline at end of file
diff --git a/ide/css.editor/test/unit/data/testfiles/case006.scss.formatted
b/ide/css.editor/test/unit/data/testfiles/case006.scss.formatted
new file mode 100644
index 0000000..3b21956
--- /dev/null
+++ b/ide/css.editor/test/unit/data/testfiles/case006.scss.formatted
@@ -0,0 +1,8 @@
+@mixin corner-icon($name, $top-or-bottom, $left-or-right) {
+ .icon-#{$name} {
+ background-image: url("/icons/#{$name}.svg");
+ position: absolute;
+ #{$top-or-bottom}: 0;
+ #{$left-or-right}: 0;
+ }
+}
\ No newline at end of file
diff --git
a/ide/css.editor/test/unit/src/org/netbeans/modules/css/editor/indent/CssIndenterTest.java
b/ide/css.editor/test/unit/src/org/netbeans/modules/css/editor/indent/CssIndenterTest.java
index 609d863..1e4c423 100644
---
a/ide/css.editor/test/unit/src/org/netbeans/modules/css/editor/indent/CssIndenterTest.java
+++
b/ide/css.editor/test/unit/src/org/netbeans/modules/css/editor/indent/CssIndenterTest.java
@@ -186,7 +186,7 @@ public class CssIndenterTest extends TestBase {
public void testPartitialFormatting() throws Exception {
IndentPrefs preferences = new IndentPrefs(4, 4);
String file = "testfiles/partialformatting.css";
-
+
FileObject fo = getTestFile(file);
assertNotNull(fo);
BaseDocument doc = getDocument(fo);
@@ -201,14 +201,14 @@ public class CssIndenterTest extends TestBase {
assertDescriptionMatches(file, after, false, ".formatted");
DataObject.find(fo).getLookup().lookup(Closable.class).close();
-
+
doc = getDocument(fo);
setupDocumentIndentation(doc, preferences);
format(doc, formatter, 857, 904, false);
after = doc.getText(0, doc.getLength());
assertDescriptionMatches(file, after, false, ".formatted2");
}
-
+
public void testIndentation() throws Exception {
// property indentation:
insertNewline("a{^background: red;\n }\n", "a{\n ^background:
red;\n }\n", null);
diff --git
a/ide/css.editor/test/unit/src/org/netbeans/modules/css/editor/indent/LessIndenterTest.java
b/ide/css.editor/test/unit/src/org/netbeans/modules/css/editor/indent/LessIndenterTest.java
new file mode 100644
index 0000000..0d45596
--- /dev/null
+++
b/ide/css.editor/test/unit/src/org/netbeans/modules/css/editor/indent/LessIndenterTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.css.editor.indent;
+
+import org.netbeans.modules.css.editor.test.*;
+import org.netbeans.modules.csl.api.Formatter;
+import org.netbeans.modules.csl.api.test.CslTestBase;
+import org.netbeans.modules.csl.spi.DefaultLanguageConfig;
+import org.netbeans.modules.css.editor.csl.CssLanguage;
+
+
+public class LessIndenterTest extends CslTestBase {
+
+ private static final String PROP_MIME_TYPE = "mimeType"; //NOI18N
+
+ public LessIndenterTest(String name) {
+ super(name);
+ }
+
+ @Override
+ protected DefaultLanguageConfig getPreferredLanguage() {
+ return new CssLanguage();
+ }
+
+ @Override
+ protected String getPreferredMimeType() {
+ return "text/less";
+ }
+
+ @Override
+ public Formatter getFormatter(IndentPrefs preferences) {
+ return null;
+ }
+
+ public void testFormattingCase5() throws Exception {
+ reformatFileContents("testfiles/case005.less", new IndentPrefs(4, 4));
+ }
+
+}
diff --git
a/ide/css.editor/test/unit/src/org/netbeans/modules/css/editor/indent/ScssIndenterTest.java
b/ide/css.editor/test/unit/src/org/netbeans/modules/css/editor/indent/ScssIndenterTest.java
new file mode 100644
index 0000000..66901eb
--- /dev/null
+++
b/ide/css.editor/test/unit/src/org/netbeans/modules/css/editor/indent/ScssIndenterTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.css.editor.indent;
+
+import org.netbeans.editor.BaseDocument;
+import org.netbeans.modules.csl.api.Formatter;
+import org.netbeans.modules.csl.api.test.CslTestBase;
+import org.netbeans.modules.csl.spi.DefaultLanguageConfig;
+import org.netbeans.modules.css.editor.csl.CssLanguage;
+import org.netbeans.modules.css.lib.TestUtil;
+import org.netbeans.modules.parsing.api.Source;
+import org.openide.filesystems.FileObject;
+
+
+public class ScssIndenterTest extends CslTestBase {
+
+ private static final String PROP_MIME_TYPE = "mimeType"; //NOI18N
+
+ public ScssIndenterTest(String name) {
+ super(name);
+ }
+
+ @Override
+ protected DefaultLanguageConfig getPreferredLanguage() {
+ return new CssLanguage();
+ }
+
+ @Override
+ protected String getPreferredMimeType() {
+ return "text/scss";
+ }
+
+ @Override
+ public Formatter getFormatter(IndentPrefs preferences) {
+ return null;
+ }
+
+ public void testFormattingCase6() throws Exception {
+ reformatFileContents("testfiles/case006.scss", new IndentPrefs(4, 4));
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists