You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by db...@apache.org on 2022/04/04 12:28:15 UTC
[netbeans] branch master updated: Support for Micronaut configuration enhanced. (#3897)
This is an automated email from the ASF dual-hosted git repository.
dbalek 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 a4911de245 Support for Micronaut configuration enhanced. (#3897)
a4911de245 is described below
commit a4911de245fbd6574244a41eca9e2ee64bf1aa87
Author: Dusan Balek <du...@oracle.com>
AuthorDate: Mon Apr 4 14:28:09 2022 +0200
Support for Micronaut configuration enhanced. (#3897)
* Navigation to custom properties declared via @Property annotation added.
* Code completion for Micronaut config values.
* YamlStructureItem should return non null ElementHandle as required by API.
* Validation for Micronaut config values added.
---
.../micronaut/MicronautConfigProperties.java | 123 ++++++++++++++
.../micronaut/MicronautConfigValidator.java | 181 +++++++++++++++++++++
.../MicronautConfigCompletionCollector.java | 8 +
.../MicronautConfigCompletionProvider.java | 37 ++++-
.../completion/MicronautConfigCompletionTask.java | 148 ++++++++++++++---
.../MicronautConfigHyperlinkProvider.java | 25 ++-
.../refactor/MicronautRefactoringFactory.java | 34 +++-
.../netbeans/modules/micronaut/resources/layer.xml | 14 ++
.../modules/csl/hints/GsfErrorProvider.java | 6 +-
.../modules/languages/yaml/YamlParser.java | 2 +-
.../modules/languages/yaml/YamlSection.java | 36 ++--
.../modules/languages/yaml/YamlStructureItem.java | 81 +++++----
12 files changed, 611 insertions(+), 84 deletions(-)
diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/MicronautConfigProperties.java b/enterprise/micronaut/src/org/netbeans/modules/micronaut/MicronautConfigProperties.java
index 163171cae4..6a20f576e8 100644
--- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/MicronautConfigProperties.java
+++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/MicronautConfigProperties.java
@@ -18,13 +18,46 @@
*/
package org.netbeans.modules.micronaut;
+import com.sun.source.tree.AnnotationTree;
+import com.sun.source.tree.AssignmentTree;
+import com.sun.source.tree.ExpressionTree;
+import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.LiteralTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.util.TreePath;
+import com.sun.source.util.TreePathScanner;
+import com.sun.source.util.Trees;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.project.JavaProjectConstants;
+import org.netbeans.api.java.source.ClassIndex;
+import org.netbeans.api.java.source.ClasspathInfo;
+import org.netbeans.api.java.source.CompilationController;
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.api.java.source.JavaSource;
+import org.netbeans.api.java.source.TypeUtilities;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
+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.modules.parsing.spi.ParseException;
import org.openide.filesystems.FileObject;
import org.openide.util.Exceptions;
import org.springframework.boot.configurationmetadata.ConfigurationMetadataGroup;
@@ -39,6 +72,7 @@ import org.springframework.boot.configurationmetadata.ConfigurationMetadataRepos
public final class MicronautConfigProperties {
private static final String CONFIG_METADATA_JSON = "META-INF/spring-configuration-metadata.json";
+ private static final ElementHandle<TypeElement> PROPERTY_HANDLE = ElementHandle.createTypeElementHandle(ElementKind.ANNOTATION_TYPE, "io.micronaut.context.annotation.Property");
private MicronautConfigProperties() {
}
@@ -60,6 +94,16 @@ public final class MicronautConfigProperties {
Exceptions.printStackTrace(ex);
}
}
+ String customRepository = getCustomRepository(project);
+ if (customRepository != null) {
+ try {
+ InputStream stream = new ByteArrayInputStream(customRepository.getBytes(StandardCharsets.UTF_8));
+ ConfigurationMetadataRepository repository = ConfigurationMetadataRepositoryJsonBuilder.create().withJsonResource(stream).build();
+ props.putAll(repository.getAllProperties());
+ } catch (Exception ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
}
return props;
}
@@ -76,10 +120,89 @@ public final class MicronautConfigProperties {
Exceptions.printStackTrace(ex);
}
}
+ String customRepository = getCustomRepository(project);
+ if (customRepository != null) {
+ try {
+ InputStream stream = new ByteArrayInputStream(customRepository.getBytes(StandardCharsets.UTF_8));
+ ConfigurationMetadataRepository repository = ConfigurationMetadataRepositoryJsonBuilder.create().withJsonResource(stream).build();
+ groups.putAll(repository.getAllGroups());
+ } catch (Exception ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
}
return groups;
}
+ private static String getCustomRepository(Project project) {
+ AtomicReference<String> ret = new AtomicReference<>();
+ SourceGroup[] srcGroups = ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
+ for (int i = 0; i < srcGroups.length; i++) {
+ SourceGroup srcGroup = srcGroups[i];
+ ClassIndex ci = ClasspathInfo.create(srcGroup.getRootFolder()).getClassIndex();
+ Set<FileObject> resources = ci.getResources(PROPERTY_HANDLE,
+ EnumSet.of(ClassIndex.SearchKind.TYPE_REFERENCES), EnumSet.of(ClassIndex.SearchScope.SOURCE));
+ try {
+ ParserManager.parse(resources.stream().map(resource -> Source.create(resource)).collect(Collectors.toList()), new UserTask() {
+ @Override
+ public void run(ResultIterator resultIterator) throws Exception {
+ CompilationController cc = CompilationController.get(resultIterator.getParserResult());
+ cc.toPhase(JavaSource.Phase.RESOLVED);
+ Trees trees = cc.getTrees();
+ TypeElement te = PROPERTY_HANDLE.resolve(cc);
+ new TreePathScanner<Void, Void>() {
+ @Override
+ public Void visitAnnotation(AnnotationTree node, Void p) {
+ if (te == trees.getElement(new TreePath(getCurrentPath(), node.getAnnotationType()))) {
+ for (ExpressionTree argument : node.getArguments()) {
+ if (argument.getKind() == Tree.Kind.ASSIGNMENT) {
+ ExpressionTree variable = ((AssignmentTree) argument).getVariable();
+ ExpressionTree expression = ((AssignmentTree) argument).getExpression();
+ if (expression.getKind() == Tree.Kind.STRING_LITERAL && variable.getKind() == Tree.Kind.IDENTIFIER && "name".contentEquals(((IdentifierTree) variable).getName())) {
+ try {
+ String value = (String) ((LiteralTree) expression).getValue();
+ JSONObject group = new JSONObject();
+ JSONObject property = new JSONObject();
+ group.put("name", value);
+ property.put("name", value);
+ final TreePath grandParentPath = getCurrentPath().getParentPath().getParentPath();
+ if (grandParentPath.getLeaf().getKind() == Tree.Kind.VARIABLE) {
+ Element el = trees.getElement(grandParentPath);
+ if (el != null && el.getKind().isField()) {
+ String typeName = cc.getTypeUtilities().getTypeName(el.asType(), TypeUtilities.TypeNameOptions.PRINT_FQN).toString();
+ String sourceTypeName = cc.getElementUtilities().getElementName(el.getEnclosingElement(), true).toString();
+ property.put("type", typeName);
+ property.put("sourceType", sourceTypeName);
+ group.put("type", sourceTypeName);
+ }
+ }
+ JSONArray groups = new JSONArray();
+ groups.put(group);
+ JSONArray properties = new JSONArray();
+ properties.put(property);
+ JSONObject data = new JSONObject();
+ data.put("groups", groups);
+ data.put("properties", properties);
+ ret.set(data.toString());
+ } catch (JSONException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ }
+ }
+ }
+ return super.visitAnnotation(node, p);
+ }
+ }.scan(new TreePath(cc.getCompilationUnit()), null);
+ }
+ });
+ } catch (ParseException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ return ret.get();
+ }
+
private static ClassPath getExecuteClasspath(Project project) {
SourceGroup[] srcGroups = ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
if (srcGroups.length > 0) {
diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/MicronautConfigValidator.java b/enterprise/micronaut/src/org/netbeans/modules/micronaut/MicronautConfigValidator.java
new file mode 100644
index 0000000000..a30c5c2463
--- /dev/null
+++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/MicronautConfigValidator.java
@@ -0,0 +1,181 @@
+/*
+ * 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.micronaut;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
+import org.netbeans.api.editor.document.EditorDocumentUtils;
+import org.netbeans.api.java.source.ClasspathInfo;
+import org.netbeans.api.java.source.JavaSource;
+import org.netbeans.api.project.FileOwnerQuery;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.csl.api.Error;
+import org.netbeans.modules.csl.api.Hint;
+import org.netbeans.modules.csl.api.HintsProvider;
+import org.netbeans.modules.csl.api.Rule;
+import org.netbeans.modules.csl.api.RuleContext;
+import org.netbeans.modules.csl.api.Severity;
+import org.netbeans.modules.csl.api.StructureItem;
+import org.netbeans.modules.csl.api.StructureScanner;
+import org.netbeans.modules.csl.core.Language;
+import org.netbeans.modules.csl.core.LanguageRegistry;
+import org.netbeans.modules.csl.spi.DefaultError;
+import org.netbeans.modules.csl.spi.ParserResult;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty;
+
+/**
+ *
+ * @author Dusan Balek
+ */
+public class MicronautConfigValidator implements HintsProvider {
+
+ @Override
+ public void computeHints(HintsManager manager, RuleContext context, List<Hint> hints) {
+ }
+
+ @Override
+ public void computeSuggestions(HintsManager manager, RuleContext context, List<Hint> suggestions, int caretOffset) {
+ }
+
+ @Override
+ public void computeSelectionHints(HintsManager manager, RuleContext context, List<Hint> suggestions, int start, int end) {
+ }
+
+ @Override
+ public void computeErrors(HintsManager manager, RuleContext context, List<Hint> hints, List<Error> unhandled) {
+ FileObject fo = EditorDocumentUtils.getFileObject(context.doc);
+ if (MicronautConfigUtilities.isMicronautConfigFile(fo)) {
+ final ParserResult parserResult = context.parserResult;
+ final List<? extends Error> diagnostics = parserResult.getDiagnostics();
+ if (diagnostics != null && !diagnostics.isEmpty()) {
+ unhandled.addAll(diagnostics);
+ }
+ final Project project = FileOwnerQuery.getOwner(fo);
+ if (project != null) {
+ if (MicronautConfigProperties.hasConfigMetadata(project)) {
+ final Language language = LanguageRegistry.getInstance().getLanguageByMimeType(parserResult.getSnapshot().getMimeType());
+ if (language != null) {
+ final StructureScanner scanner = language.getStructure();
+ if (scanner != null) {
+ final List<? extends StructureItem> structures = scanner.scan(parserResult);
+ if (!structures.isEmpty()) {
+ final Map<String, ConfigurationMetadataProperty> properties = MicronautConfigProperties.getProperties(project);
+ if (!properties.isEmpty()) {
+ validate(parserResult, structures, "", properties, unhandled);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void cancel() {
+ }
+
+ @Override
+ public List<Rule> getBuiltinRules() {
+ return null;
+ }
+
+ @Override
+ public RuleContext createRuleContext() {
+ return new RuleContext();
+ }
+
+ @NbBundle.Messages({
+ "MSG_InvalidValue=Invalid value \"{0}\", must be of type \"{1}\"",
+ })
+ private static void validate(ParserResult parserResult, List<? extends StructureItem> structure, String name, Map<String, ConfigurationMetadataProperty> properties, List<Error> errors) {
+ final FileObject fileObject = parserResult.getSnapshot().getSource().getFileObject();
+ final CharSequence text = parserResult.getSnapshot().getText();
+ for (StructureItem item : structure) {
+ final String fullName = name.isEmpty() ? item.getName() : name + '.' + item.getName();
+ List<? extends StructureItem> nestedItems = item.getNestedItems();
+ if (nestedItems.isEmpty()) {
+ final ConfigurationMetadataProperty property = properties.get(fullName);
+ if (property != null) {
+ final String type = property.getType();
+ if (type != null && !"java.lang.String".equals(type)) {
+ try {
+ final String itemText = text.subSequence((int) item.getPosition(), (int) item.getEndPosition()).toString();
+ int idx = itemText.lastIndexOf(':');
+ if (idx >= 0) {
+ final String value = itemText.substring(idx + 1).trim();
+ if (!value.isEmpty()) {
+ int start = (int) item.getPosition() + itemText.indexOf(value, idx + 1);
+ int end = start + value.length();
+ switch (type) {
+ case "boolean":
+ if (!"true".equalsIgnoreCase(value) && !"false".equalsIgnoreCase(value)) {
+ errors.add(DefaultError.createDefaultError(null, Bundle.MSG_InvalidValue(value, type), null, fileObject, start, end, false, Severity.ERROR));
+ }
+ break;
+ case "java.lang.Integer":
+ try {
+ Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ errors.add(DefaultError.createDefaultError(null, Bundle.MSG_InvalidValue(value, type), null, fileObject, start, end, false, Severity.ERROR));
+ }
+ break;
+ case "java.lang.Long":
+ try {
+ Long.parseLong(value);
+ } catch (NumberFormatException e) {
+ errors.add(DefaultError.createDefaultError(null, Bundle.MSG_InvalidValue(value, type), null, fileObject, start, end, false, Severity.ERROR));
+ }
+ break;
+ default:
+ JavaSource js = JavaSource.create(ClasspathInfo.create(fileObject));
+ if (js != null) {
+ try {
+ js.runUserActionTask(cc -> {
+ cc.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
+ TypeElement typeElement = cc.getElements().getTypeElement(type);
+ if (typeElement != null && typeElement.getKind() == ElementKind.ENUM) {
+ if (!typeElement.getEnclosedElements().stream().anyMatch(e -> e.getKind() == ElementKind.ENUM_CONSTANT && value.contentEquals(e.getSimpleName()))) {
+ errors.add(DefaultError.createDefaultError(null, Bundle.MSG_InvalidValue(value, type), null, fileObject, start, end, false, Severity.ERROR));
+ }
+ }
+ }, true);
+ } catch (IOException ioe) {
+ Exceptions.printStackTrace(ioe);
+ }
+ }
+ }
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ }
+ }
+ }
+ } else {
+ validate(parserResult, nestedItems, fullName, properties, errors);
+ }
+ }
+ }
+}
diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautConfigCompletionCollector.java b/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautConfigCompletionCollector.java
index 06d40ba545..893f858898 100644
--- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautConfigCompletionCollector.java
+++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautConfigCompletionCollector.java
@@ -119,6 +119,14 @@ public class MicronautConfigCompletionCollector implements CompletionCollector {
}
return builder.build();
}
+
+ @Override
+ public Completion createValueItem(String value, int offset, boolean isEnum) {
+ return CompletionCollector.newBuilder(value)
+ .kind(isEnum ? Completion.Kind.EnumMember : Completion.Kind.Keyword)
+ .sortText(String.format("%04d%s", 5, value))
+ .build();
+ }
}).stream().forEach(consumer);
}
}
diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautConfigCompletionProvider.java b/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautConfigCompletionProvider.java
index 92456a7b89..f5417bb0ea 100644
--- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautConfigCompletionProvider.java
+++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautConfigCompletionProvider.java
@@ -110,7 +110,10 @@ public class MicronautConfigCompletionProvider implements CompletionProvider {
private static class MicronautConfigCompletionQuery extends AsyncCompletionQuery {
- private static final String ICON = "org/netbeans/modules/editor/resources/completion/field_16.png"; //NOI18N
+ private static final String FIELD_ICON = "org/netbeans/modules/editor/resources/completion/field_16.png"; //NOI18N
+ private static final String KEYWORD_ICON = "org/netbeans/modules/java/editor/resources/javakw_16.png"; //NOI18N
+ private static final String FIELD_COLOR = getHTMLColor(64, 198, 88);
+ private static final String KEYWORD_COLOR = getHTMLColor(64, 64, 217);
private static final Pattern FQN = Pattern.compile("(\\w+\\.)+(\\w+)");
private final Project project;
@@ -128,7 +131,7 @@ public class MicronautConfigCompletionProvider implements CompletionProvider {
String propName = property.getId();
String propType = property.getType();
CompletionUtilities.CompletionItemBuilder builder = CompletionUtilities.newCompletionItemBuilder(propName)
- .iconResource(ICON)
+ .iconResource(FIELD_ICON)
.leftHtmlText(property.isDeprecated()
? PROPERTY_NAME_COLOR + "<s>" + propName + "</s></font>"
: PROPERTY_NAME_COLOR + propName + "</font>")
@@ -211,7 +214,7 @@ public class MicronautConfigCompletionProvider implements CompletionProvider {
public CompletionItem createTopLevelPropertyItem(String propName, int offset, int baseIndent, int indentLevelSize) {
resultSet.setAnchorOffset(offset);
return CompletionUtilities.newCompletionItemBuilder(propName)
- .iconResource(ICON)
+ .iconResource(FIELD_ICON)
.leftHtmlText(PROPERTY_NAME_COLOR + "<b>" + propName + "</b></font>")
.sortPriority(10)
.onSelect(ctx -> {
@@ -249,6 +252,34 @@ public class MicronautConfigCompletionProvider implements CompletionProvider {
})
.build();
}
+
+ @Override
+ public CompletionItem createValueItem(String value, int offset, boolean isEnum) {
+ resultSet.setAnchorOffset(offset);
+ return CompletionUtilities.newCompletionItemBuilder(value)
+ .iconResource(isEnum ? FIELD_ICON : KEYWORD_ICON)
+ .leftHtmlText(isEnum ? KEYWORD_COLOR + "<b>" + value + "</b></font>" : FIELD_COLOR + value + "</font>")
+ .sortPriority(5)
+ .onSelect(ctx -> {
+ try {
+ Document doc = ctx.getComponent().getDocument();
+ LineDocument lineDocument = LineDocumentUtils.as(doc, LineDocument.class);
+ if (lineDocument != null) {
+ int caretOffset = ctx.getComponent().getCaretPosition();
+ int end = LineDocumentUtils.getWordEnd(lineDocument, caretOffset);
+ if (ctx.isOverwrite() && LineDocumentUtils.getWordStart(lineDocument, end) == offset) {
+ doc.remove(offset, Math.max(caretOffset, end) - offset);
+ } else if (offset < caretOffset) {
+ doc.remove(offset, caretOffset - offset);
+ }
+ doc.insertString(offset, value, null);
+ }
+ } catch (BadLocationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ })
+ .build();
+ }
}));
resultSet.finish();
}
diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautConfigCompletionTask.java b/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautConfigCompletionTask.java
index f94582fd59..bcd5031d42 100644
--- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautConfigCompletionTask.java
+++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/completion/MicronautConfigCompletionTask.java
@@ -18,6 +18,7 @@
*/
package org.netbeans.modules.micronaut.completion;
+import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
@@ -26,11 +27,21 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import static javax.lang.model.element.ElementKind.ENUM_CONSTANT;
+import javax.lang.model.element.TypeElement;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import org.netbeans.api.editor.document.LineDocument;
import org.netbeans.api.editor.document.LineDocumentUtils;
+import org.netbeans.api.java.project.JavaProjectConstants;
+import org.netbeans.api.java.source.ClasspathInfo;
+import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectUtils;
+import org.netbeans.api.project.SourceGroup;
import org.netbeans.lib.editor.util.swing.DocumentUtilities;
import org.netbeans.modules.csl.api.StructureItem;
import org.netbeans.modules.csl.api.StructureScanner;
@@ -56,6 +67,7 @@ public class MicronautConfigCompletionTask {
public static interface ItemFactory<T> {
T createTopLevelPropertyItem(String propName, int offset, int baseIndent, int indentLevelSize);
T createPropertyItem(ConfigurationMetadataProperty property, int offset, int baseIndent, int indentLevelSize, int idx);
+ T createValueItem(String value, int offset, boolean isEnum);
}
public <T> List<T> query(Document doc, int caretOffset, Project project, ItemFactory<T> factory) {
@@ -95,7 +107,6 @@ public class MicronautConfigCompletionTask {
currentItem = item;
}
}
- int filterLength = filter.length();
if (prefix != null) {
filter += prefix;
}
@@ -124,37 +135,77 @@ public class MicronautConfigCompletionTask {
}
}
});
+ } else {
+ final int prevWS = LineDocumentUtils.getPreviousWhitespace(lineDocument, caretOffset);
+ final int wordStart = (prevWS < lineStart + idx ? lineStart + idx : prevWS) + 1;
+ final String prefix = wordStart < caretOffset ? text.substring(wordStart - lineStart) : "";
+ final int anchorOffset = wordStart < caretOffset ? wordStart : caretOffset;
+ ParserManager.parse(Collections.singleton(Source.create(lineDocument)), new UserTask() {
+ public @Override void run(ResultIterator resultIterator) throws Exception {
+ Parser.Result r = resultIterator.getParserResult();
+ if (r instanceof ParserResult) {
+ Language language = LanguageRegistry.getInstance().getLanguageByMimeType(resultIterator.getSnapshot().getMimeType());
+ if (language != null) {
+ StructureScanner scanner = language.getStructure();
+ if (scanner != null) {
+ List<? extends StructureItem> structures = scanner.scan((ParserResult) r);
+ List<? extends StructureItem> context = getContext(structures, wordStart);
+ String propName = "";
+ for (StructureItem structureItem : context) {
+ propName += propName.isEmpty() ? structureItem.getName() : '.' + structureItem.getName();
+ }
+ if (!propName.isEmpty()) {
+ items.addAll(completeValues(propName, prefix, anchorOffset, project, factory));
+ }
+ }
+ }
+ }
+ }
+ });
}
}
} else {
if (!text.startsWith("#") && !text.startsWith("!")) {
int colIdx = text.indexOf(':');
int eqIdx = text.indexOf('=');
- if (colIdx < 0 && eqIdx < 0) {
- final int wordStart = LineDocumentUtils.getPreviousWhitespace(lineDocument, caretOffset) + 1;
- final String prefix = wordStart < caretOffset ? text.substring(wordStart - lineStart) : "";
- final int lastDotIdx = prefix.lastIndexOf('.');
- final int anchorOffset = wordStart < caretOffset ? wordStart + (lastDotIdx < 0 ? 0 : lastDotIdx + 1) : caretOffset;
- final Properties props = new Properties();
- props.load(new StringReader(doc.getText(0, doc.getLength())));
- Map<String, ConfigurationMetadataProperty> properties = MicronautConfigProperties.getProperties(project);
- Set<String> topLevels = new HashSet<>();
- for (Map.Entry<String, ConfigurationMetadataProperty> entry : properties.entrySet()) {
- String propName = entry.getKey();
- int idx = match(propName, prefix);
- if (idx >= 0) {
- int dotIdx = propName.indexOf('.', idx);
- String simpleName = dotIdx < 0 ? propName.substring(idx) : propName.substring(idx, dotIdx);
- if (props.getProperty(propName) == null) {
- items.add(factory.createPropertyItem(entry.getValue(), anchorOffset, -1, -1, idx));
- if (dotIdx > 0) {
- topLevels.add(simpleName);
+ if (colIdx < 0) {
+ if (eqIdx < 0) {
+ final int wordStart = LineDocumentUtils.getPreviousWhitespace(lineDocument, caretOffset) + 1;
+ final String prefix = wordStart < caretOffset ? text.substring(wordStart - lineStart) : "";
+ final int lastDotIdx = prefix.lastIndexOf('.');
+ final int anchorOffset = wordStart < caretOffset ? wordStart + (lastDotIdx < 0 ? 0 : lastDotIdx + 1) : caretOffset;
+ final Properties props = new Properties();
+ props.load(new StringReader(doc.getText(0, doc.getLength())));
+ Map<String, ConfigurationMetadataProperty> properties = MicronautConfigProperties.getProperties(project);
+ Set<String> topLevels = new HashSet<>();
+ for (Map.Entry<String, ConfigurationMetadataProperty> entry : properties.entrySet()) {
+ String propName = entry.getKey();
+ int idx = match(propName, prefix);
+ if (idx >= 0) {
+ int dotIdx = propName.indexOf('.', idx);
+ String simpleName = dotIdx < 0 ? propName.substring(idx) : propName.substring(idx, dotIdx);
+ if (props.getProperty(propName) == null) {
+ items.add(factory.createPropertyItem(entry.getValue(), anchorOffset, -1, -1, idx));
+ if (dotIdx > 0) {
+ topLevels.add(simpleName);
+ }
}
}
}
- }
- for (String topLevel : topLevels) {
- items.add(factory.createTopLevelPropertyItem(topLevel, anchorOffset, -1, -1));
+ for (String topLevel : topLevels) {
+ items.add(factory.createTopLevelPropertyItem(topLevel, anchorOffset, -1, -1));
+ }
+ } else {
+ int wordStart = LineDocumentUtils.getPreviousWhitespace(lineDocument, caretOffset) + 1;
+ if (wordStart < lineStart + eqIdx) {
+ wordStart = lineStart + eqIdx + 1;
+ }
+ final String prefix = wordStart < caretOffset ? text.substring(wordStart - lineStart) : "";
+ final int anchorOffset = wordStart < caretOffset ? wordStart : caretOffset;
+ final String propName = text.substring(0, eqIdx).trim();
+ if (!propName.isEmpty()) {
+ items.addAll(completeValues(propName, prefix, anchorOffset, project, factory));
+ }
}
}
}
@@ -166,6 +217,57 @@ public class MicronautConfigCompletionTask {
return items;
}
+ private <T> List<T> completeValues(String propName, String prefix, int anchorOffset, Project project, ItemFactory<T> factory) {
+ List<T> items = new ArrayList<>();
+ Map<String, ConfigurationMetadataProperty> properties = MicronautConfigProperties.getProperties(project);
+ ConfigurationMetadataProperty property = properties.get(propName);
+ if (property != null) {
+ String type = property.getType();
+ if (type != null) {
+ if ("boolean".equals(type)) {
+ if ("true".startsWith(prefix)) {
+ items.add(factory.createValueItem("true", anchorOffset, false));
+ }
+ if ("false".startsWith(prefix)) {
+ items.add(factory.createValueItem("false", anchorOffset, false));
+ }
+ } else {
+ SourceGroup[] srcGroups = ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
+ AtomicBoolean resolved = new AtomicBoolean();
+ for (SourceGroup srcGroup : srcGroups) {
+ if (!resolved.get()) {
+ JavaSource js = JavaSource.create(ClasspathInfo.create(srcGroup.getRootFolder()));
+ if (js != null) {
+ try {
+ js.runUserActionTask(cc -> {
+ cc.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
+ TypeElement typeElement = cc.getElements().getTypeElement(type);
+ if (typeElement != null) {
+ resolved.set(true);
+ if (typeElement.getKind() == ElementKind.ENUM) {
+ for (Element e : typeElement.getEnclosedElements()) {
+ if (e.getKind() == ENUM_CONSTANT) {
+ String name = e.getSimpleName().toString();
+ if (name.startsWith(prefix)) {
+ items.add(factory.createValueItem(name, anchorOffset, true));
+ }
+ }
+ }
+ }
+ }
+ }, true);
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return items;
+ }
+
private int match(String propName, String filter) {
int len = 0;
String[] parts = propName.split("\\*");
diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/hyperlink/MicronautConfigHyperlinkProvider.java b/enterprise/micronaut/src/org/netbeans/modules/micronaut/hyperlink/MicronautConfigHyperlinkProvider.java
index 608beba914..e6f243d0d3 100644
--- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/hyperlink/MicronautConfigHyperlinkProvider.java
+++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/hyperlink/MicronautConfigHyperlinkProvider.java
@@ -23,12 +23,16 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementFilter;
import javax.swing.text.Document;
import org.netbeans.api.editor.mimelookup.MimeRegistration;
@@ -129,13 +133,32 @@ public class MicronautConfigHyperlinkProvider implements HyperlinkProviderExt {
}
TypeElement te = (TypeElement) handle[0].resolve(controller);
if (te != null) {
+ ElementHandle found = null;
String name = "set" + propertyName.replace("-", "");
for (ExecutableElement executableElement : ElementFilter.methodsIn(te.getEnclosedElements())) {
if (name.equalsIgnoreCase(executableElement.getSimpleName().toString())) {
- handle[0] = ElementHandle.create(executableElement);
+ found = ElementHandle.create(executableElement);
break;
}
}
+ if (found == null) {
+ TypeElement typeElement = controller.getElements().getTypeElement("io.micronaut.context.annotation.Property");
+ for (VariableElement variableElement : ElementFilter.fieldsIn(te.getEnclosedElements())) {
+ for (AnnotationMirror annotationMirror : variableElement.getAnnotationMirrors()) {
+ if (typeElement == annotationMirror.getAnnotationType().asElement()) {
+ for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : annotationMirror.getElementValues().entrySet()) {
+ if ("name".contentEquals(entry.getKey().getSimpleName()) && propertyName.equals(entry.getValue().getValue())) {
+ found = ElementHandle.create(variableElement);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (found != null) {
+ handle[0] = found;
+ }
}
}, true);
} catch (IOException ex) {}
diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/refactor/MicronautRefactoringFactory.java b/enterprise/micronaut/src/org/netbeans/modules/micronaut/refactor/MicronautRefactoringFactory.java
index 00b4bdf22c..9bb887a352 100644
--- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/refactor/MicronautRefactoringFactory.java
+++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/refactor/MicronautRefactoringFactory.java
@@ -22,7 +22,10 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
@@ -134,13 +137,13 @@ public class MicronautRefactoringFactory implements RefactoringPluginFactory {
if (info == null) {
info = getInfo();
}
- if (info.className != null && info.methodName != null && info.methodName.startsWith("set")) {
+ if (info.className != null && info.propertyName != null) {
for (ConfigurationMetadataGroup group : MicronautConfigProperties.getGroups(project).values()) {
ConfigurationMetadataSource source = group.getSources().get(info.className);
if (source != null) {
for (ConfigurationMetadataProperty property : source.getProperties().values()) {
- String name = "set" + property.getName().replace("-", "");
- if (name.equalsIgnoreCase(info.methodName)) {
+ String name = property.getName().replace("-", "");
+ if (name.equalsIgnoreCase(info.propertyName)) {
for (FileObject configFile : configFiles) {
MicronautConfigUtilities.collectUsages(configFile, property.getId(), usage -> {
refactoringElements.add(refactoring, new WhereUsedRefactoringElement(usage.getFileObject(), usage.getStartOffset(), usage.getEndOffset(), usage.getText()));
@@ -169,9 +172,26 @@ public class MicronautRefactoringFactory implements RefactoringPluginFactory {
source.runUserActionTask(controller -> {
controller.toPhase(JavaSource.Phase.RESOLVED);
Element el = handle.resolveElement(controller);
- if (el != null && el.getKind() == ElementKind.METHOD && el.getModifiers().contains(Modifier.PUBLIC)) {
- info.methodName = el.getSimpleName().toString();
- info.className = ((TypeElement)((ExecutableElement)el).getEnclosingElement()).getQualifiedName().toString();
+ if (el != null) {
+ if (el.getKind() == ElementKind.METHOD) {
+ if (el.getModifiers().contains(Modifier.PUBLIC) && el.getSimpleName().toString().startsWith("set")) {
+ info.propertyName = el.getSimpleName().toString().substring(3);
+ info.className = ((TypeElement) el.getEnclosingElement()).getQualifiedName().toString();
+ }
+ } else if (el.getKind().isField()) {
+ TypeElement typeElement = controller.getElements().getTypeElement("io.micronaut.context.annotation.Property");
+ for (AnnotationMirror annotationMirror : el.getAnnotationMirrors()) {
+ if (typeElement == annotationMirror.getAnnotationType().asElement()) {
+ for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : annotationMirror.getElementValues().entrySet()) {
+ if ("name".contentEquals(entry.getKey().getSimpleName())) {
+ info.propertyName = (String) entry.getValue().getValue();
+ info.className = ((TypeElement) el.getEnclosingElement()).getQualifiedName().toString();
+ break;
+ }
+ }
+ }
+ }
+ }
}
}, true);
}
@@ -180,7 +200,7 @@ public class MicronautRefactoringFactory implements RefactoringPluginFactory {
private static class Info {
private String className;
- private String methodName;
+ private String propertyName;
}
}
diff --git a/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/layer.xml b/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/layer.xml
index b103120a3d..2a73a7cbf7 100644
--- a/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/layer.xml
+++ b/enterprise/micronaut/src/org/netbeans/modules/micronaut/resources/layer.xml
@@ -28,6 +28,20 @@
<file name="org-netbeans-modules-micronaut-completion-MicronautJavaConfigPropertiesCompletion.instance"/>
</folder>
</folder>
+ <folder name="x-yaml">
+ <file name="org-netbeans-modules-csl-hints-GsfErrorProvider.instance">
+ <attr name="instanceClass" stringvalue="org.netbeans.modules.csl.hints.GsfErrorProvider"/>
+ </file>
+ </folder>
+ </folder>
+ </folder>
+ <folder name="CslPlugins">
+ <folder name="text">
+ <folder name="x-yaml">
+ <file name="hints.instance">
+ <attr name="instanceClass" stringvalue="org.netbeans.modules.micronaut.MicronautConfigValidator"/>
+ </file>
+ </folder>
</folder>
</folder>
<folder name="Projects">
diff --git a/ide/csl.api/src/org/netbeans/modules/csl/hints/GsfErrorProvider.java b/ide/csl.api/src/org/netbeans/modules/csl/hints/GsfErrorProvider.java
index ca0eab0f50..4754ed03ed 100644
--- a/ide/csl.api/src/org/netbeans/modules/csl/hints/GsfErrorProvider.java
+++ b/ide/csl.api/src/org/netbeans/modules/csl/hints/GsfErrorProvider.java
@@ -112,20 +112,20 @@ public class GsfErrorProvider implements ErrorProvider {
private Diagnostic error2Diagnostic(Error error, LineDocument lineDocument, int idx) {
Diagnostic.Builder diagBuilder = Diagnostic.Builder.create(() -> {
- if (lineDocument != null) {
+ if (lineDocument != null && error.getStartPosition() >= error.getEndPosition()) {
try {
return LineDocumentUtils.getLineFirstNonWhitespace(lineDocument, error.getStartPosition());
} catch (BadLocationException ex) {}
}
return error.getStartPosition();
}, () -> {
- if (lineDocument != null) {
+ if (lineDocument != null && error.getStartPosition() >= error.getEndPosition()) {
try {
return LineDocumentUtils.getLineLastNonWhitespace(lineDocument, error.getEndPosition());
} catch (BadLocationException ex) {}
}
return error.getEndPosition();
- }, error.getDescription());
+ }, error.getDescription() != null ? error.getDescription() : error.getDisplayName());
switch (error.getSeverity()) {
case FATAL:
case ERROR:
diff --git a/ide/languages.yaml/src/org/netbeans/modules/languages/yaml/YamlParser.java b/ide/languages.yaml/src/org/netbeans/modules/languages/yaml/YamlParser.java
index 55d863d8fd..653f62837d 100644
--- a/ide/languages.yaml/src/org/netbeans/modules/languages/yaml/YamlParser.java
+++ b/ide/languages.yaml/src/org/netbeans/modules/languages/yaml/YamlParser.java
@@ -195,7 +195,7 @@ public class YamlParser extends org.netbeans.modules.parsing.spi.Parser {
if (stallCounter < 2) {
YamlSection section = sources.pop();
try {
- List<? extends StructureItem> items = section.collectItems();
+ List<? extends StructureItem> items = section.collectItems(snapshot);
result.addStructure(items);
} catch (ScannerException se) {
result.addError(section.processException(snapshot, se));
diff --git a/ide/languages.yaml/src/org/netbeans/modules/languages/yaml/YamlSection.java b/ide/languages.yaml/src/org/netbeans/modules/languages/yaml/YamlSection.java
index 131e7af2e4..f0b4b17539 100644
--- a/ide/languages.yaml/src/org/netbeans/modules/languages/yaml/YamlSection.java
+++ b/ide/languages.yaml/src/org/netbeans/modules/languages/yaml/YamlSection.java
@@ -104,7 +104,7 @@ public class YamlSection {
return source.length();
}
- List<? extends StructureItem> collectItems() {
+ List<? extends StructureItem> collectItems(Snapshot snapshot) {
if (parser != null) {
throw new IllegalStateException("This YAML segment is already parsed.");
}
@@ -112,7 +112,7 @@ public class YamlSection {
ScannerImpl scanner = new ScannerImpl(SETTINGS, new StreamReader(SETTINGS, source));
parser = new ParserImpl(SETTINGS, scanner);
while (parser.hasNext()) {
- YamlStructureItem root = processItem();
+ YamlStructureItem root = processItem(snapshot);
if (root != null) {
ret.addAll(root.getNestedItems());
}
@@ -120,21 +120,21 @@ public class YamlSection {
return ret;
}
- private YamlStructureItem processItem() {
+ private YamlStructureItem processItem(Snapshot snapshot) {
YamlStructureItem ret = null;
while ((ret == null) && parser.hasNext()) {
switch (parser.peekEvent().getEventId()) {
case MappingStart:
- ret = processMapping((MappingStartEvent) parser.next());
+ ret = processMapping(snapshot, (MappingStartEvent) parser.next());
break;
case SequenceStart:
- ret = processSequence((SequenceStartEvent) parser.next());
+ ret = processSequence(snapshot, (SequenceStartEvent) parser.next());
break;
case Scalar:
- ret = processScalar((ScalarEvent) parser.next());
+ ret = processScalar(snapshot, (ScalarEvent) parser.next());
break;
case Alias:
- ret = processAlias((AliasEvent) parser.next());
+ ret = processAlias(snapshot, (AliasEvent) parser.next());
break;
default:
parser.next();
@@ -143,19 +143,19 @@ public class YamlSection {
return ret;
}
- private YamlStructureItem processAlias(AliasEvent evt) {
- return new YamlStructureItem.Simple(ALIAS, evt.getAlias().getValue(), getIndex(evt.getStartMark()), getIndex(evt.getEndMark()));
+ private YamlStructureItem processAlias(Snapshot snapshot, AliasEvent evt) {
+ return new YamlStructureItem.Simple(ALIAS, snapshot.getSource().getFileObject(), evt.getAlias().getValue(), getIndex(evt.getStartMark()), getIndex(evt.getEndMark()));
}
- private YamlStructureItem processScalar(ScalarEvent evt) {
- return new YamlStructureItem.Simple(SCALAR, evt.getValue(), getIndex(evt.getStartMark()), getIndex(evt.getEndMark()));
+ private YamlStructureItem processScalar(Snapshot snapshot, ScalarEvent evt) {
+ return new YamlStructureItem.Simple(SCALAR, snapshot.getSource().getFileObject(), evt.getValue(), getIndex(evt.getStartMark()), getIndex(evt.getEndMark()));
}
- private YamlStructureItem processMapping(MappingStartEvent evt) {
- YamlStructureItem.Collection item = new YamlStructureItem.Collection(MAP, getIndex(evt.getStartMark()));
+ private YamlStructureItem processMapping(Snapshot snapshot, MappingStartEvent evt) {
+ YamlStructureItem.Collection item = new YamlStructureItem.Collection(MAP, snapshot.getSource().getFileObject(), getIndex(evt.getStartMark()));
while (parser.hasNext() && !parser.checkEvent(Event.ID.MappingEnd)) {
- YamlStructureItem keyItem = processItem();
- YamlStructureItem valueItem = processItem();
+ YamlStructureItem keyItem = processItem(snapshot);
+ YamlStructureItem valueItem = processItem(snapshot);
item.add(new YamlStructureItem.MapEntry(keyItem, valueItem));
}
if (parser.hasNext()) {
@@ -167,10 +167,10 @@ public class YamlSection {
return item;
}
- private YamlStructureItem processSequence(SequenceStartEvent evt) {
- YamlStructureItem.Collection item = new YamlStructureItem.Collection(SEQUENCE, getIndex(evt.getStartMark()));
+ private YamlStructureItem processSequence(Snapshot snapshot, SequenceStartEvent evt) {
+ YamlStructureItem.Collection item = new YamlStructureItem.Collection(SEQUENCE, snapshot.getSource().getFileObject(), getIndex(evt.getStartMark()));
while (parser.hasNext() && !parser.checkEvent(Event.ID.SequenceEnd)) {
- item.add(processItem());
+ item.add(processItem(snapshot));
}
if (parser.hasNext()) {
SequenceEndEvent eevt = (SequenceEndEvent) parser.next();
diff --git a/ide/languages.yaml/src/org/netbeans/modules/languages/yaml/YamlStructureItem.java b/ide/languages.yaml/src/org/netbeans/modules/languages/yaml/YamlStructureItem.java
index 8ee86132c0..2fcec4ec35 100644
--- a/ide/languages.yaml/src/org/netbeans/modules/languages/yaml/YamlStructureItem.java
+++ b/ide/languages.yaml/src/org/netbeans/modules/languages/yaml/YamlStructureItem.java
@@ -30,24 +30,31 @@ import org.netbeans.modules.csl.api.ElementHandle;
import org.netbeans.modules.csl.api.ElementKind;
import org.netbeans.modules.csl.api.HtmlFormatter;
import org.netbeans.modules.csl.api.Modifier;
+import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.csl.api.StructureItem;
+import org.netbeans.modules.csl.spi.ParserResult;
+import org.openide.filesystems.FileObject;
import org.openide.xml.XMLUtil;
/**
*
* @author lkishalmi
*/
-public abstract class YamlStructureItem implements StructureItem {
+public abstract class YamlStructureItem implements StructureItem, ElementHandle {
public static enum NodeType { MAP, SEQUENCE, MAPPING, SCALAR, ALIAS };
private static final Logger LOGGER = Logger.getLogger(YamlStructureItem.class.getName());
private final NodeType type;
+ private final FileObject fileObject;
private final long startMark;
+ private long endMark;
- public YamlStructureItem(NodeType type, long startMark) {
+ public YamlStructureItem(NodeType type, FileObject fileObject, long startMark, long endMark) {
this.type = type;
+ this.fileObject = fileObject;
this.startMark = startMark;
+ this.endMark = endMark;
}
public NodeType getType() {
@@ -72,7 +79,7 @@ public abstract class YamlStructureItem implements StructureItem {
@Override
public ElementHandle getElementHandle() {
- return null;
+ return this;
}
@Override
@@ -90,30 +97,65 @@ public abstract class YamlStructureItem implements StructureItem {
return getNestedItems().isEmpty();
}
+ @Override
+ public FileObject getFileObject() {
+ return fileObject;
+ }
+
@Override
public long getPosition() {
return startMark;
}
+ @Override
+ public long getEndPosition() {
+ return endMark;
+ }
+
+ @Override
+ public OffsetRange getOffsetRange(ParserResult result) {
+ return new OffsetRange((int) startMark, (int) endMark);
+ }
+
@Override
public ImageIcon getCustomIcon() {
return null;
}
+ @Override
+ public String getIn() {
+ return null;
+ }
+
+ @Override
+ public String getMimeType() {
+ return YamlTokenId.YAML_MIME_TYPE;
+ }
+
+ @Override
+ public boolean signatureEquals(ElementHandle handle) {
+ if (handle instanceof YamlStructureItem) {
+ return this.equals(handle);
+ }
+ return false;
+ }
+
@Override
public String toString() {
return "" + getPosition() + ": " + getName();
}
+ void setEndMark(long end) {
+ endMark = end;
+ }
+
public static final class Simple extends YamlStructureItem {
final String name;
- final long endMark;
- public Simple(NodeType type, String name, long startMark, long endMark) {
- super(type, startMark);
+ public Simple(NodeType type, FileObject fileObject, String name, long startMark, long endMark) {
+ super(type, fileObject, startMark, endMark);
this.name = name;
- this.endMark = endMark;
}
@Override
@@ -125,21 +167,13 @@ public abstract class YamlStructureItem implements StructureItem {
public List<? extends StructureItem> getNestedItems() {
return Collections.emptyList();
}
-
- @Override
- public long getEndPosition() {
- return endMark;
- }
-
}
public static final class Collection extends YamlStructureItem {
private final List<YamlStructureItem> children = new ArrayList<>();
- private long endMark;
- public Collection(NodeType type, long startMark) {
- super(type, startMark);
- this.endMark = startMark;
+ public Collection(NodeType type, FileObject fileObject, long startMark) {
+ super(type, fileObject, startMark, startMark);
}
@Override
@@ -156,19 +190,10 @@ public abstract class YamlStructureItem implements StructureItem {
return children;
}
- @Override
- public long getEndPosition() {
- return endMark;
- }
-
public void add(YamlStructureItem item) {
- endMark = item.getEndPosition();
+ setEndMark(item.getEndPosition());
children.add(item);
}
-
- public void setEndMark(int end) {
- endMark = end;
- }
}
public static final class MapEntry extends YamlStructureItem {
@@ -176,7 +201,7 @@ public abstract class YamlStructureItem implements StructureItem {
final YamlStructureItem valueItem;
public MapEntry(YamlStructureItem keyItem, YamlStructureItem valueItem) {
- super(NodeType.MAPPING, keyItem.startMark);
+ super(NodeType.MAPPING, keyItem.fileObject, keyItem.startMark, valueItem.endMark);
this.keyItem = keyItem;
this.valueItem = valueItem;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists