You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@netbeans.apache.org by GitBox <gi...@apache.org> on 2022/01/28 11:56:02 UTC

[GitHub] [netbeans] ppisl opened a new pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

ppisl opened a new pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525


   This is the outlineview implementation not only for Groovy files, but for all GSF languages that are/will be enabled in the Vs Code extension. At the moment it is for Groovy files and YAML files that have `application` or `bootstrap` prefix.
   
   The implementation requires adding two interfaces to the LSP API. Clients can implement and register a `StructureProvider` into `MimeLookup` for a given mimetype. `StructureProvider` provides a list of top symbols to be displayed in the outline view. The symbol structure is composed of `StrctureElements`. 
   
   StructureElements are then translated into `DocumentSymbol`s on the VSCode API side, which are displayed in the outline view and also in Go to a symbol (CTRL+SHIFT+O by default). `DocumentSymbol`  has two methods `getName()` and `getDetail()`, which both return `String` and the resulting compound text is displayed in the outline view, where the text returned by `getName()` is slightly larger than the text returned by `getDetail()`. On the other hand, only the text returned by `getName()` is displayed in **Go to a symbol**. The `DocumentSymbol` documentation says that `getName()` should return the name of the symbol and `getDetail()` should return the detail of the symbol, such as the signature of the function. 
   
   Currently in outline view we display the signature as the symbol name and the type as the symbol detail for java files. This means that in Go to a symbol we display not only the names but the symbol, but also signatures with the types of the function parameters, which can affect the symbol search.
   
   On the other hand, the java extension offered by Microsoft does the same. However, in my opinion, `getName` should really return only the name of the symbols and this would make the search in Go to symbol easier. 
   
   This PR also moves the existing functionality that provided outline view for java files outside the LSP server. The JavaStructureProvider implementation is now in the java.editor module, which already has a dependency on the LSP API.  Provider should logically belong to java.navigation module, but this module is not enabled for VsCode extension and if we enable it, it brings with it dependency on WindowsSystem.API, which is not sufficient now.  


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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r804469788



##########
File path: ide/api.lsp/src/org/netbeans/spi/lsp/StructureProvider.java
##########
@@ -0,0 +1,244 @@
+/*
+ * 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.spi.lsp;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import org.netbeans.api.lsp.StructureElement;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import javax.swing.text.Document;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.modules.lsp.StructureElementAccessor;
+
+/**
+ * Interface for building structure of symbols at a given document.
+ * Implementations of the interface should be registered in MimeLookup.
+ * <pre>
+ *
+ *  {@code @MimeRegistration(mimeType = "text/foo", service = StructureProvider.class)
+ *   public class FooStructureProvider implements StructureProvider {
+ *     ...
+ *   }
+ *  }
+ * </pre>
+ *
+ * @author Petr Pisl
+ * @since 1.8
+ */
+public interface StructureProvider {
+
+    /**
+     * Resolves a structure tree of symbols at the given document.
+     *
+     * @param doc document on which to operate.
+     * @return a list of top level structure elements
+     *
+     * @since 1.8
+     */
+    @NonNull
+    CompletableFuture<List<StructureElement>> getStructure(@NonNull Document doc);
+
+    /**
+     * Create builder for {@link StructureElement} instances.
+     *
+     * @param name the name of the structure element
+     * @param kind the kind of structure element
+     * @return newly created builder
+     *
+     * @since 1.8
+     */
+    public static Builder newBuilder(@NonNull String name, @NonNull StructureElement.Kind kind) {
+        return new Builder(name, kind);
+    }
+
+    /**
+     * Builder for {@link StructureElement} instances.
+     *
+     * @since 1.8
+     */
+    public static final class Builder {
+
+        private String name;
+        private String detail;
+        private int selectionStartOffset;
+        private int selectionEndOffset;
+        private int expandedStartOffset;
+        private int expandedEndOffset;
+        private StructureElement.Kind kind;
+        private Set<StructureElement.Tag> tags;
+        private List<StructureElement> children;
+
+        private Builder(@NonNull String name, @NonNull StructureElement.Kind kind) {
+            this.name = name;
+            this.kind = kind;
+        }
+
+        /**
+         * The name of {@link StructureElement} is displayed in the structure
+         * tree and other ui.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder name(@NonNull String name) {
+            this.name = name;
+            return this;
+        }
+
+        /**
+         * Kind of this structure element.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder kind(@NonNull StructureElement.Kind name) {
+            this.kind = kind;
+            return this;
+        }
+
+        /**
+         * The detail of {@link StructureElement}, e.g the signature of a
+         * function. If not provided only the name is used.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder detail(@NonNull String detail) {
+            this.detail = detail;
+            return this;
+        }
+
+        /**
+         * The start of offset range where this element should be selected and
+         * revealed in document when selected in outline view.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder selectionStartOffset(int selectionStartOffset) {
+            this.selectionStartOffset = selectionStartOffset;
+            return this;
+        }
+
+        /**
+         * The end of offset range where this element should be selected and
+         * revealed in document when selected in outline view.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder selectionEndOffset(int selectionEndOffset) {
+            this.selectionEndOffset = selectionEndOffset;
+            return this;
+        }
+
+        /**
+         * The expanded range is offset range that is typically used to
+         * determine if the cursors inside the element to reveal in the element
+         * in the UI.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder expandedStartOffset(int expandedStartOffset) {
+            this.expandedStartOffset = expandedStartOffset;
+            return this;
+        }
+
+        /**
+         * The expanded range is offset range that is typically used to
+         * determine if the cursors inside the element to reveal in the element
+         * in the UI.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder expandedEndOffset(int expandedEndOffset) {
+            this.expandedEndOffset = expandedEndOffset;
+            return this;
+        }
+
+        /**
+         * Adds tag for this structure element.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder addTag(@NonNull StructureElement.Tag tag) {
+            if (this.tags == null) {
+                this.tags = new HashSet<>();
+            }
+            this.tags.add(tag);
+            return this;
+        }
+        
+        /**
+         * Tags for this structure element.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder tags(@NonNull Set<StructureElement.Tag> tags) {
+            this.tags = tags;
+            return this;
+        }
+
+        /**
+         * Adds sub element for this structure element.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder addChild(@NonNull StructureElement child) {

Review comment:
       I have changed this. 




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r801709734



##########
File path: ide/api.lsp/src/org/netbeans/api/lsp/StructureElement.java
##########
@@ -0,0 +1,130 @@
+/*
+ * 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.api.lsp;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * StructureElement is a tree item that shows the structure of the source code.
+ * 
+ * @author Petr Pisl
+ * @since 1.8
+ */
+public interface StructureElement {

Review comment:
       Done




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r794847685



##########
File path: ide/api.lsp/src/org/netbeans/api/lsp/StructureElement.java
##########
@@ -0,0 +1,130 @@
+/*
+ * 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.api.lsp;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * StructureElement is a tree item that shows the structure of the source code.
+ * 
+ * @author Petr Pisl
+ * @since 1.8
+ */
+public interface StructureElement {
+   
+    /**
+     * Kind of the structure element. 
+     */
+    public static enum Kind {
+        File,
+	Module,

Review comment:
       Oh, this was copy pase from other place. I will correct it. 




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r805839287



##########
File path: ide/csl.api/src/org/netbeans/modules/csl/navigation/GsfStructureProvider.java
##########
@@ -0,0 +1,268 @@
+/*
+ * 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.csl.navigation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+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.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.ParserResult;
+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.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.api.lsp.StructureElement;
+import org.netbeans.modules.csl.api.ElementKind;
+import org.netbeans.modules.csl.api.HtmlFormatter;
+import org.netbeans.modules.csl.api.Modifier;
+import org.netbeans.spi.lsp.StructureProvider;
+
+/**
+ * Implementation of StructureProvider to supply outline view in VSCode
+ * @author Petr Pisl
+ */
+public class GsfStructureProvider implements StructureProvider {
+
+    private static final Logger LOGGER = Logger.getLogger(GsfStructureProvider.class.getName());
+    
+    private static StructureElement.Kind convertKind(ElementKind elementKind) {
+        switch(elementKind) {
+            case ATTRIBUTE: return StructureElement.Kind.Property;
+            case CALL: return StructureElement.Kind.Event;
+            case CLASS: return StructureElement.Kind.Class;
+            case CONSTANT: return StructureElement.Kind.Constant;
+            case CONSTRUCTOR: return StructureElement.Kind.Constructor;
+            case DB: return StructureElement.Kind.File;
+            case ERROR: return StructureElement.Kind.Event;
+            case METHOD: return StructureElement.Kind.Method;
+            case FILE: return StructureElement.Kind.File;
+            case FIELD: return StructureElement.Kind.Field;
+            case MODULE: return StructureElement.Kind.Module;
+            case VARIABLE: return StructureElement.Kind.Variable;
+            case GLOBAL: return StructureElement.Kind.Module;
+            case INTERFACE: return StructureElement.Kind.Interface;
+            case KEYWORD: return StructureElement.Kind.Key;
+            case OTHER: return StructureElement.Kind.Object;
+            case PACKAGE: return StructureElement.Kind.Package;
+            case PARAMETER: return StructureElement.Kind.TypeParameter;
+            case PROPERTY: return StructureElement.Kind.Property;
+            case RULE: return StructureElement.Kind.Event;
+            case TAG: return StructureElement.Kind.Operator;
+            case TEST: return StructureElement.Kind.Function;
+        }
+        return StructureElement.Kind.Object;
+    }
+    
+    private static void  createDetail(StructureItem item, Builder builder) {
+        NoHtmlFormatter formatter = new NoHtmlFormatter();
+        String s = item.getHtml(formatter);
+        s = s.substring(item.getName().length()).trim();
+        if (!s.trim().isEmpty()) {
+            builder.detail(s);
+        }
+    }
+    
+    private static void createTags(StructureItem item, Builder builder) {
+        if (item.getModifiers().contains(Modifier.DEPRECATED)) {
+            builder.addTag(StructureElement.Tag.Deprecated);
+        }
+    }
+    
+    private static void createChildren(Document doc, StructureItem item, Builder builder) {
+        if (!item.isLeaf()) {
+            List <? extends StructureItem> origChildren = item.getNestedItems();
+            if (!origChildren.isEmpty()) {
+                List<StructureElement> children = new ArrayList<>(origChildren.size());
+                convertStructureItems(doc, origChildren, children);
+                builder.children(children);
+            }
+        }
+    }
+    
+    /** A formatter that strips the html elements from the text */
+    static private class NoHtmlFormatter extends HtmlFormatter {
+        StringBuilder sb = new StringBuilder();
+        
+        @Override
+        public void reset() {
+            sb = new StringBuilder();
+        }
+
+        static String stripHtml( String htmlText ) {
+            if( null == htmlText )
+                return null;
+            String res = htmlText.replaceAll( "<[^>]*>", "" ); // NOI18N // NOI18N
+            res = res.replaceAll( "&nbsp;", " " ); // NOI18N // NOI18N
+            res = res.trim();
+            return res;
+        }
+        
+        @Override
+        public void appendHtml(String html) {
+            sb.append(stripHtml(html));
+        }
+
+        @Override
+        public void appendText(String text, int fromInclusive, int toExclusive) {
+            int l = toExclusive - fromInclusive;
+            if (sb.length() + l < maxLength) {
+                sb.append(text.subSequence(fromInclusive, toExclusive));
+            } else {
+                sb.append(text.subSequence(fromInclusive, toExclusive - (l - maxLength)));
+                sb.append("...");   //NOI18N
+            }
+        }
+
+        @Override
+        public void emphasis(boolean start) {
+        }
+
+        @Override
+        public void name(ElementKind kind, boolean start) {
+        }
+
+        @Override
+        public void parameters(boolean start) {
+        }
+
+        @Override
+        public void active(boolean start) {
+        }
+
+        @Override
+        public void type(boolean start) {
+        }
+
+        @Override
+        public void deprecated(boolean start) {
+        }
+
+        @Override
+        public String getText() {
+            return sb.toString();
+        }
+    }
+    
+    @Override
+    public CompletableFuture<List<StructureElement>> getStructure(Document doc) {
+        final List<StructureElement> sElements = new ArrayList<>();
+        try {
+            ParserManager.parse(Collections.singletonList(Source.create(doc)), new UserTask() {
+                @Override
+                public void run(ResultIterator resultIterator) throws Exception {
+                    Parser.Result result = resultIterator.getParserResult(-1);
+                    if(result instanceof ParserResult) {
+                        ParserResult parserResult = (ParserResult) result;
+                        Language language = LanguageRegistry.getInstance().getLanguageByMimeType(resultIterator.getSnapshot().getMimeType());
+                        if (language != null) {
+                            StructureScanner scanner = language.getStructure();
+                            if (scanner != null) {
+                                List<? extends StructureItem> items = scanner.scan(parserResult);
+                                convertStructureItems(doc, items, sElements);
+                            }
+                        }
+                    }
+                }
+
+            });
+            return CompletableFuture.completedFuture(sElements);
+        } catch (ParseException ex) {
+            LOGGER.log(Level.FINE, null, ex);
+            return CompletableFuture.completedFuture(null);
+        }
+    }
+    
+    private static void convertStructureItems(Document doc, List<? extends StructureItem> items, List<StructureElement> sElements) {
+        StructureElement lastElement = null;
+        if (doc instanceof LineDocument) {
+            //  if it's line document, we can set the enclosing range for whole line
+            LineDocument ldoc = (LineDocument)doc;
+            for (StructureItem item : items) {
+                int startOffset = (int)item.getPosition();
+                int lineStart = startOffset;
+                int lineEnd = (int)item.getEndPosition();
+                Builder builder = StructureProvider.newBuilder(item.getName(), convertKind(item.getKind()));
+                builder.selectionStartOffset(startOffset).selectionEndOffset(lineEnd);
+                createDetail(item, builder);
+                createTags(item, builder);
+
+                try {
+                    String prefix = doc.getText(lineStart, startOffset);

Review comment:
       This is useful for example for yaml files like:
   ```
   martin:
     name: Martin D'vloper
   |  job: Developer
     skill: Elite
   ```
   The ui will select the `job` item, not `martin` structure (that will be selected if the job expanded offsets will be the same lake selected offsets. 




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r805644354



##########
File path: ide/csl.api/src/org/netbeans/modules/csl/navigation/GsfStructureProvider.java
##########
@@ -0,0 +1,268 @@
+/*
+ * 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.csl.navigation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+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.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.ParserResult;
+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.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.api.lsp.StructureElement;
+import org.netbeans.modules.csl.api.ElementKind;
+import org.netbeans.modules.csl.api.HtmlFormatter;
+import org.netbeans.modules.csl.api.Modifier;
+import org.netbeans.spi.lsp.StructureProvider;
+
+/**
+ * Implementation of StructureProvider to supply outline view in VSCode
+ * @author Petr Pisl
+ */
+public class GsfStructureProvider implements StructureProvider {
+
+    private static final Logger LOGGER = Logger.getLogger(GsfStructureProvider.class.getName());
+    
+    private static StructureElement.Kind convertKind(ElementKind elementKind) {
+        switch(elementKind) {
+            case ATTRIBUTE: return StructureElement.Kind.Property;
+            case CALL: return StructureElement.Kind.Event;
+            case CLASS: return StructureElement.Kind.Class;
+            case CONSTANT: return StructureElement.Kind.Constant;
+            case CONSTRUCTOR: return StructureElement.Kind.Constructor;
+            case DB: return StructureElement.Kind.File;
+            case ERROR: return StructureElement.Kind.Event;
+            case METHOD: return StructureElement.Kind.Method;
+            case FILE: return StructureElement.Kind.File;
+            case FIELD: return StructureElement.Kind.Field;
+            case MODULE: return StructureElement.Kind.Module;
+            case VARIABLE: return StructureElement.Kind.Variable;
+            case GLOBAL: return StructureElement.Kind.Module;
+            case INTERFACE: return StructureElement.Kind.Interface;
+            case KEYWORD: return StructureElement.Kind.Key;
+            case OTHER: return StructureElement.Kind.Object;
+            case PACKAGE: return StructureElement.Kind.Package;
+            case PARAMETER: return StructureElement.Kind.TypeParameter;
+            case PROPERTY: return StructureElement.Kind.Property;
+            case RULE: return StructureElement.Kind.Event;
+            case TAG: return StructureElement.Kind.Operator;
+            case TEST: return StructureElement.Kind.Function;
+        }
+        return StructureElement.Kind.Object;
+    }
+    
+    private static void  createDetail(StructureItem item, Builder builder) {
+        NoHtmlFormatter formatter = new NoHtmlFormatter();
+        String s = item.getHtml(formatter);
+        s = s.substring(item.getName().length()).trim();
+        if (!s.trim().isEmpty()) {
+            builder.detail(s);
+        }
+    }
+    
+    private static void createTags(StructureItem item, Builder builder) {
+        if (item.getModifiers().contains(Modifier.DEPRECATED)) {
+            builder.addTag(StructureElement.Tag.Deprecated);
+        }
+    }
+    
+    private static void createChildren(Document doc, StructureItem item, Builder builder) {
+        if (!item.isLeaf()) {
+            List <? extends StructureItem> origChildren = item.getNestedItems();
+            if (!origChildren.isEmpty()) {
+                List<StructureElement> children = new ArrayList<>(origChildren.size());
+                convertStructureItems(doc, origChildren, children);
+                builder.children(children);
+            }
+        }
+    }
+    
+    /** A formatter that strips the html elements from the text */
+    static private class NoHtmlFormatter extends HtmlFormatter {
+        StringBuilder sb = new StringBuilder();
+        
+        @Override
+        public void reset() {
+            sb = new StringBuilder();
+        }
+
+        static String stripHtml( String htmlText ) {
+            if( null == htmlText )
+                return null;
+            String res = htmlText.replaceAll( "<[^>]*>", "" ); // NOI18N // NOI18N
+            res = res.replaceAll( "&nbsp;", " " ); // NOI18N // NOI18N
+            res = res.trim();
+            return res;
+        }
+        
+        @Override
+        public void appendHtml(String html) {
+            sb.append(stripHtml(html));
+        }
+
+        @Override
+        public void appendText(String text, int fromInclusive, int toExclusive) {
+            int l = toExclusive - fromInclusive;
+            if (sb.length() + l < maxLength) {
+                sb.append(text.subSequence(fromInclusive, toExclusive));
+            } else {
+                sb.append(text.subSequence(fromInclusive, toExclusive - (l - maxLength)));
+                sb.append("...");   //NOI18N
+            }
+        }
+
+        @Override
+        public void emphasis(boolean start) {
+        }
+
+        @Override
+        public void name(ElementKind kind, boolean start) {
+        }
+
+        @Override
+        public void parameters(boolean start) {
+        }
+
+        @Override
+        public void active(boolean start) {
+        }
+
+        @Override
+        public void type(boolean start) {
+        }
+
+        @Override
+        public void deprecated(boolean start) {
+        }
+
+        @Override
+        public String getText() {
+            return sb.toString();
+        }
+    }
+    
+    @Override
+    public CompletableFuture<List<StructureElement>> getStructure(Document doc) {
+        final List<StructureElement> sElements = new ArrayList<>();
+        try {
+            ParserManager.parse(Collections.singletonList(Source.create(doc)), new UserTask() {
+                @Override
+                public void run(ResultIterator resultIterator) throws Exception {
+                    Parser.Result result = resultIterator.getParserResult(-1);
+                    if(result instanceof ParserResult) {
+                        ParserResult parserResult = (ParserResult) result;
+                        Language language = LanguageRegistry.getInstance().getLanguageByMimeType(resultIterator.getSnapshot().getMimeType());
+                        if (language != null) {
+                            StructureScanner scanner = language.getStructure();
+                            if (scanner != null) {
+                                List<? extends StructureItem> items = scanner.scan(parserResult);
+                                convertStructureItems(doc, items, sElements);
+                            }
+                        }
+                    }
+                }
+
+            });
+            return CompletableFuture.completedFuture(sElements);
+        } catch (ParseException ex) {
+            LOGGER.log(Level.FINE, null, ex);
+            return CompletableFuture.completedFuture(null);
+        }
+    }
+    
+    private static void convertStructureItems(Document doc, List<? extends StructureItem> items, List<StructureElement> sElements) {
+        StructureElement lastElement = null;
+        if (doc instanceof LineDocument) {
+            //  if it's line document, we can set the enclosing range for whole line
+            LineDocument ldoc = (LineDocument)doc;
+            for (StructureItem item : items) {
+                int startOffset = (int)item.getPosition();
+                int lineStart = startOffset;
+                int lineEnd = (int)item.getEndPosition();
+                Builder builder = StructureProvider.newBuilder(item.getName(), convertKind(item.getKind()));
+                builder.selectionStartOffset(startOffset).selectionEndOffset(lineEnd);
+                createDetail(item, builder);
+                createTags(item, builder);
+
+                try {
+                    String prefix = doc.getText(lineStart, startOffset);
+                    lineStart = LineDocumentUtils.getLineStart(ldoc, lineStart);
+                    if (prefix.trim().isEmpty()) {
+                        lineEnd = LineDocumentUtils.getLineEnd(ldoc, lineEnd);
+                    } else {
+                        lineStart = startOffset;
+                    }
+                    
+                } catch (BadLocationException ex) {
+                    lineStart = (int)item.getPosition();
+                    lineEnd = (int)item.getEndPosition();
+                }
+                if (lastElement == null) {
+                    builder.expandedStartOffset(lineStart);
+                    builder.expandedEndOffset(lineEnd);
+                } else {
+                    if (lastElement.getExpandedEndOffset() < lineStart) {
+                        builder.expandedStartOffset(lineStart);
+                        builder.expandedEndOffset(lineEnd);
+                    } else if (lastElement.getExpandedStartOffset() <= lineStart && lineEnd == lastElement.getExpandedEndOffset()) {
+                        // The same line
+                        sElements.remove(lastElement);
+                        Builder leBuilder = StructureProvider.newBuilder(lastElement.getName(), lastElement.getKind());

Review comment:
       I was thinking about this as well. I will do it. 




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r806083325



##########
File path: java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java
##########
@@ -813,97 +814,61 @@ protected void process(CompilationInfo arg0, Document arg1, SchedulerEvent arg2)
     @Override
     public CompletableFuture<List<Either<SymbolInformation, DocumentSymbol>>> documentSymbol(DocumentSymbolParams params) {
         return server.openedProjects().thenCompose(projects -> {
-            JavaSource js = getJavaSource(params.getTextDocument().getUri());
-            if (js == null) {
+            List<Either<SymbolInformation, DocumentSymbol>> result = new ArrayList<>();
+        
+            String uri = params.getTextDocument().getUri();
+            FileObject file = fromURI(uri);
+            Document doc = server.getOpenedDocuments().getDocument(uri);
+            if (file == null || !(doc instanceof LineDocument)) {
                 return CompletableFuture.completedFuture(Collections.emptyList());
             }
-            List<Either<SymbolInformation, DocumentSymbol>> result = new ArrayList<>();
-            try {
-                js.runUserActionTask(cc -> {
-                    cc.toPhase(JavaSource.Phase.RESOLVED);
-                    Trees trees = cc.getTrees();
-                    CompilationUnitTree cu = cc.getCompilationUnit();
-                    if (cu.getPackage() != null) {
-                        TreePath tp = trees.getPath(cu, cu.getPackage());
-                        Element el = trees.getElement(tp);
-                        if (el != null && el.getKind() == ElementKind.PACKAGE) {
-                            String name = Utils.label(cc, el, true);
-                            SymbolKind kind = Utils.elementKind2SymbolKind(el.getKind());
-                            Range range = Utils.treeRange(cc, tp.getLeaf());
-                            result.add(Either.forRight(new DocumentSymbol(name, kind, range, range)));
-                        }
-                    }
-                    for (Element tel : cc.getTopLevelElements()) {
-                        DocumentSymbol ds = element2DocumentSymbol(cc, tel);
-                        if (ds != null)
+            StructureProvider structureProvider = MimeLookup.getLookup(DocumentUtilities.getMimeType(doc)).lookup(StructureProvider.class);
+            if (structureProvider != null) {
+                return structureProvider.getStructure(doc).thenApply(structureElements -> {

Review comment:
       I have put it into the Background taks.




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r805852652



##########
File path: ide/csl.api/src/org/netbeans/modules/csl/navigation/GsfStructureProvider.java
##########
@@ -0,0 +1,268 @@
+/*
+ * 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.csl.navigation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+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.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.ParserResult;
+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.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.api.lsp.StructureElement;
+import org.netbeans.modules.csl.api.ElementKind;
+import org.netbeans.modules.csl.api.HtmlFormatter;
+import org.netbeans.modules.csl.api.Modifier;
+import org.netbeans.spi.lsp.StructureProvider;
+
+/**
+ * Implementation of StructureProvider to supply outline view in VSCode
+ * @author Petr Pisl
+ */
+public class GsfStructureProvider implements StructureProvider {
+
+    private static final Logger LOGGER = Logger.getLogger(GsfStructureProvider.class.getName());
+    
+    private static StructureElement.Kind convertKind(ElementKind elementKind) {
+        switch(elementKind) {
+            case ATTRIBUTE: return StructureElement.Kind.Property;
+            case CALL: return StructureElement.Kind.Event;
+            case CLASS: return StructureElement.Kind.Class;
+            case CONSTANT: return StructureElement.Kind.Constant;
+            case CONSTRUCTOR: return StructureElement.Kind.Constructor;
+            case DB: return StructureElement.Kind.File;
+            case ERROR: return StructureElement.Kind.Event;
+            case METHOD: return StructureElement.Kind.Method;
+            case FILE: return StructureElement.Kind.File;
+            case FIELD: return StructureElement.Kind.Field;
+            case MODULE: return StructureElement.Kind.Module;
+            case VARIABLE: return StructureElement.Kind.Variable;
+            case GLOBAL: return StructureElement.Kind.Module;
+            case INTERFACE: return StructureElement.Kind.Interface;
+            case KEYWORD: return StructureElement.Kind.Key;
+            case OTHER: return StructureElement.Kind.Object;
+            case PACKAGE: return StructureElement.Kind.Package;
+            case PARAMETER: return StructureElement.Kind.TypeParameter;
+            case PROPERTY: return StructureElement.Kind.Property;
+            case RULE: return StructureElement.Kind.Event;
+            case TAG: return StructureElement.Kind.Operator;
+            case TEST: return StructureElement.Kind.Function;
+        }
+        return StructureElement.Kind.Object;
+    }
+    
+    private static void  createDetail(StructureItem item, Builder builder) {
+        NoHtmlFormatter formatter = new NoHtmlFormatter();
+        String s = item.getHtml(formatter);
+        s = s.substring(item.getName().length()).trim();
+        if (!s.trim().isEmpty()) {
+            builder.detail(s);
+        }
+    }
+    
+    private static void createTags(StructureItem item, Builder builder) {
+        if (item.getModifiers().contains(Modifier.DEPRECATED)) {
+            builder.addTag(StructureElement.Tag.Deprecated);
+        }
+    }
+    
+    private static void createChildren(Document doc, StructureItem item, Builder builder) {
+        if (!item.isLeaf()) {
+            List <? extends StructureItem> origChildren = item.getNestedItems();
+            if (!origChildren.isEmpty()) {
+                List<StructureElement> children = new ArrayList<>(origChildren.size());
+                convertStructureItems(doc, origChildren, children);
+                builder.children(children);
+            }
+        }
+    }
+    
+    /** A formatter that strips the html elements from the text */
+    static private class NoHtmlFormatter extends HtmlFormatter {
+        StringBuilder sb = new StringBuilder();
+        
+        @Override
+        public void reset() {
+            sb = new StringBuilder();
+        }
+
+        static String stripHtml( String htmlText ) {
+            if( null == htmlText )
+                return null;
+            String res = htmlText.replaceAll( "<[^>]*>", "" ); // NOI18N // NOI18N
+            res = res.replaceAll( "&nbsp;", " " ); // NOI18N // NOI18N
+            res = res.trim();
+            return res;
+        }
+        
+        @Override
+        public void appendHtml(String html) {
+            sb.append(stripHtml(html));
+        }
+
+        @Override
+        public void appendText(String text, int fromInclusive, int toExclusive) {
+            int l = toExclusive - fromInclusive;
+            if (sb.length() + l < maxLength) {
+                sb.append(text.subSequence(fromInclusive, toExclusive));
+            } else {
+                sb.append(text.subSequence(fromInclusive, toExclusive - (l - maxLength)));
+                sb.append("...");   //NOI18N
+            }
+        }
+
+        @Override
+        public void emphasis(boolean start) {
+        }
+
+        @Override
+        public void name(ElementKind kind, boolean start) {
+        }
+
+        @Override
+        public void parameters(boolean start) {
+        }
+
+        @Override
+        public void active(boolean start) {
+        }
+
+        @Override
+        public void type(boolean start) {
+        }
+
+        @Override
+        public void deprecated(boolean start) {
+        }
+
+        @Override
+        public String getText() {
+            return sb.toString();
+        }
+    }
+    
+    @Override
+    public CompletableFuture<List<StructureElement>> getStructure(Document doc) {
+        final List<StructureElement> sElements = new ArrayList<>();
+        try {
+            ParserManager.parse(Collections.singletonList(Source.create(doc)), new UserTask() {
+                @Override
+                public void run(ResultIterator resultIterator) throws Exception {
+                    Parser.Result result = resultIterator.getParserResult(-1);
+                    if(result instanceof ParserResult) {
+                        ParserResult parserResult = (ParserResult) result;
+                        Language language = LanguageRegistry.getInstance().getLanguageByMimeType(resultIterator.getSnapshot().getMimeType());
+                        if (language != null) {
+                            StructureScanner scanner = language.getStructure();
+                            if (scanner != null) {
+                                List<? extends StructureItem> items = scanner.scan(parserResult);
+                                convertStructureItems(doc, items, sElements);
+                            }
+                        }
+                    }
+                }
+
+            });
+            return CompletableFuture.completedFuture(sElements);
+        } catch (ParseException ex) {
+            LOGGER.log(Level.FINE, null, ex);
+            return CompletableFuture.completedFuture(null);
+        }
+    }
+    
+    private static void convertStructureItems(Document doc, List<? extends StructureItem> items, List<StructureElement> sElements) {
+        StructureElement lastElement = null;
+        if (doc instanceof LineDocument) {
+            //  if it's line document, we can set the enclosing range for whole line
+            LineDocument ldoc = (LineDocument)doc;
+            for (StructureItem item : items) {
+                int startOffset = (int)item.getPosition();
+                int lineStart = startOffset;
+                int lineEnd = (int)item.getEndPosition();
+                Builder builder = StructureProvider.newBuilder(item.getName(), convertKind(item.getKind()));
+                builder.selectionStartOffset(startOffset).selectionEndOffset(lineEnd);
+                createDetail(item, builder);
+                createTags(item, builder);
+
+                try {
+                    String prefix = doc.getText(lineStart, startOffset);
+                    lineStart = LineDocumentUtils.getLineStart(ldoc, lineStart);
+                    if (prefix.trim().isEmpty()) {
+                        lineEnd = LineDocumentUtils.getLineEnd(ldoc, lineEnd);
+                    } else {
+                        lineStart = startOffset;
+                    }
+                    
+                } catch (BadLocationException ex) {
+                    lineStart = (int)item.getPosition();
+                    lineEnd = (int)item.getEndPosition();
+                }
+                if (lastElement == null) {
+                    builder.expandedStartOffset(lineStart);
+                    builder.expandedEndOffset(lineEnd);
+                } else {
+                    if (lastElement.getExpandedEndOffset() < lineStart) {
+                        builder.expandedStartOffset(lineStart);
+                        builder.expandedEndOffset(lineEnd);
+                    } else if (lastElement.getExpandedStartOffset() <= lineStart && lineEnd == lastElement.getExpandedEndOffset()) {
+                        // The same line
+                        sElements.remove(lastElement);
+                        Builder leBuilder = StructureProvider.newBuilder(lastElement.getName(), lastElement.getKind());

Review comment:
       Will be in the next commit. 




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

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

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



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

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


[GitHub] [netbeans] sdedic merged pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
sdedic merged pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525


   


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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r794857772



##########
File path: ide/api.lsp/src/org/netbeans/spi/lsp/StructureProvider.java
##########
@@ -0,0 +1,57 @@
+/*
+ * 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.spi.lsp;
+
+import org.netbeans.api.lsp.StructureElement;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import javax.swing.text.Document;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.spi.editor.mimelookup.MimeLocation;
+
+/**
+ * Interface for building structure of symbols at a given document.
+ * Implementations of the interface should be registered in MimeLookup.
+ * <pre>
+ *
+ *  {@code @MimeRegistration(mimeType = "text/foo", service = StructureProvider.class)
+ *   public class FooStructureProvider implements StructureProvider {
+ *     ...
+ *   }
+ *  }
+ * </pre>
+ *
+ * @author Petr Pisl
+ * @since 1.8
+ */
+
+//@MimeLocation(subfolderName = "StructureProviders")
+public interface StructureProvider {
+    
+    /**
+     * Resolves a structure tree of symbols at the given document.
+     *
+     * @param doc document on which to operate.
+     * @return a list of top level structure elements
+     * 
+     * @since 1.8
+     */
+    @NonNull
+    CompletableFuture<List<? extends StructureElement>> getStructure(@NonNull Document doc);

Review comment:
       When we agree, that we don't need to create subnodes lazily, I will do it in this way.  Thanks for the comments. 




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r794856708



##########
File path: ide/api.lsp/src/org/netbeans/api/lsp/StructureElement.java
##########
@@ -0,0 +1,130 @@
+/*
+ * 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.api.lsp;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * StructureElement is a tree item that shows the structure of the source code.
+ * 
+ * @author Petr Pisl
+ * @since 1.8
+ */
+public interface StructureElement {

Review comment:
       I was trying to create the sub nodes lazily. The tree doesn't appear all at once, only the top two levels. But in the end, the whole tree is sent in response, so from that perspective it doesn't matter. But for the future ....
   
   




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r805839287



##########
File path: ide/csl.api/src/org/netbeans/modules/csl/navigation/GsfStructureProvider.java
##########
@@ -0,0 +1,268 @@
+/*
+ * 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.csl.navigation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+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.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.ParserResult;
+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.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.api.lsp.StructureElement;
+import org.netbeans.modules.csl.api.ElementKind;
+import org.netbeans.modules.csl.api.HtmlFormatter;
+import org.netbeans.modules.csl.api.Modifier;
+import org.netbeans.spi.lsp.StructureProvider;
+
+/**
+ * Implementation of StructureProvider to supply outline view in VSCode
+ * @author Petr Pisl
+ */
+public class GsfStructureProvider implements StructureProvider {
+
+    private static final Logger LOGGER = Logger.getLogger(GsfStructureProvider.class.getName());
+    
+    private static StructureElement.Kind convertKind(ElementKind elementKind) {
+        switch(elementKind) {
+            case ATTRIBUTE: return StructureElement.Kind.Property;
+            case CALL: return StructureElement.Kind.Event;
+            case CLASS: return StructureElement.Kind.Class;
+            case CONSTANT: return StructureElement.Kind.Constant;
+            case CONSTRUCTOR: return StructureElement.Kind.Constructor;
+            case DB: return StructureElement.Kind.File;
+            case ERROR: return StructureElement.Kind.Event;
+            case METHOD: return StructureElement.Kind.Method;
+            case FILE: return StructureElement.Kind.File;
+            case FIELD: return StructureElement.Kind.Field;
+            case MODULE: return StructureElement.Kind.Module;
+            case VARIABLE: return StructureElement.Kind.Variable;
+            case GLOBAL: return StructureElement.Kind.Module;
+            case INTERFACE: return StructureElement.Kind.Interface;
+            case KEYWORD: return StructureElement.Kind.Key;
+            case OTHER: return StructureElement.Kind.Object;
+            case PACKAGE: return StructureElement.Kind.Package;
+            case PARAMETER: return StructureElement.Kind.TypeParameter;
+            case PROPERTY: return StructureElement.Kind.Property;
+            case RULE: return StructureElement.Kind.Event;
+            case TAG: return StructureElement.Kind.Operator;
+            case TEST: return StructureElement.Kind.Function;
+        }
+        return StructureElement.Kind.Object;
+    }
+    
+    private static void  createDetail(StructureItem item, Builder builder) {
+        NoHtmlFormatter formatter = new NoHtmlFormatter();
+        String s = item.getHtml(formatter);
+        s = s.substring(item.getName().length()).trim();
+        if (!s.trim().isEmpty()) {
+            builder.detail(s);
+        }
+    }
+    
+    private static void createTags(StructureItem item, Builder builder) {
+        if (item.getModifiers().contains(Modifier.DEPRECATED)) {
+            builder.addTag(StructureElement.Tag.Deprecated);
+        }
+    }
+    
+    private static void createChildren(Document doc, StructureItem item, Builder builder) {
+        if (!item.isLeaf()) {
+            List <? extends StructureItem> origChildren = item.getNestedItems();
+            if (!origChildren.isEmpty()) {
+                List<StructureElement> children = new ArrayList<>(origChildren.size());
+                convertStructureItems(doc, origChildren, children);
+                builder.children(children);
+            }
+        }
+    }
+    
+    /** A formatter that strips the html elements from the text */
+    static private class NoHtmlFormatter extends HtmlFormatter {
+        StringBuilder sb = new StringBuilder();
+        
+        @Override
+        public void reset() {
+            sb = new StringBuilder();
+        }
+
+        static String stripHtml( String htmlText ) {
+            if( null == htmlText )
+                return null;
+            String res = htmlText.replaceAll( "<[^>]*>", "" ); // NOI18N // NOI18N
+            res = res.replaceAll( "&nbsp;", " " ); // NOI18N // NOI18N
+            res = res.trim();
+            return res;
+        }
+        
+        @Override
+        public void appendHtml(String html) {
+            sb.append(stripHtml(html));
+        }
+
+        @Override
+        public void appendText(String text, int fromInclusive, int toExclusive) {
+            int l = toExclusive - fromInclusive;
+            if (sb.length() + l < maxLength) {
+                sb.append(text.subSequence(fromInclusive, toExclusive));
+            } else {
+                sb.append(text.subSequence(fromInclusive, toExclusive - (l - maxLength)));
+                sb.append("...");   //NOI18N
+            }
+        }
+
+        @Override
+        public void emphasis(boolean start) {
+        }
+
+        @Override
+        public void name(ElementKind kind, boolean start) {
+        }
+
+        @Override
+        public void parameters(boolean start) {
+        }
+
+        @Override
+        public void active(boolean start) {
+        }
+
+        @Override
+        public void type(boolean start) {
+        }
+
+        @Override
+        public void deprecated(boolean start) {
+        }
+
+        @Override
+        public String getText() {
+            return sb.toString();
+        }
+    }
+    
+    @Override
+    public CompletableFuture<List<StructureElement>> getStructure(Document doc) {
+        final List<StructureElement> sElements = new ArrayList<>();
+        try {
+            ParserManager.parse(Collections.singletonList(Source.create(doc)), new UserTask() {
+                @Override
+                public void run(ResultIterator resultIterator) throws Exception {
+                    Parser.Result result = resultIterator.getParserResult(-1);
+                    if(result instanceof ParserResult) {
+                        ParserResult parserResult = (ParserResult) result;
+                        Language language = LanguageRegistry.getInstance().getLanguageByMimeType(resultIterator.getSnapshot().getMimeType());
+                        if (language != null) {
+                            StructureScanner scanner = language.getStructure();
+                            if (scanner != null) {
+                                List<? extends StructureItem> items = scanner.scan(parserResult);
+                                convertStructureItems(doc, items, sElements);
+                            }
+                        }
+                    }
+                }
+
+            });
+            return CompletableFuture.completedFuture(sElements);
+        } catch (ParseException ex) {
+            LOGGER.log(Level.FINE, null, ex);
+            return CompletableFuture.completedFuture(null);
+        }
+    }
+    
+    private static void convertStructureItems(Document doc, List<? extends StructureItem> items, List<StructureElement> sElements) {
+        StructureElement lastElement = null;
+        if (doc instanceof LineDocument) {
+            //  if it's line document, we can set the enclosing range for whole line
+            LineDocument ldoc = (LineDocument)doc;
+            for (StructureItem item : items) {
+                int startOffset = (int)item.getPosition();
+                int lineStart = startOffset;
+                int lineEnd = (int)item.getEndPosition();
+                Builder builder = StructureProvider.newBuilder(item.getName(), convertKind(item.getKind()));
+                builder.selectionStartOffset(startOffset).selectionEndOffset(lineEnd);
+                createDetail(item, builder);
+                createTags(item, builder);
+
+                try {
+                    String prefix = doc.getText(lineStart, startOffset);

Review comment:
       This is useful for example for yaml files like:
   ```
   martin:
     name: Martin D'vloper
   |  job: Developer
     skill: Elite
   ```
   The ui will select the `job` item, not `martin` structure (that will be selected if the job expanded offsets will be the sema lake selected offsets. 




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#issuecomment-1032685520


   > There are no tests yet, I need to write them.
   
   There is now test for the api. 


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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r805836410



##########
File path: ide/csl.api/src/org/netbeans/modules/csl/navigation/GsfStructureProvider.java
##########
@@ -0,0 +1,268 @@
+/*
+ * 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.csl.navigation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+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.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.ParserResult;
+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.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.api.lsp.StructureElement;
+import org.netbeans.modules.csl.api.ElementKind;
+import org.netbeans.modules.csl.api.HtmlFormatter;
+import org.netbeans.modules.csl.api.Modifier;
+import org.netbeans.spi.lsp.StructureProvider;
+
+/**
+ * Implementation of StructureProvider to supply outline view in VSCode
+ * @author Petr Pisl
+ */
+public class GsfStructureProvider implements StructureProvider {
+
+    private static final Logger LOGGER = Logger.getLogger(GsfStructureProvider.class.getName());
+    
+    private static StructureElement.Kind convertKind(ElementKind elementKind) {
+        switch(elementKind) {
+            case ATTRIBUTE: return StructureElement.Kind.Property;
+            case CALL: return StructureElement.Kind.Event;
+            case CLASS: return StructureElement.Kind.Class;
+            case CONSTANT: return StructureElement.Kind.Constant;
+            case CONSTRUCTOR: return StructureElement.Kind.Constructor;
+            case DB: return StructureElement.Kind.File;
+            case ERROR: return StructureElement.Kind.Event;
+            case METHOD: return StructureElement.Kind.Method;
+            case FILE: return StructureElement.Kind.File;
+            case FIELD: return StructureElement.Kind.Field;
+            case MODULE: return StructureElement.Kind.Module;
+            case VARIABLE: return StructureElement.Kind.Variable;
+            case GLOBAL: return StructureElement.Kind.Module;
+            case INTERFACE: return StructureElement.Kind.Interface;
+            case KEYWORD: return StructureElement.Kind.Key;
+            case OTHER: return StructureElement.Kind.Object;
+            case PACKAGE: return StructureElement.Kind.Package;
+            case PARAMETER: return StructureElement.Kind.TypeParameter;
+            case PROPERTY: return StructureElement.Kind.Property;
+            case RULE: return StructureElement.Kind.Event;
+            case TAG: return StructureElement.Kind.Operator;
+            case TEST: return StructureElement.Kind.Function;
+        }
+        return StructureElement.Kind.Object;
+    }
+    
+    private static void  createDetail(StructureItem item, Builder builder) {
+        NoHtmlFormatter formatter = new NoHtmlFormatter();
+        String s = item.getHtml(formatter);
+        s = s.substring(item.getName().length()).trim();
+        if (!s.trim().isEmpty()) {
+            builder.detail(s);
+        }
+    }
+    
+    private static void createTags(StructureItem item, Builder builder) {
+        if (item.getModifiers().contains(Modifier.DEPRECATED)) {
+            builder.addTag(StructureElement.Tag.Deprecated);
+        }
+    }
+    
+    private static void createChildren(Document doc, StructureItem item, Builder builder) {
+        if (!item.isLeaf()) {
+            List <? extends StructureItem> origChildren = item.getNestedItems();
+            if (!origChildren.isEmpty()) {
+                List<StructureElement> children = new ArrayList<>(origChildren.size());
+                convertStructureItems(doc, origChildren, children);
+                builder.children(children);
+            }
+        }
+    }
+    
+    /** A formatter that strips the html elements from the text */
+    static private class NoHtmlFormatter extends HtmlFormatter {
+        StringBuilder sb = new StringBuilder();
+        
+        @Override
+        public void reset() {
+            sb = new StringBuilder();
+        }
+
+        static String stripHtml( String htmlText ) {
+            if( null == htmlText )
+                return null;
+            String res = htmlText.replaceAll( "<[^>]*>", "" ); // NOI18N // NOI18N
+            res = res.replaceAll( "&nbsp;", " " ); // NOI18N // NOI18N
+            res = res.trim();
+            return res;
+        }
+        
+        @Override
+        public void appendHtml(String html) {
+            sb.append(stripHtml(html));
+        }
+
+        @Override
+        public void appendText(String text, int fromInclusive, int toExclusive) {
+            int l = toExclusive - fromInclusive;
+            if (sb.length() + l < maxLength) {
+                sb.append(text.subSequence(fromInclusive, toExclusive));
+            } else {
+                sb.append(text.subSequence(fromInclusive, toExclusive - (l - maxLength)));
+                sb.append("...");   //NOI18N
+            }
+        }
+
+        @Override
+        public void emphasis(boolean start) {
+        }
+
+        @Override
+        public void name(ElementKind kind, boolean start) {
+        }
+
+        @Override
+        public void parameters(boolean start) {
+        }
+
+        @Override
+        public void active(boolean start) {
+        }
+
+        @Override
+        public void type(boolean start) {
+        }
+
+        @Override
+        public void deprecated(boolean start) {
+        }
+
+        @Override
+        public String getText() {
+            return sb.toString();
+        }
+    }
+    
+    @Override
+    public CompletableFuture<List<StructureElement>> getStructure(Document doc) {
+        final List<StructureElement> sElements = new ArrayList<>();
+        try {
+            ParserManager.parse(Collections.singletonList(Source.create(doc)), new UserTask() {
+                @Override
+                public void run(ResultIterator resultIterator) throws Exception {
+                    Parser.Result result = resultIterator.getParserResult(-1);
+                    if(result instanceof ParserResult) {
+                        ParserResult parserResult = (ParserResult) result;
+                        Language language = LanguageRegistry.getInstance().getLanguageByMimeType(resultIterator.getSnapshot().getMimeType());
+                        if (language != null) {
+                            StructureScanner scanner = language.getStructure();
+                            if (scanner != null) {
+                                List<? extends StructureItem> items = scanner.scan(parserResult);
+                                convertStructureItems(doc, items, sElements);
+                            }
+                        }
+                    }
+                }
+
+            });
+            return CompletableFuture.completedFuture(sElements);
+        } catch (ParseException ex) {
+            LOGGER.log(Level.FINE, null, ex);
+            return CompletableFuture.completedFuture(null);
+        }
+    }
+    
+    private static void convertStructureItems(Document doc, List<? extends StructureItem> items, List<StructureElement> sElements) {
+        StructureElement lastElement = null;
+        if (doc instanceof LineDocument) {
+            //  if it's line document, we can set the enclosing range for whole line
+            LineDocument ldoc = (LineDocument)doc;
+            for (StructureItem item : items) {
+                int startOffset = (int)item.getPosition();
+                int lineStart = startOffset;
+                int lineEnd = (int)item.getEndPosition();
+                Builder builder = StructureProvider.newBuilder(item.getName(), convertKind(item.getKind()));
+                builder.selectionStartOffset(startOffset).selectionEndOffset(lineEnd);
+                createDetail(item, builder);
+                createTags(item, builder);
+
+                try {
+                    String prefix = doc.getText(lineStart, startOffset);

Review comment:
       The code i a little bit misleading. I have change it little bit. I will try to explain the logic:
   ```
   class A {
    |   def methodC {} {
    }
   }
   ```
   The `|` marks text cursor, in this case the logic counts the expanded offset from the beginning of the line, becase on the line starts `methodC` definition. So in this case the methodC element is selected. But when you have something like:
   ```
   class A{
       int field1; |int field2
   }
   ```
   the start of the expanded offset will be the same as selected offset of the element `field2` and not from the begining of the line.




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r806083325



##########
File path: java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java
##########
@@ -813,97 +814,61 @@ protected void process(CompilationInfo arg0, Document arg1, SchedulerEvent arg2)
     @Override
     public CompletableFuture<List<Either<SymbolInformation, DocumentSymbol>>> documentSymbol(DocumentSymbolParams params) {
         return server.openedProjects().thenCompose(projects -> {
-            JavaSource js = getJavaSource(params.getTextDocument().getUri());
-            if (js == null) {
+            List<Either<SymbolInformation, DocumentSymbol>> result = new ArrayList<>();
+        
+            String uri = params.getTextDocument().getUri();
+            FileObject file = fromURI(uri);
+            Document doc = server.getOpenedDocuments().getDocument(uri);
+            if (file == null || !(doc instanceof LineDocument)) {
                 return CompletableFuture.completedFuture(Collections.emptyList());
             }
-            List<Either<SymbolInformation, DocumentSymbol>> result = new ArrayList<>();
-            try {
-                js.runUserActionTask(cc -> {
-                    cc.toPhase(JavaSource.Phase.RESOLVED);
-                    Trees trees = cc.getTrees();
-                    CompilationUnitTree cu = cc.getCompilationUnit();
-                    if (cu.getPackage() != null) {
-                        TreePath tp = trees.getPath(cu, cu.getPackage());
-                        Element el = trees.getElement(tp);
-                        if (el != null && el.getKind() == ElementKind.PACKAGE) {
-                            String name = Utils.label(cc, el, true);
-                            SymbolKind kind = Utils.elementKind2SymbolKind(el.getKind());
-                            Range range = Utils.treeRange(cc, tp.getLeaf());
-                            result.add(Either.forRight(new DocumentSymbol(name, kind, range, range)));
-                        }
-                    }
-                    for (Element tel : cc.getTopLevelElements()) {
-                        DocumentSymbol ds = element2DocumentSymbol(cc, tel);
-                        if (ds != null)
+            StructureProvider structureProvider = MimeLookup.getLookup(DocumentUtilities.getMimeType(doc)).lookup(StructureProvider.class);
+            if (structureProvider != null) {
+                return structureProvider.getStructure(doc).thenApply(structureElements -> {

Review comment:
       I have put it into the Background taks.




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

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

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



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

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


[GitHub] [netbeans] JaroslavTulach commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
JaroslavTulach commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r805115819



##########
File path: ide/api.lsp/src/org/netbeans/api/lsp/StructureElement.java
##########
@@ -0,0 +1,191 @@
+/*
+ * 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.api.lsp;
+
+import java.util.List;
+import java.util.Set;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.modules.lsp.StructureElementAccessor;
+
+/**
+ * StructureElement is a tree item that shows the structure of the source code.
+ *
+ * @author Petr Pisl
+ * @since 1.8
+ */
+public final class StructureElement {
+
+    static {
+        StructureElementAccessor.setDefault(new StructureElementAccessor() {
+            @Override
+            public StructureElement createStructureElement(String name, String detail, int selectionStartOffset, int selectionEndOffset, int expandedStartOffset, int expandedEndOffset, Kind kind, Set<Tag> tags, List<StructureElement> children) {
+                return new StructureElement(name, detail, selectionStartOffset, selectionEndOffset, expandedStartOffset, expandedEndOffset, kind, tags, children);
+            }
+        });
+    }
+
+    private final String name;
+    private final String detail;
+    private final int selectionStartOffset;

Review comment:
       Do we want the _structure_ to represent read-only snapshot and be always re-created from scratch? Or do we want the _structure_ to be updated?
   
   I believe we strive for the first approach. As such making the fields `final` more properly represents the _snapshot_ nature of the _structure_. Implementations can of course maintain `javax.swing.text.Position` internally.




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

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

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



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

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


[GitHub] [netbeans] JaroslavTulach commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
JaroslavTulach commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r794659709



##########
File path: ide/api.lsp/src/org/netbeans/api/lsp/StructureElement.java
##########
@@ -0,0 +1,130 @@
+/*
+ * 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.api.lsp;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * StructureElement is a tree item that shows the structure of the source code.
+ * 
+ * @author Petr Pisl
+ * @since 1.8
+ */
+public interface StructureElement {
+   
+    /**
+     * Kind of the structure element. 
+     */
+    public static enum Kind {
+        File,
+	Module,

Review comment:
       Strange formatting. Space vs. tab? Using 8 spaces would be more consistent.

##########
File path: ide/api.lsp/src/org/netbeans/spi/lsp/StructureProvider.java
##########
@@ -0,0 +1,57 @@
+/*
+ * 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.spi.lsp;
+
+import org.netbeans.api.lsp.StructureElement;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import javax.swing.text.Document;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.spi.editor.mimelookup.MimeLocation;
+
+/**
+ * Interface for building structure of symbols at a given document.
+ * Implementations of the interface should be registered in MimeLookup.
+ * <pre>
+ *
+ *  {@code @MimeRegistration(mimeType = "text/foo", service = StructureProvider.class)
+ *   public class FooStructureProvider implements StructureProvider {
+ *     ...
+ *   }
+ *  }
+ * </pre>
+ *
+ * @author Petr Pisl
+ * @since 1.8
+ */
+
+//@MimeLocation(subfolderName = "StructureProviders")
+public interface StructureProvider {
+    
+    /**
+     * Resolves a structure tree of symbols at the given document.
+     *
+     * @param doc document on which to operate.
+     * @return a list of top level structure elements
+     * 
+     * @since 1.8
+     */
+    @NonNull
+    CompletableFuture<List<? extends StructureElement>> getStructure(@NonNull Document doc);

Review comment:
       You need a builder like [CompletionCollector.Builder](https://bits.netbeans.org/dev/javadoc/org-netbeans-api-lsp/org/netbeans/spi/lsp/CompletionCollector.Builder.html).

##########
File path: ide/api.lsp/src/org/netbeans/api/lsp/StructureElement.java
##########
@@ -0,0 +1,130 @@
+/*
+ * 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.api.lsp;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * StructureElement is a tree item that shows the structure of the source code.
+ * 
+ * @author Petr Pisl
+ * @since 1.8
+ */
+public interface StructureElement {

Review comment:
       How do you want to evolve this type? You may need to add new getters in the future.
   
   I't be better to follow the pattern of [Completion](https://bits.netbeans.org/dev/javadoc/org-netbeans-api-lsp/org/netbeans/api/lsp/Completion.html) in API and 
   [CompletionCollector](https://bits.netbeans.org/dev/javadoc/org-netbeans-api-lsp/org/netbeans/spi/lsp/CompletionCollector.html) in SPI.
   
   Turn `StructureElement` into `final class`.

##########
File path: java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java
##########
@@ -813,97 +814,61 @@ protected void process(CompilationInfo arg0, Document arg1, SchedulerEvent arg2)
     @Override
     public CompletableFuture<List<Either<SymbolInformation, DocumentSymbol>>> documentSymbol(DocumentSymbolParams params) {
         return server.openedProjects().thenCompose(projects -> {
-            JavaSource js = getJavaSource(params.getTextDocument().getUri());
-            if (js == null) {
+            List<Either<SymbolInformation, DocumentSymbol>> result = new ArrayList<>();
+        
+            String uri = params.getTextDocument().getUri();
+            FileObject file = fromURI(uri);
+            Document doc = server.getOpenedDocuments().getDocument(uri);
+            if (file == null || !(doc instanceof LineDocument)) {
                 return CompletableFuture.completedFuture(Collections.emptyList());
             }
-            List<Either<SymbolInformation, DocumentSymbol>> result = new ArrayList<>();
-            try {
-                js.runUserActionTask(cc -> {

Review comment:
       Removing this special Java code is a great step at the right direction. Thanks.




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r805839287



##########
File path: ide/csl.api/src/org/netbeans/modules/csl/navigation/GsfStructureProvider.java
##########
@@ -0,0 +1,268 @@
+/*
+ * 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.csl.navigation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+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.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.ParserResult;
+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.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.api.lsp.StructureElement;
+import org.netbeans.modules.csl.api.ElementKind;
+import org.netbeans.modules.csl.api.HtmlFormatter;
+import org.netbeans.modules.csl.api.Modifier;
+import org.netbeans.spi.lsp.StructureProvider;
+
+/**
+ * Implementation of StructureProvider to supply outline view in VSCode
+ * @author Petr Pisl
+ */
+public class GsfStructureProvider implements StructureProvider {
+
+    private static final Logger LOGGER = Logger.getLogger(GsfStructureProvider.class.getName());
+    
+    private static StructureElement.Kind convertKind(ElementKind elementKind) {
+        switch(elementKind) {
+            case ATTRIBUTE: return StructureElement.Kind.Property;
+            case CALL: return StructureElement.Kind.Event;
+            case CLASS: return StructureElement.Kind.Class;
+            case CONSTANT: return StructureElement.Kind.Constant;
+            case CONSTRUCTOR: return StructureElement.Kind.Constructor;
+            case DB: return StructureElement.Kind.File;
+            case ERROR: return StructureElement.Kind.Event;
+            case METHOD: return StructureElement.Kind.Method;
+            case FILE: return StructureElement.Kind.File;
+            case FIELD: return StructureElement.Kind.Field;
+            case MODULE: return StructureElement.Kind.Module;
+            case VARIABLE: return StructureElement.Kind.Variable;
+            case GLOBAL: return StructureElement.Kind.Module;
+            case INTERFACE: return StructureElement.Kind.Interface;
+            case KEYWORD: return StructureElement.Kind.Key;
+            case OTHER: return StructureElement.Kind.Object;
+            case PACKAGE: return StructureElement.Kind.Package;
+            case PARAMETER: return StructureElement.Kind.TypeParameter;
+            case PROPERTY: return StructureElement.Kind.Property;
+            case RULE: return StructureElement.Kind.Event;
+            case TAG: return StructureElement.Kind.Operator;
+            case TEST: return StructureElement.Kind.Function;
+        }
+        return StructureElement.Kind.Object;
+    }
+    
+    private static void  createDetail(StructureItem item, Builder builder) {
+        NoHtmlFormatter formatter = new NoHtmlFormatter();
+        String s = item.getHtml(formatter);
+        s = s.substring(item.getName().length()).trim();
+        if (!s.trim().isEmpty()) {
+            builder.detail(s);
+        }
+    }
+    
+    private static void createTags(StructureItem item, Builder builder) {
+        if (item.getModifiers().contains(Modifier.DEPRECATED)) {
+            builder.addTag(StructureElement.Tag.Deprecated);
+        }
+    }
+    
+    private static void createChildren(Document doc, StructureItem item, Builder builder) {
+        if (!item.isLeaf()) {
+            List <? extends StructureItem> origChildren = item.getNestedItems();
+            if (!origChildren.isEmpty()) {
+                List<StructureElement> children = new ArrayList<>(origChildren.size());
+                convertStructureItems(doc, origChildren, children);
+                builder.children(children);
+            }
+        }
+    }
+    
+    /** A formatter that strips the html elements from the text */
+    static private class NoHtmlFormatter extends HtmlFormatter {
+        StringBuilder sb = new StringBuilder();
+        
+        @Override
+        public void reset() {
+            sb = new StringBuilder();
+        }
+
+        static String stripHtml( String htmlText ) {
+            if( null == htmlText )
+                return null;
+            String res = htmlText.replaceAll( "<[^>]*>", "" ); // NOI18N // NOI18N
+            res = res.replaceAll( "&nbsp;", " " ); // NOI18N // NOI18N
+            res = res.trim();
+            return res;
+        }
+        
+        @Override
+        public void appendHtml(String html) {
+            sb.append(stripHtml(html));
+        }
+
+        @Override
+        public void appendText(String text, int fromInclusive, int toExclusive) {
+            int l = toExclusive - fromInclusive;
+            if (sb.length() + l < maxLength) {
+                sb.append(text.subSequence(fromInclusive, toExclusive));
+            } else {
+                sb.append(text.subSequence(fromInclusive, toExclusive - (l - maxLength)));
+                sb.append("...");   //NOI18N
+            }
+        }
+
+        @Override
+        public void emphasis(boolean start) {
+        }
+
+        @Override
+        public void name(ElementKind kind, boolean start) {
+        }
+
+        @Override
+        public void parameters(boolean start) {
+        }
+
+        @Override
+        public void active(boolean start) {
+        }
+
+        @Override
+        public void type(boolean start) {
+        }
+
+        @Override
+        public void deprecated(boolean start) {
+        }
+
+        @Override
+        public String getText() {
+            return sb.toString();
+        }
+    }
+    
+    @Override
+    public CompletableFuture<List<StructureElement>> getStructure(Document doc) {
+        final List<StructureElement> sElements = new ArrayList<>();
+        try {
+            ParserManager.parse(Collections.singletonList(Source.create(doc)), new UserTask() {
+                @Override
+                public void run(ResultIterator resultIterator) throws Exception {
+                    Parser.Result result = resultIterator.getParserResult(-1);
+                    if(result instanceof ParserResult) {
+                        ParserResult parserResult = (ParserResult) result;
+                        Language language = LanguageRegistry.getInstance().getLanguageByMimeType(resultIterator.getSnapshot().getMimeType());
+                        if (language != null) {
+                            StructureScanner scanner = language.getStructure();
+                            if (scanner != null) {
+                                List<? extends StructureItem> items = scanner.scan(parserResult);
+                                convertStructureItems(doc, items, sElements);
+                            }
+                        }
+                    }
+                }
+
+            });
+            return CompletableFuture.completedFuture(sElements);
+        } catch (ParseException ex) {
+            LOGGER.log(Level.FINE, null, ex);
+            return CompletableFuture.completedFuture(null);
+        }
+    }
+    
+    private static void convertStructureItems(Document doc, List<? extends StructureItem> items, List<StructureElement> sElements) {
+        StructureElement lastElement = null;
+        if (doc instanceof LineDocument) {
+            //  if it's line document, we can set the enclosing range for whole line
+            LineDocument ldoc = (LineDocument)doc;
+            for (StructureItem item : items) {
+                int startOffset = (int)item.getPosition();
+                int lineStart = startOffset;
+                int lineEnd = (int)item.getEndPosition();
+                Builder builder = StructureProvider.newBuilder(item.getName(), convertKind(item.getKind()));
+                builder.selectionStartOffset(startOffset).selectionEndOffset(lineEnd);
+                createDetail(item, builder);
+                createTags(item, builder);
+
+                try {
+                    String prefix = doc.getText(lineStart, startOffset);

Review comment:
       This is useful for example for yaml files like:
   ```
   martin:
     name: Martin D'vloper
   |  job: Developer
     skill: Elite
   ```
   The ui will select the `job` item, not `martin` structure (that will be selected if the job expanded offsets will be the seme lake selected offsets. 




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

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

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



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

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


[GitHub] [netbeans] sdedic commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
sdedic commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r804709345



##########
File path: ide/csl.api/src/org/netbeans/modules/csl/navigation/GsfStructureProvider.java
##########
@@ -0,0 +1,268 @@
+/*
+ * 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.csl.navigation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+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.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.ParserResult;
+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.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.api.lsp.StructureElement;
+import org.netbeans.modules.csl.api.ElementKind;
+import org.netbeans.modules.csl.api.HtmlFormatter;
+import org.netbeans.modules.csl.api.Modifier;
+import org.netbeans.spi.lsp.StructureProvider;
+
+/**
+ * Implementation of StructureProvider to supply outline view in VSCode
+ * @author Petr Pisl
+ */
+public class GsfStructureProvider implements StructureProvider {
+
+    private static final Logger LOGGER = Logger.getLogger(GsfStructureProvider.class.getName());
+    
+    private static StructureElement.Kind convertKind(ElementKind elementKind) {
+        switch(elementKind) {
+            case ATTRIBUTE: return StructureElement.Kind.Property;
+            case CALL: return StructureElement.Kind.Event;
+            case CLASS: return StructureElement.Kind.Class;
+            case CONSTANT: return StructureElement.Kind.Constant;
+            case CONSTRUCTOR: return StructureElement.Kind.Constructor;
+            case DB: return StructureElement.Kind.File;
+            case ERROR: return StructureElement.Kind.Event;
+            case METHOD: return StructureElement.Kind.Method;
+            case FILE: return StructureElement.Kind.File;
+            case FIELD: return StructureElement.Kind.Field;
+            case MODULE: return StructureElement.Kind.Module;
+            case VARIABLE: return StructureElement.Kind.Variable;
+            case GLOBAL: return StructureElement.Kind.Module;
+            case INTERFACE: return StructureElement.Kind.Interface;
+            case KEYWORD: return StructureElement.Kind.Key;
+            case OTHER: return StructureElement.Kind.Object;
+            case PACKAGE: return StructureElement.Kind.Package;
+            case PARAMETER: return StructureElement.Kind.TypeParameter;
+            case PROPERTY: return StructureElement.Kind.Property;
+            case RULE: return StructureElement.Kind.Event;
+            case TAG: return StructureElement.Kind.Operator;
+            case TEST: return StructureElement.Kind.Function;
+        }
+        return StructureElement.Kind.Object;
+    }
+    
+    private static void  createDetail(StructureItem item, Builder builder) {
+        NoHtmlFormatter formatter = new NoHtmlFormatter();
+        String s = item.getHtml(formatter);
+        s = s.substring(item.getName().length()).trim();
+        if (!s.trim().isEmpty()) {
+            builder.detail(s);
+        }
+    }
+    
+    private static void createTags(StructureItem item, Builder builder) {
+        if (item.getModifiers().contains(Modifier.DEPRECATED)) {
+            builder.addTag(StructureElement.Tag.Deprecated);
+        }
+    }
+    
+    private static void createChildren(Document doc, StructureItem item, Builder builder) {
+        if (!item.isLeaf()) {
+            List <? extends StructureItem> origChildren = item.getNestedItems();
+            if (!origChildren.isEmpty()) {
+                List<StructureElement> children = new ArrayList<>(origChildren.size());
+                convertStructureItems(doc, origChildren, children);
+                builder.children(children);
+            }
+        }
+    }
+    
+    /** A formatter that strips the html elements from the text */
+    static private class NoHtmlFormatter extends HtmlFormatter {
+        StringBuilder sb = new StringBuilder();
+        
+        @Override
+        public void reset() {
+            sb = new StringBuilder();
+        }
+
+        static String stripHtml( String htmlText ) {
+            if( null == htmlText )
+                return null;
+            String res = htmlText.replaceAll( "<[^>]*>", "" ); // NOI18N // NOI18N
+            res = res.replaceAll( "&nbsp;", " " ); // NOI18N // NOI18N
+            res = res.trim();
+            return res;
+        }
+        
+        @Override
+        public void appendHtml(String html) {
+            sb.append(stripHtml(html));
+        }
+
+        @Override
+        public void appendText(String text, int fromInclusive, int toExclusive) {
+            int l = toExclusive - fromInclusive;
+            if (sb.length() + l < maxLength) {
+                sb.append(text.subSequence(fromInclusive, toExclusive));
+            } else {
+                sb.append(text.subSequence(fromInclusive, toExclusive - (l - maxLength)));
+                sb.append("...");   //NOI18N
+            }
+        }
+
+        @Override
+        public void emphasis(boolean start) {
+        }
+
+        @Override
+        public void name(ElementKind kind, boolean start) {
+        }
+
+        @Override
+        public void parameters(boolean start) {
+        }
+
+        @Override
+        public void active(boolean start) {
+        }
+
+        @Override
+        public void type(boolean start) {
+        }
+
+        @Override
+        public void deprecated(boolean start) {
+        }
+
+        @Override
+        public String getText() {
+            return sb.toString();
+        }
+    }
+    
+    @Override
+    public CompletableFuture<List<StructureElement>> getStructure(Document doc) {
+        final List<StructureElement> sElements = new ArrayList<>();
+        try {
+            ParserManager.parse(Collections.singletonList(Source.create(doc)), new UserTask() {
+                @Override
+                public void run(ResultIterator resultIterator) throws Exception {
+                    Parser.Result result = resultIterator.getParserResult(-1);
+                    if(result instanceof ParserResult) {
+                        ParserResult parserResult = (ParserResult) result;
+                        Language language = LanguageRegistry.getInstance().getLanguageByMimeType(resultIterator.getSnapshot().getMimeType());
+                        if (language != null) {
+                            StructureScanner scanner = language.getStructure();
+                            if (scanner != null) {
+                                List<? extends StructureItem> items = scanner.scan(parserResult);
+                                convertStructureItems(doc, items, sElements);
+                            }
+                        }
+                    }
+                }
+
+            });
+            return CompletableFuture.completedFuture(sElements);
+        } catch (ParseException ex) {
+            LOGGER.log(Level.FINE, null, ex);
+            return CompletableFuture.completedFuture(null);
+        }
+    }
+    
+    private static void convertStructureItems(Document doc, List<? extends StructureItem> items, List<StructureElement> sElements) {
+        StructureElement lastElement = null;
+        if (doc instanceof LineDocument) {
+            //  if it's line document, we can set the enclosing range for whole line
+            LineDocument ldoc = (LineDocument)doc;
+            for (StructureItem item : items) {
+                int startOffset = (int)item.getPosition();
+                int lineStart = startOffset;
+                int lineEnd = (int)item.getEndPosition();
+                Builder builder = StructureProvider.newBuilder(item.getName(), convertKind(item.getKind()));
+                builder.selectionStartOffset(startOffset).selectionEndOffset(lineEnd);
+                createDetail(item, builder);
+                createTags(item, builder);
+
+                try {
+                    String prefix = doc.getText(lineStart, startOffset);
+                    lineStart = LineDocumentUtils.getLineStart(ldoc, lineStart);
+                    if (prefix.trim().isEmpty()) {
+                        lineEnd = LineDocumentUtils.getLineEnd(ldoc, lineEnd);
+                    } else {
+                        lineStart = startOffset;
+                    }
+                    
+                } catch (BadLocationException ex) {
+                    lineStart = (int)item.getPosition();
+                    lineEnd = (int)item.getEndPosition();
+                }
+                if (lastElement == null) {
+                    builder.expandedStartOffset(lineStart);
+                    builder.expandedEndOffset(lineEnd);
+                } else {
+                    if (lastElement.getExpandedEndOffset() < lineStart) {
+                        builder.expandedStartOffset(lineStart);
+                        builder.expandedEndOffset(lineEnd);
+                    } else if (lastElement.getExpandedStartOffset() <= lineStart && lineEnd == lastElement.getExpandedEndOffset()) {
+                        // The same line
+                        sElements.remove(lastElement);
+                        Builder leBuilder = StructureProvider.newBuilder(lastElement.getName(), lastElement.getKind());

Review comment:
       What about adding `Builder StructureProvider.copy(StructureElement from)` ? All the settings can be copied, the caller will just call builder methods for changes.

##########
File path: ide/csl.api/src/org/netbeans/modules/csl/navigation/GsfStructureProvider.java
##########
@@ -0,0 +1,268 @@
+/*
+ * 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.csl.navigation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+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.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.ParserResult;
+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.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.api.lsp.StructureElement;
+import org.netbeans.modules.csl.api.ElementKind;
+import org.netbeans.modules.csl.api.HtmlFormatter;
+import org.netbeans.modules.csl.api.Modifier;
+import org.netbeans.spi.lsp.StructureProvider;
+
+/**
+ * Implementation of StructureProvider to supply outline view in VSCode
+ * @author Petr Pisl
+ */
+public class GsfStructureProvider implements StructureProvider {
+
+    private static final Logger LOGGER = Logger.getLogger(GsfStructureProvider.class.getName());
+    
+    private static StructureElement.Kind convertKind(ElementKind elementKind) {
+        switch(elementKind) {
+            case ATTRIBUTE: return StructureElement.Kind.Property;
+            case CALL: return StructureElement.Kind.Event;
+            case CLASS: return StructureElement.Kind.Class;
+            case CONSTANT: return StructureElement.Kind.Constant;
+            case CONSTRUCTOR: return StructureElement.Kind.Constructor;
+            case DB: return StructureElement.Kind.File;
+            case ERROR: return StructureElement.Kind.Event;
+            case METHOD: return StructureElement.Kind.Method;
+            case FILE: return StructureElement.Kind.File;
+            case FIELD: return StructureElement.Kind.Field;
+            case MODULE: return StructureElement.Kind.Module;
+            case VARIABLE: return StructureElement.Kind.Variable;
+            case GLOBAL: return StructureElement.Kind.Module;
+            case INTERFACE: return StructureElement.Kind.Interface;
+            case KEYWORD: return StructureElement.Kind.Key;
+            case OTHER: return StructureElement.Kind.Object;
+            case PACKAGE: return StructureElement.Kind.Package;
+            case PARAMETER: return StructureElement.Kind.TypeParameter;
+            case PROPERTY: return StructureElement.Kind.Property;
+            case RULE: return StructureElement.Kind.Event;
+            case TAG: return StructureElement.Kind.Operator;
+            case TEST: return StructureElement.Kind.Function;
+        }
+        return StructureElement.Kind.Object;
+    }
+    
+    private static void  createDetail(StructureItem item, Builder builder) {
+        NoHtmlFormatter formatter = new NoHtmlFormatter();
+        String s = item.getHtml(formatter);
+        s = s.substring(item.getName().length()).trim();
+        if (!s.trim().isEmpty()) {
+            builder.detail(s);
+        }
+    }
+    
+    private static void createTags(StructureItem item, Builder builder) {
+        if (item.getModifiers().contains(Modifier.DEPRECATED)) {
+            builder.addTag(StructureElement.Tag.Deprecated);
+        }
+    }
+    
+    private static void createChildren(Document doc, StructureItem item, Builder builder) {
+        if (!item.isLeaf()) {
+            List <? extends StructureItem> origChildren = item.getNestedItems();
+            if (!origChildren.isEmpty()) {
+                List<StructureElement> children = new ArrayList<>(origChildren.size());
+                convertStructureItems(doc, origChildren, children);
+                builder.children(children);
+            }
+        }
+    }
+    
+    /** A formatter that strips the html elements from the text */
+    static private class NoHtmlFormatter extends HtmlFormatter {
+        StringBuilder sb = new StringBuilder();
+        
+        @Override
+        public void reset() {
+            sb = new StringBuilder();
+        }
+
+        static String stripHtml( String htmlText ) {
+            if( null == htmlText )
+                return null;
+            String res = htmlText.replaceAll( "<[^>]*>", "" ); // NOI18N // NOI18N
+            res = res.replaceAll( "&nbsp;", " " ); // NOI18N // NOI18N
+            res = res.trim();
+            return res;
+        }
+        
+        @Override
+        public void appendHtml(String html) {
+            sb.append(stripHtml(html));
+        }
+
+        @Override
+        public void appendText(String text, int fromInclusive, int toExclusive) {
+            int l = toExclusive - fromInclusive;
+            if (sb.length() + l < maxLength) {
+                sb.append(text.subSequence(fromInclusive, toExclusive));
+            } else {
+                sb.append(text.subSequence(fromInclusive, toExclusive - (l - maxLength)));
+                sb.append("...");   //NOI18N
+            }
+        }
+
+        @Override
+        public void emphasis(boolean start) {
+        }
+
+        @Override
+        public void name(ElementKind kind, boolean start) {
+        }
+
+        @Override
+        public void parameters(boolean start) {
+        }
+
+        @Override
+        public void active(boolean start) {
+        }
+
+        @Override
+        public void type(boolean start) {
+        }
+
+        @Override
+        public void deprecated(boolean start) {
+        }
+
+        @Override
+        public String getText() {
+            return sb.toString();
+        }
+    }
+    
+    @Override
+    public CompletableFuture<List<StructureElement>> getStructure(Document doc) {
+        final List<StructureElement> sElements = new ArrayList<>();
+        try {
+            ParserManager.parse(Collections.singletonList(Source.create(doc)), new UserTask() {
+                @Override
+                public void run(ResultIterator resultIterator) throws Exception {
+                    Parser.Result result = resultIterator.getParserResult(-1);
+                    if(result instanceof ParserResult) {
+                        ParserResult parserResult = (ParserResult) result;
+                        Language language = LanguageRegistry.getInstance().getLanguageByMimeType(resultIterator.getSnapshot().getMimeType());
+                        if (language != null) {
+                            StructureScanner scanner = language.getStructure();
+                            if (scanner != null) {
+                                List<? extends StructureItem> items = scanner.scan(parserResult);
+                                convertStructureItems(doc, items, sElements);
+                            }
+                        }
+                    }
+                }
+
+            });
+            return CompletableFuture.completedFuture(sElements);
+        } catch (ParseException ex) {
+            LOGGER.log(Level.FINE, null, ex);
+            return CompletableFuture.completedFuture(null);
+        }
+    }
+    
+    private static void convertStructureItems(Document doc, List<? extends StructureItem> items, List<StructureElement> sElements) {
+        StructureElement lastElement = null;
+        if (doc instanceof LineDocument) {
+            //  if it's line document, we can set the enclosing range for whole line
+            LineDocument ldoc = (LineDocument)doc;
+            for (StructureItem item : items) {
+                int startOffset = (int)item.getPosition();
+                int lineStart = startOffset;
+                int lineEnd = (int)item.getEndPosition();
+                Builder builder = StructureProvider.newBuilder(item.getName(), convertKind(item.getKind()));
+                builder.selectionStartOffset(startOffset).selectionEndOffset(lineEnd);
+                createDetail(item, builder);
+                createTags(item, builder);
+
+                try {
+                    String prefix = doc.getText(lineStart, startOffset);

Review comment:
       `lineStart` was assigned the value of `startOffset` (line 210), but was never changed after that -- maybe swap lines 219 & 220 ?

##########
File path: java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java
##########
@@ -813,97 +814,61 @@ protected void process(CompilationInfo arg0, Document arg1, SchedulerEvent arg2)
     @Override
     public CompletableFuture<List<Either<SymbolInformation, DocumentSymbol>>> documentSymbol(DocumentSymbolParams params) {
         return server.openedProjects().thenCompose(projects -> {
-            JavaSource js = getJavaSource(params.getTextDocument().getUri());
-            if (js == null) {
+            List<Either<SymbolInformation, DocumentSymbol>> result = new ArrayList<>();
+        
+            String uri = params.getTextDocument().getUri();
+            FileObject file = fromURI(uri);
+            Document doc = server.getOpenedDocuments().getDocument(uri);
+            if (file == null || !(doc instanceof LineDocument)) {
                 return CompletableFuture.completedFuture(Collections.emptyList());
             }
-            List<Either<SymbolInformation, DocumentSymbol>> result = new ArrayList<>();
-            try {
-                js.runUserActionTask(cc -> {
-                    cc.toPhase(JavaSource.Phase.RESOLVED);
-                    Trees trees = cc.getTrees();
-                    CompilationUnitTree cu = cc.getCompilationUnit();
-                    if (cu.getPackage() != null) {
-                        TreePath tp = trees.getPath(cu, cu.getPackage());
-                        Element el = trees.getElement(tp);
-                        if (el != null && el.getKind() == ElementKind.PACKAGE) {
-                            String name = Utils.label(cc, el, true);
-                            SymbolKind kind = Utils.elementKind2SymbolKind(el.getKind());
-                            Range range = Utils.treeRange(cc, tp.getLeaf());
-                            result.add(Either.forRight(new DocumentSymbol(name, kind, range, range)));
-                        }
-                    }
-                    for (Element tel : cc.getTopLevelElements()) {
-                        DocumentSymbol ds = element2DocumentSymbol(cc, tel);
-                        if (ds != null)
+            StructureProvider structureProvider = MimeLookup.getLookup(DocumentUtilities.getMimeType(doc)).lookup(StructureProvider.class);
+            if (structureProvider != null) {
+                return structureProvider.getStructure(doc).thenApply(structureElements -> {

Review comment:
       The implementations (java, GSF) in this PR will actually block, not fork; so this will likely block the LSP message thread until the parsing is done. I was about to suggest in the GSF impl that it should fork the .parse() into a RP, but maybe it would be better to do the fork here, centrally (?)

##########
File path: ide/csl.api/src/org/netbeans/modules/csl/navigation/GsfStructureProvider.java
##########
@@ -0,0 +1,328 @@
+/*
+ * 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.csl.navigation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+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.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.ParserResult;
+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.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.api.lsp.StructureElement;
+import org.netbeans.modules.csl.api.ElementKind;
+import org.netbeans.modules.csl.api.HtmlFormatter;
+import org.netbeans.modules.csl.api.Modifier;
+import org.netbeans.spi.lsp.StructureProvider;
+
+/**
+ * Implementation of StructureProvider to supply outline view in VSCode
+ * @author Petr Pisl
+ */
+public class GsfStructureProvider implements StructureProvider {
+
+    private static final Logger LOGGER = Logger.getLogger(GsfStructureProvider.class.getName());
+    
+    /** The structure element implementation. Some properties are counted lazy. 
+     * 
+     */
+    private static class GsfStructureElement implements StructureElement {
+        
+        private final static Set<StructureElement.Tag> DEPRECATED_TAG = Collections.singleton(StructureElement.Tag.Deprecated);
+        
+        private final Document doc;         // The children are counted lazily and we need the document for it. 
+        private final StructureItem origItem;
+        private List<GsfStructureElement> children;
+        private String signature;
+        private int expandedStartOffset;
+        private int expandedEndOffset;
+        
+
+        public GsfStructureElement(Document doc, StructureItem origItem) {
+            this.doc = doc;
+            this.origItem = origItem;
+            this.signature = null;
+            this.children = null;
+            this.expandedStartOffset = (int)origItem.getPosition();
+            this.expandedEndOffset = (int)origItem.getEndPosition();
+        }
+        
+        @Override
+        public String getName() {
+            return origItem.getName();
+        }
+
+        @Override
+        public int getSelectionStartOffset() {
+            return (int)origItem.getPosition();
+        }
+
+        @Override
+        public int getSelectionEndOffset() {
+            return (int)origItem.getEndPosition();
+        }
+        
+        @Override
+        public int getExpandedStartOffset() {
+            return expandedStartOffset;
+        }
+
+        protected void setExpandedStartOffset(int enclosedStartOffset) {
+            this.expandedStartOffset = enclosedStartOffset;
+        }
+
+        @Override
+        public int getExpandedEndOffset() {
+            return expandedEndOffset;
+        }
+        
+        protected void setExpandedEndOffset(int enclosedEndOffset) {
+            this.expandedEndOffset = enclosedEndOffset;
+        }
+
+        
+        @Override
+        public String getDetail() { 
+            if (signature == null) {
+                createSignature();
+            }
+            return signature;
+        }
+
+        private void createSignature() {
+            NoHtmlFormatter formatter = new NoHtmlFormatter();
+            String s = origItem.getHtml(formatter);
+            signature = s.substring(getName().length()).trim();
+        }
+        
+        @Override
+        public StructureElement.Kind getKind() {
+            switch(origItem.getKind()) {
+                case ATTRIBUTE: return Kind.Property;
+                case CALL: return Kind.Event;
+                case CLASS: return Kind.Class;
+                case CONSTANT: return Kind.Constant;
+                case CONSTRUCTOR: return Kind.Constructor;
+                case DB: return Kind.File;
+                case ERROR: return Kind.Event;
+                case METHOD: return Kind.Method;
+                case FILE: return Kind.File;
+                case FIELD: return Kind.Field;
+                case MODULE: return Kind.Module;
+                case VARIABLE: return Kind.Variable;
+                case GLOBAL: return Kind.Module;
+                case INTERFACE: return Kind.Interface;
+                case KEYWORD: return Kind.Key;
+                case OTHER: return Kind.Object;
+                case PACKAGE: return Kind.Package;
+                case PARAMETER: return Kind.TypeParameter;

Review comment:
       What is `PARAMETER` really in csl langugaes used for ?

##########
File path: java/java.editor/src/org/netbeans/modules/editor/java/JavaStructureProvider.java
##########
@@ -0,0 +1,314 @@
+/*
+ * 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 com.sun.source.tree.ClassTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.NewClassTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreePath;
+import com.sun.source.util.TreePathScanner;
+import com.sun.source.util.Trees;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.swing.text.Document;
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.JavaSource;
+import org.netbeans.api.java.source.TreeUtilities;
+import org.netbeans.api.lsp.StructureElement;
+import org.netbeans.spi.lsp.StructureProvider;
+
+/**
+ * Implementation of StructureProvider from LSP API. It's used for displaying
+ * outline view and GoTo File Symbols in VSCode.
+ *
+ * @author Petr Pisl
+ */
+@MimeRegistration(mimeType = "text/x-java", service = StructureProvider.class)
+public class JavaStructureProvider implements StructureProvider {
+
+    private static final Logger LOGGER = Logger.getLogger(JavaStructureProvider.class.getName());
+
+    @Override
+    public CompletableFuture<List<StructureElement>> getStructure(Document doc) {
+        JavaSource js = JavaSource.forDocument(doc);
+
+        if (js != null) {
+            List<StructureElement> result = new ArrayList<>();
+            try {
+                js.runUserActionTask(cc -> {
+                    cc.toPhase(JavaSource.Phase.RESOLVED);
+                    Trees trees = cc.getTrees();
+                    CompilationUnitTree cu = cc.getCompilationUnit();
+                    if (cu.getPackage() != null) {
+                        TreePath tp = trees.getPath(cu, cu.getPackage());
+                        Element el = trees.getElement(tp);
+                        if (el != null && el.getKind() == ElementKind.PACKAGE) {
+                            StructureElement jse = element2StructureElement(cc, el);
+                            if (jse != null) {
+                                result.add(jse);
+                            }
+                        }
+                    }
+                    for (Element tel : cc.getTopLevelElements()) {
+                        StructureElement jse = element2StructureElement(cc, tel);
+                        if (jse != null) {
+                            result.add(jse);
+                        }
+                    }
+                }, true);
+            } catch (IOException ex) {
+                LOGGER.log(Level.FINE, null, ex);
+            }
+            return CompletableFuture.completedFuture(result);
+        }
+        return CompletableFuture.completedFuture(null);
+    }
+
+    private static StructureElement element2StructureElement(CompilationInfo info, Element el) {
+        TreePath path = info.getTrees().getPath(el);
+        if (path == null) {
+            return null;
+        }
+        TreeUtilities tu = info.getTreeUtilities();
+        if (tu.isSynthetic(path)) {
+            return null;
+        }
+
+        Builder builder = StructureProvider.newBuilder(createName(info, el), convertKind(el.getKind()));
+        builder.detail(createDetail(info, el));
+        setOffsets(info, el, builder);
+        if (info.getElements().isDeprecated(el)) {
+            builder.addTag(StructureElement.Tag.Deprecated);
+        }
+        for (Element child : el.getEnclosedElements()) {
+            StructureElement jse = element2StructureElement(info, child);
+            if (jse != null) {
+                builder.children(jse);
+            }
+        }
+        if (path.getLeaf().getKind() == Tree.Kind.METHOD || path.getLeaf().getKind() == Tree.Kind.VARIABLE) {

Review comment:
       What about initializers ?

##########
File path: ide/api.lsp/src/org/netbeans/api/lsp/StructureElement.java
##########
@@ -0,0 +1,191 @@
+/*
+ * 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.api.lsp;
+
+import java.util.List;
+import java.util.Set;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.modules.lsp.StructureElementAccessor;
+
+/**
+ * StructureElement is a tree item that shows the structure of the source code.
+ *
+ * @author Petr Pisl
+ * @since 1.8
+ */
+public final class StructureElement {
+
+    static {
+        StructureElementAccessor.setDefault(new StructureElementAccessor() {
+            @Override
+            public StructureElement createStructureElement(String name, String detail, int selectionStartOffset, int selectionEndOffset, int expandedStartOffset, int expandedEndOffset, Kind kind, Set<Tag> tags, List<StructureElement> children) {
+                return new StructureElement(name, detail, selectionStartOffset, selectionEndOffset, expandedStartOffset, expandedEndOffset, kind, tags, children);
+            }
+        });
+    }
+
+    private final String name;
+    private final String detail;
+    private final int selectionStartOffset;

Review comment:
       A weird idea: if `javax.swing.text.Position` is used here, the structure could survive some edits between the time StructureElement is created and transofmed into LSP4J wire format -- and during the translation the document could be readlocked to protect the consistency. @JaroslavTulach  ?




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

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

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



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

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


[GitHub] [netbeans] JaroslavTulach commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
JaroslavTulach commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r805115819



##########
File path: ide/api.lsp/src/org/netbeans/api/lsp/StructureElement.java
##########
@@ -0,0 +1,191 @@
+/*
+ * 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.api.lsp;
+
+import java.util.List;
+import java.util.Set;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.modules.lsp.StructureElementAccessor;
+
+/**
+ * StructureElement is a tree item that shows the structure of the source code.
+ *
+ * @author Petr Pisl
+ * @since 1.8
+ */
+public final class StructureElement {
+
+    static {
+        StructureElementAccessor.setDefault(new StructureElementAccessor() {
+            @Override
+            public StructureElement createStructureElement(String name, String detail, int selectionStartOffset, int selectionEndOffset, int expandedStartOffset, int expandedEndOffset, Kind kind, Set<Tag> tags, List<StructureElement> children) {
+                return new StructureElement(name, detail, selectionStartOffset, selectionEndOffset, expandedStartOffset, expandedEndOffset, kind, tags, children);
+            }
+        });
+    }
+
+    private final String name;
+    private final String detail;
+    private final int selectionStartOffset;

Review comment:
       Do we want the _structure_ to represent read-only snapshot and be always re-created from scratch? Or do we want the _structure_ to be updated?
   
   I believe we strive for the first approach. As such making the fields `final` more properly represents the _snapshot_ nature of the _structure_.




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

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

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



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

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


[GitHub] [netbeans] JaroslavTulach commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
JaroslavTulach commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r802247004



##########
File path: ide/api.lsp/src/org/netbeans/spi/lsp/StructureProvider.java
##########
@@ -0,0 +1,244 @@
+/*
+ * 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.spi.lsp;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import org.netbeans.api.lsp.StructureElement;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import javax.swing.text.Document;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.modules.lsp.StructureElementAccessor;
+
+/**
+ * Interface for building structure of symbols at a given document.
+ * Implementations of the interface should be registered in MimeLookup.
+ * <pre>
+ *
+ *  {@code @MimeRegistration(mimeType = "text/foo", service = StructureProvider.class)

Review comment:
       Consider using `{@codesnippet}` tag.

##########
File path: ide/api.lsp/src/org/netbeans/spi/lsp/StructureProvider.java
##########
@@ -0,0 +1,244 @@
+/*
+ * 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.spi.lsp;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import org.netbeans.api.lsp.StructureElement;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import javax.swing.text.Document;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.modules.lsp.StructureElementAccessor;
+
+/**
+ * Interface for building structure of symbols at a given document.
+ * Implementations of the interface should be registered in MimeLookup.
+ * <pre>
+ *
+ *  {@code @MimeRegistration(mimeType = "text/foo", service = StructureProvider.class)
+ *   public class FooStructureProvider implements StructureProvider {
+ *     ...
+ *   }
+ *  }
+ * </pre>
+ *
+ * @author Petr Pisl
+ * @since 1.8
+ */
+public interface StructureProvider {
+
+    /**
+     * Resolves a structure tree of symbols at the given document.
+     *
+     * @param doc document on which to operate.
+     * @return a list of top level structure elements
+     *
+     * @since 1.8
+     */
+    @NonNull
+    CompletableFuture<List<StructureElement>> getStructure(@NonNull Document doc);
+
+    /**
+     * Create builder for {@link StructureElement} instances.
+     *
+     * @param name the name of the structure element
+     * @param kind the kind of structure element
+     * @return newly created builder
+     *
+     * @since 1.8
+     */
+    public static Builder newBuilder(@NonNull String name, @NonNull StructureElement.Kind kind) {
+        return new Builder(name, kind);
+    }
+
+    /**
+     * Builder for {@link StructureElement} instances.
+     *
+     * @since 1.8
+     */
+    public static final class Builder {
+
+        private String name;
+        private String detail;
+        private int selectionStartOffset;
+        private int selectionEndOffset;
+        private int expandedStartOffset;
+        private int expandedEndOffset;
+        private StructureElement.Kind kind;
+        private Set<StructureElement.Tag> tags;
+        private List<StructureElement> children;
+
+        private Builder(@NonNull String name, @NonNull StructureElement.Kind kind) {
+            this.name = name;
+            this.kind = kind;
+        }
+
+        /**
+         * The name of {@link StructureElement} is displayed in the structure
+         * tree and other ui.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder name(@NonNull String name) {
+            this.name = name;
+            return this;
+        }
+
+        /**
+         * Kind of this structure element.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder kind(@NonNull StructureElement.Kind name) {
+            this.kind = kind;
+            return this;
+        }
+
+        /**
+         * The detail of {@link StructureElement}, e.g the signature of a
+         * function. If not provided only the name is used.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder detail(@NonNull String detail) {
+            this.detail = detail;
+            return this;
+        }
+
+        /**
+         * The start of offset range where this element should be selected and
+         * revealed in document when selected in outline view.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder selectionStartOffset(int selectionStartOffset) {
+            this.selectionStartOffset = selectionStartOffset;
+            return this;
+        }
+
+        /**
+         * The end of offset range where this element should be selected and
+         * revealed in document when selected in outline view.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder selectionEndOffset(int selectionEndOffset) {
+            this.selectionEndOffset = selectionEndOffset;
+            return this;
+        }
+
+        /**
+         * The expanded range is offset range that is typically used to
+         * determine if the cursors inside the element to reveal in the element
+         * in the UI.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder expandedStartOffset(int expandedStartOffset) {
+            this.expandedStartOffset = expandedStartOffset;
+            return this;
+        }
+
+        /**
+         * The expanded range is offset range that is typically used to
+         * determine if the cursors inside the element to reveal in the element
+         * in the UI.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder expandedEndOffset(int expandedEndOffset) {
+            this.expandedEndOffset = expandedEndOffset;
+            return this;
+        }
+
+        /**
+         * Adds tag for this structure element.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder addTag(@NonNull StructureElement.Tag tag) {
+            if (this.tags == null) {
+                this.tags = new HashSet<>();
+            }
+            this.tags.add(tag);
+            return this;
+        }
+        
+        /**
+         * Tags for this structure element.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder tags(@NonNull Set<StructureElement.Tag> tags) {
+            this.tags = tags;
+            return this;
+        }
+
+        /**
+         * Adds sub element for this structure element.
+         *
+         * @since 1.8
+         */
+        @NonNull
+        public Builder addChild(@NonNull StructureElement child) {

Review comment:
       Why `addChild` vs. `children`? It'd be enough to have `children(StructureElement... children)` and possibly `children(List<StructureElement> children)` that would both add few child(ren) to the list.




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r794865358



##########
File path: ide/api.lsp/src/org/netbeans/spi/lsp/StructureProvider.java
##########
@@ -0,0 +1,57 @@
+/*
+ * 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.spi.lsp;
+
+import org.netbeans.api.lsp.StructureElement;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import javax.swing.text.Document;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.spi.editor.mimelookup.MimeLocation;
+
+/**
+ * Interface for building structure of symbols at a given document.
+ * Implementations of the interface should be registered in MimeLookup.
+ * <pre>
+ *
+ *  {@code @MimeRegistration(mimeType = "text/foo", service = StructureProvider.class)
+ *   public class FooStructureProvider implements StructureProvider {
+ *     ...
+ *   }
+ *  }
+ * </pre>
+ *
+ * @author Petr Pisl
+ * @since 1.8
+ */
+
+//@MimeLocation(subfolderName = "StructureProviders")
+public interface StructureProvider {
+    
+    /**
+     * Resolves a structure tree of symbols at the given document.
+     *
+     * @param doc document on which to operate.
+     * @return a list of top level structure elements
+     * 
+     * @since 1.8
+     */
+    @NonNull
+    CompletableFuture<List<? extends StructureElement>> getStructure(@NonNull Document doc);

Review comment:
       I was thinking about this again and I agree with @JaroslavTulach . I will change `StructureElement` to the final class and create a builder for it. 




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r805643810



##########
File path: ide/csl.api/src/org/netbeans/modules/csl/navigation/GsfStructureProvider.java
##########
@@ -0,0 +1,328 @@
+/*
+ * 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.csl.navigation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+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.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.ParserResult;
+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.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.api.lsp.StructureElement;
+import org.netbeans.modules.csl.api.ElementKind;
+import org.netbeans.modules.csl.api.HtmlFormatter;
+import org.netbeans.modules.csl.api.Modifier;
+import org.netbeans.spi.lsp.StructureProvider;
+
+/**
+ * Implementation of StructureProvider to supply outline view in VSCode
+ * @author Petr Pisl
+ */
+public class GsfStructureProvider implements StructureProvider {
+
+    private static final Logger LOGGER = Logger.getLogger(GsfStructureProvider.class.getName());
+    
+    /** The structure element implementation. Some properties are counted lazy. 
+     * 
+     */
+    private static class GsfStructureElement implements StructureElement {
+        
+        private final static Set<StructureElement.Tag> DEPRECATED_TAG = Collections.singleton(StructureElement.Tag.Deprecated);
+        
+        private final Document doc;         // The children are counted lazily and we need the document for it. 
+        private final StructureItem origItem;
+        private List<GsfStructureElement> children;
+        private String signature;
+        private int expandedStartOffset;
+        private int expandedEndOffset;
+        
+
+        public GsfStructureElement(Document doc, StructureItem origItem) {
+            this.doc = doc;
+            this.origItem = origItem;
+            this.signature = null;
+            this.children = null;
+            this.expandedStartOffset = (int)origItem.getPosition();
+            this.expandedEndOffset = (int)origItem.getEndPosition();
+        }
+        
+        @Override
+        public String getName() {
+            return origItem.getName();
+        }
+
+        @Override
+        public int getSelectionStartOffset() {
+            return (int)origItem.getPosition();
+        }
+
+        @Override
+        public int getSelectionEndOffset() {
+            return (int)origItem.getEndPosition();
+        }
+        
+        @Override
+        public int getExpandedStartOffset() {
+            return expandedStartOffset;
+        }
+
+        protected void setExpandedStartOffset(int enclosedStartOffset) {
+            this.expandedStartOffset = enclosedStartOffset;
+        }
+
+        @Override
+        public int getExpandedEndOffset() {
+            return expandedEndOffset;
+        }
+        
+        protected void setExpandedEndOffset(int enclosedEndOffset) {
+            this.expandedEndOffset = enclosedEndOffset;
+        }
+
+        
+        @Override
+        public String getDetail() { 
+            if (signature == null) {
+                createSignature();
+            }
+            return signature;
+        }
+
+        private void createSignature() {
+            NoHtmlFormatter formatter = new NoHtmlFormatter();
+            String s = origItem.getHtml(formatter);
+            signature = s.substring(getName().length()).trim();
+        }
+        
+        @Override
+        public StructureElement.Kind getKind() {
+            switch(origItem.getKind()) {
+                case ATTRIBUTE: return Kind.Property;
+                case CALL: return Kind.Event;
+                case CLASS: return Kind.Class;
+                case CONSTANT: return Kind.Constant;
+                case CONSTRUCTOR: return Kind.Constructor;
+                case DB: return Kind.File;
+                case ERROR: return Kind.Event;
+                case METHOD: return Kind.Method;
+                case FILE: return Kind.File;
+                case FIELD: return Kind.Field;
+                case MODULE: return Kind.Module;
+                case VARIABLE: return Kind.Variable;
+                case GLOBAL: return Kind.Module;
+                case INTERFACE: return Kind.Interface;
+                case KEYWORD: return Kind.Key;
+                case OTHER: return Kind.Object;
+                case PACKAGE: return Kind.Package;
+                case PARAMETER: return Kind.TypeParameter;

Review comment:
       It depends on the language.




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#issuecomment-1024145756


   There are no tests yet, I need to write them. 


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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r794847685



##########
File path: ide/api.lsp/src/org/netbeans/api/lsp/StructureElement.java
##########
@@ -0,0 +1,130 @@
+/*
+ * 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.api.lsp;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * StructureElement is a tree item that shows the structure of the source code.
+ * 
+ * @author Petr Pisl
+ * @since 1.8
+ */
+public interface StructureElement {
+   
+    /**
+     * Kind of the structure element. 
+     */
+    public static enum Kind {
+        File,
+	Module,

Review comment:
       Oh, this was copy paste from other place. I will correct it. 




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r794857772



##########
File path: ide/api.lsp/src/org/netbeans/spi/lsp/StructureProvider.java
##########
@@ -0,0 +1,57 @@
+/*
+ * 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.spi.lsp;
+
+import org.netbeans.api.lsp.StructureElement;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import javax.swing.text.Document;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.spi.editor.mimelookup.MimeLocation;
+
+/**
+ * Interface for building structure of symbols at a given document.
+ * Implementations of the interface should be registered in MimeLookup.
+ * <pre>
+ *
+ *  {@code @MimeRegistration(mimeType = "text/foo", service = StructureProvider.class)
+ *   public class FooStructureProvider implements StructureProvider {
+ *     ...
+ *   }
+ *  }
+ * </pre>
+ *
+ * @author Petr Pisl
+ * @since 1.8
+ */
+
+//@MimeLocation(subfolderName = "StructureProviders")
+public interface StructureProvider {
+    
+    /**
+     * Resolves a structure tree of symbols at the given document.
+     *
+     * @param doc document on which to operate.
+     * @return a list of top level structure elements
+     * 
+     * @since 1.8
+     */
+    @NonNull
+    CompletableFuture<List<? extends StructureElement>> getStructure(@NonNull Document doc);

Review comment:
       When we agree, that we don't need to create subnodes lazily, I will do it in this way. 




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r804469526



##########
File path: ide/api.lsp/src/org/netbeans/spi/lsp/StructureProvider.java
##########
@@ -0,0 +1,244 @@
+/*
+ * 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.spi.lsp;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import org.netbeans.api.lsp.StructureElement;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import javax.swing.text.Document;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.modules.lsp.StructureElementAccessor;
+
+/**
+ * Interface for building structure of symbols at a given document.
+ * Implementations of the interface should be registered in MimeLookup.
+ * <pre>
+ *
+ *  {@code @MimeRegistration(mimeType = "text/foo", service = StructureProvider.class)

Review comment:
       Corrected.




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

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

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



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

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


[GitHub] [netbeans] ppisl commented on a change in pull request #3525: [NETBEANS-6425] Provide outline view for Groovy file in VSCode.

Posted by GitBox <gi...@apache.org>.
ppisl commented on a change in pull request #3525:
URL: https://github.com/apache/netbeans/pull/3525#discussion_r805854326



##########
File path: java/java.editor/src/org/netbeans/modules/editor/java/JavaStructureProvider.java
##########
@@ -0,0 +1,314 @@
+/*
+ * 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 com.sun.source.tree.ClassTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.NewClassTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreePath;
+import com.sun.source.util.TreePathScanner;
+import com.sun.source.util.Trees;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.swing.text.Document;
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.JavaSource;
+import org.netbeans.api.java.source.TreeUtilities;
+import org.netbeans.api.lsp.StructureElement;
+import org.netbeans.spi.lsp.StructureProvider;
+
+/**
+ * Implementation of StructureProvider from LSP API. It's used for displaying
+ * outline view and GoTo File Symbols in VSCode.
+ *
+ * @author Petr Pisl
+ */
+@MimeRegistration(mimeType = "text/x-java", service = StructureProvider.class)
+public class JavaStructureProvider implements StructureProvider {
+
+    private static final Logger LOGGER = Logger.getLogger(JavaStructureProvider.class.getName());
+
+    @Override
+    public CompletableFuture<List<StructureElement>> getStructure(Document doc) {
+        JavaSource js = JavaSource.forDocument(doc);
+
+        if (js != null) {
+            List<StructureElement> result = new ArrayList<>();
+            try {
+                js.runUserActionTask(cc -> {
+                    cc.toPhase(JavaSource.Phase.RESOLVED);
+                    Trees trees = cc.getTrees();
+                    CompilationUnitTree cu = cc.getCompilationUnit();
+                    if (cu.getPackage() != null) {
+                        TreePath tp = trees.getPath(cu, cu.getPackage());
+                        Element el = trees.getElement(tp);
+                        if (el != null && el.getKind() == ElementKind.PACKAGE) {
+                            StructureElement jse = element2StructureElement(cc, el);
+                            if (jse != null) {
+                                result.add(jse);
+                            }
+                        }
+                    }
+                    for (Element tel : cc.getTopLevelElements()) {
+                        StructureElement jse = element2StructureElement(cc, tel);
+                        if (jse != null) {
+                            result.add(jse);
+                        }
+                    }
+                }, true);
+            } catch (IOException ex) {
+                LOGGER.log(Level.FINE, null, ex);
+            }
+            return CompletableFuture.completedFuture(result);
+        }
+        return CompletableFuture.completedFuture(null);
+    }
+
+    private static StructureElement element2StructureElement(CompilationInfo info, Element el) {
+        TreePath path = info.getTrees().getPath(el);
+        if (path == null) {
+            return null;
+        }
+        TreeUtilities tu = info.getTreeUtilities();
+        if (tu.isSynthetic(path)) {
+            return null;
+        }
+
+        Builder builder = StructureProvider.newBuilder(createName(info, el), convertKind(el.getKind()));
+        builder.detail(createDetail(info, el));
+        setOffsets(info, el, builder);
+        if (info.getElements().isDeprecated(el)) {
+            builder.addTag(StructureElement.Tag.Deprecated);
+        }
+        for (Element child : el.getEnclosedElements()) {
+            StructureElement jse = element2StructureElement(info, child);
+            if (jse != null) {
+                builder.children(jse);
+            }
+        }
+        if (path.getLeaf().getKind() == Tree.Kind.METHOD || path.getLeaf().getKind() == Tree.Kind.VARIABLE) {

Review comment:
       I have copied the original code here. I didn't changed the logic. 




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

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

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



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

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