Automated merge with https://hg.netbeans.org/main/contrib
authorRalph Benjamin Ruijs <ralphbenjamin@netbeans.org>
Sun, 13 Sep 2015 11:47:42 +0200
changeset 1831464f06c7da146
parent 18304 a075d988c9d5
parent 18313 42555310aefb
child 18315 b3bafec343dc
Automated merge with https://hg.netbeans.org/main/contrib
python.editor/src/org/netbeans/modules/python/editor/AstPath.java
python.editor/src/org/netbeans/modules/python/editor/PythonAstUtils.java
python.editor/src/org/netbeans/modules/python/editor/PythonExample.py
python.editor/src/org/netbeans/modules/python/editor/PythonFormatter.java
python.editor/src/org/netbeans/modules/python/editor/PythonHintOptions.java
python.editor/src/org/netbeans/modules/python/editor/PythonIndex.java
python.editor/src/org/netbeans/modules/python/editor/PythonIndexSearcher.java
python.editor/src/org/netbeans/modules/python/editor/PythonIndexer.java
python.editor/src/org/netbeans/modules/python/editor/PythonIndexerFactory.java
python.editor/src/org/netbeans/modules/python/editor/PythonParser.java
python.editor/src/org/netbeans/modules/python/editor/PythonParserResult.java
python.editor/src/org/netbeans/modules/python/editor/PythonStructureItem.java
python.editor/src/org/netbeans/modules/python/editor/PythonStructureScanner.java
python.editor/src/org/netbeans/modules/python/editor/PythonUtils.java
python.editor/src/org/netbeans/modules/python/editor/RstFormatter.java
python.editor/src/org/netbeans/modules/python/editor/elements/AstElement.java
python.editor/src/org/netbeans/modules/python/editor/elements/Element.java
python.editor/src/org/netbeans/modules/python/editor/elements/IndexedElement.java
python.editor/src/org/netbeans/modules/python/editor/elements/IndexedMethod.java
python.editor/src/org/netbeans/modules/python/editor/elements/IndexedPackage.java
python.editor/src/org/netbeans/modules/python/editor/hints/AccessToProtected.java
python.editor/src/org/netbeans/modules/python/editor/hints/AllAssignExists.java
python.editor/src/org/netbeans/modules/python/editor/hints/AssignToVariable.java
python.editor/src/org/netbeans/modules/python/editor/hints/AttributeDefinedOutsideInit.java
python.editor/src/org/netbeans/modules/python/editor/hints/Bundle.properties
python.editor/src/org/netbeans/modules/python/editor/hints/ClassCircularRedundancy.java
python.editor/src/org/netbeans/modules/python/editor/hints/CreateDocString.java
python.editor/src/org/netbeans/modules/python/editor/hints/Deprecations.java
python.editor/src/org/netbeans/modules/python/editor/hints/ExtractCode.java
python.editor/src/org/netbeans/modules/python/editor/hints/InputOutputFinder.java
python.editor/src/org/netbeans/modules/python/editor/hints/NameRule.java
python.editor/src/org/netbeans/modules/python/editor/hints/NameRulePrefs.form
python.editor/src/org/netbeans/modules/python/editor/hints/NameRulePrefs.java
python.editor/src/org/netbeans/modules/python/editor/hints/NameStyle.java
python.editor/src/org/netbeans/modules/python/editor/hints/PythonAstRule.java
python.editor/src/org/netbeans/modules/python/editor/hints/PythonHintsProvider.java
python.editor/src/org/netbeans/modules/python/editor/hints/PythonRuleContext.java
python.editor/src/org/netbeans/modules/python/editor/hints/PythonSelectionRule.java
python.editor/src/org/netbeans/modules/python/editor/hints/RelativeImports.java
python.editor/src/org/netbeans/modules/python/editor/hints/SplitImports.java
python.editor/src/org/netbeans/modules/python/editor/hints/SurroundWith.java
python.editor/src/org/netbeans/modules/python/editor/hints/UnresolvedClassComponents.java
python.editor/src/org/netbeans/modules/python/editor/hints/UnresolvedDetector.java
python.editor/src/org/netbeans/modules/python/editor/hints/UnusedDetector.java
python.editor/src/org/netbeans/modules/python/editor/hints/UnusedDetectorPrefs.form
python.editor/src/org/netbeans/modules/python/editor/hints/UnusedDetectorPrefs.java
python.editor/src/org/netbeans/modules/python/editor/hints/UnusedImports.java
python.editor/src/org/netbeans/modules/python/editor/imports/ImportEntry.java
python.editor/src/org/netbeans/modules/python/editor/imports/ImportManager.java
python.editor/src/org/netbeans/modules/python/editor/lexer/Call.java
python.editor/src/org/netbeans/modules/python/editor/lexer/PythonCommentLexer.java
python.editor/src/org/netbeans/modules/python/editor/lexer/PythonCommentTokenId.java
python.editor/src/org/netbeans/modules/python/editor/lexer/PythonLexer.java
python.editor/src/org/netbeans/modules/python/editor/lexer/PythonLexerUtils.java
python.editor/src/org/netbeans/modules/python/editor/lexer/PythonStringLexer.java
python.editor/src/org/netbeans/modules/python/editor/lexer/PythonStringTokenId.java
python.editor/src/org/netbeans/modules/python/editor/lexer/PythonTokenId.java
python.editor/src/org/netbeans/modules/python/editor/options/Bundle.properties
python.editor/src/org/netbeans/modules/python/editor/options/CodeStyle.java
python.editor/src/org/netbeans/modules/python/editor/options/FmtAlignment.form
python.editor/src/org/netbeans/modules/python/editor/options/FmtAlignment.java
python.editor/src/org/netbeans/modules/python/editor/options/FmtBlankLines.form
python.editor/src/org/netbeans/modules/python/editor/options/FmtBlankLines.java
python.editor/src/org/netbeans/modules/python/editor/options/FmtImports.form
python.editor/src/org/netbeans/modules/python/editor/options/FmtImports.java
python.editor/src/org/netbeans/modules/python/editor/options/FmtOptions.java
python.editor/src/org/netbeans/modules/python/editor/options/FmtSpaces.form
python.editor/src/org/netbeans/modules/python/editor/options/FmtSpaces.java
python.editor/src/org/netbeans/modules/python/editor/options/FmtTabsIndents.form
python.editor/src/org/netbeans/modules/python/editor/options/FmtTabsIndents.java
python.editor/src/org/netbeans/modules/python/editor/options/FmtWrapping.form
python.editor/src/org/netbeans/modules/python/editor/options/FmtWrapping.java
python.editor/src/org/netbeans/modules/python/editor/options/NumericKeyListener.java
python.editor/src/org/netbeans/modules/python/editor/scopes/ArgListCompiler.java
python.editor/src/org/netbeans/modules/python/editor/scopes/ScopeConstants.java
python.editor/src/org/netbeans/modules/python/editor/scopes/ScopeInfo.java
python.editor/src/org/netbeans/modules/python/editor/scopes/ScopesCompiler.java
python.editor/src/org/netbeans/modules/python/editor/scopes/SymInfo.java
python.editor/src/org/netbeans/modules/python/editor/scopes/SymbolTable.java
python.source/src/org/netbeans/modules/python/source/PythonProjectSourceLevelQuery.java
     1.1 --- a/o.jython/manifest.mf	Sat Sep 12 23:03:15 2015 -0700
     1.2 +++ b/o.jython/manifest.mf	Sun Sep 13 11:47:42 2015 +0200
     1.3 @@ -1,6 +1,6 @@
     1.4  Manifest-Version: 1.0
     1.5  OpenIDE-Module: org.jython/2
     1.6  OpenIDE-Module-Localizing-Bundle: org/jython/Bundle.properties
     1.7 -OpenIDE-Module-Specification-Version: 2.11
     1.8 +OpenIDE-Module-Specification-Version: 2.12
     1.9  AutoUpdate-Show-In-Client: false
    1.10  
     2.1 --- a/o.jython/nbproject/project.xml	Sat Sep 12 23:03:15 2015 -0700
     2.2 +++ b/o.jython/nbproject/project.xml	Sun Sep 13 11:47:42 2015 +0200
     2.3 @@ -16,6 +16,8 @@
     2.4              </module-dependencies>
     2.5              <friend-packages>
     2.6                  <friend>org.netbeans.modules.python.editor</friend>
     2.7 +                <friend>org.netbeans.modules.python.hints</friend>
     2.8 +                <friend>org.netbeans.modules.python.source</friend>
     2.9                  <package>org.python.antlr</package>
    2.10                  <package>org.python.antlr.ast</package>
    2.11                  <package>org.python.antlr.base</package>
     3.1 --- a/python.editor/nbproject/project.properties	Sat Sep 12 23:03:15 2015 -0700
     3.2 +++ b/python.editor/nbproject/project.properties	Sun Sep 13 11:47:42 2015 +0200
     3.3 @@ -18,7 +18,7 @@
     3.4  javac.source=1.7
     3.5  javac.compilerargs=-Xlint -Xlint:-serial
     3.6  nbm.needs.restart=true
     3.7 -spec.version.base=1.8.1
     3.8 +spec.version.base=1.8.2
     3.9  spec.version.base.fatal.warning=false
    3.10  
    3.11  ant.jar=${ant.core.lib}
     4.1 --- a/python.editor/nbproject/project.xml	Sat Sep 12 23:03:15 2015 -0700
     4.2 +++ b/python.editor/nbproject/project.xml	Sun Sep 13 11:47:42 2015 +0200
     4.3 @@ -307,7 +307,7 @@
     4.4                      <build-prerequisite/>
     4.5                      <compile-dependency/>
     4.6                      <run-dependency>
     4.7 -                        <specification-version>1.0</specification-version>
     4.8 +                        <specification-version>1.1</specification-version>
     4.9                      </run-dependency>
    4.10                  </dependency>
    4.11                  <dependency>
    4.12 @@ -417,12 +417,14 @@
    4.13                  </dependency>
    4.14              </module-dependencies>
    4.15              <friend-packages>
    4.16 +                <friend>org.netbeans.modules.python.hints</friend>
    4.17                  <friend>org.netbeans.modules.python.project</friend>
    4.18                  <friend>org.netbeans.modules.python.project2</friend>
    4.19                  <friend>org.netbeans.modules.python.testrunner</friend>
    4.20                  <package>org.netbeans.modules.python.editor</package>
    4.21                  <package>org.netbeans.modules.python.editor.codecoverage</package>
    4.22                  <package>org.netbeans.modules.python.editor.lexer</package>
    4.23 +                <package>org.netbeans.modules.python.editor.scopes</package>
    4.24              </friend-packages>
    4.25          </data>
    4.26      </configuration>
     5.1 --- a/python.editor/src/org/netbeans/modules/python/editor/AstPath.java	Sat Sep 12 23:03:15 2015 -0700
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,436 +0,0 @@
     5.4 -/*
     5.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     5.6 - *
     5.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
     5.8 - *
     5.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    5.10 - * Other names may be trademarks of their respective owners.
    5.11 - *
    5.12 - * The contents of this file are subject to the terms of either the GNU
    5.13 - * General Public License Version 2 only ("GPL") or the Common
    5.14 - * Development and Distribution License("CDDL") (collectively, the
    5.15 - * "License"). You may not use this file except in compliance with the
    5.16 - * License. You can obtain a copy of the License at
    5.17 - * http://www.netbeans.org/cddl-gplv2.html
    5.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    5.19 - * specific language governing permissions and limitations under the
    5.20 - * License.  When distributing the software, include this License Header
    5.21 - * Notice in each file and include the License file at
    5.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    5.23 - * particular file as subject to the "Classpath" exception as provided
    5.24 - * by Oracle in the GPL Version 2 section of the License file that
    5.25 - * accompanied this code. If applicable, add the following below the
    5.26 - * License Header, with the fields enclosed by brackets [] replaced by
    5.27 - * your own identifying information:
    5.28 - * "Portions Copyrighted [year] [name of copyright owner]"
    5.29 - *
    5.30 - * Contributor(s):
    5.31 - *
    5.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
    5.33 - */
    5.34 -package org.netbeans.modules.python.editor;
    5.35 -
    5.36 -import java.util.ArrayList;
    5.37 -import java.util.Iterator;
    5.38 -import java.util.ListIterator;
    5.39 -import org.openide.util.Exceptions;
    5.40 -import org.python.antlr.PythonTree;
    5.41 -import org.python.antlr.Visitor;
    5.42 -
    5.43 -/**
    5.44 - * AstPath represents a path from a root node to a particular node in the AST.
    5.45 - * This is necessary because the parent node pointers in the nodes aren't always
    5.46 - * non null, so we can't just pass a node as a reference to a traversable path
    5.47 - * from the root to a node.
    5.48 - *
    5.49 - * @author Tor Norbye
    5.50 - */
    5.51 -public class AstPath implements Iterable<PythonTree> {
    5.52 -    private ArrayList<PythonTree> path = new ArrayList<>(30);
    5.53 -
    5.54 -    public AstPath() {
    5.55 -    }
    5.56 -
    5.57 -    public AstPath(AstPath other) {
    5.58 -        path.addAll(other.path);
    5.59 -    }
    5.60 -
    5.61 -    public AstPath(ArrayList<PythonTree> path) {
    5.62 -        this.path = path;
    5.63 -    }
    5.64 -
    5.65 -//    /**
    5.66 -//     * Initialize a node path to the given caretOffset
    5.67 -//     */
    5.68 -//    public AstPath(PythonTree root, int caretOffset) {
    5.69 -//        findPathTo(root, caretOffset);
    5.70 -//    }
    5.71 -//
    5.72 -//    /**
    5.73 -//     * Find the path to the given node in the AST
    5.74 -//     */
    5.75 -//    @SuppressWarnings("unchecked")
    5.76 -//    public AstPath(PythonTree node, PythonTree target) {
    5.77 -//        if (!find(node, target)) {
    5.78 -//            path.clear();
    5.79 -//        } else {
    5.80 -//            // Reverse the list such that node is on top
    5.81 -//            // When I get time rewrite the find method to build the list that way in the first place
    5.82 -//            Collections.reverse(path);
    5.83 -//        }
    5.84 -//    }
    5.85 -    public void descend(PythonTree node) {
    5.86 -        path.add(node);
    5.87 -    }
    5.88 -
    5.89 -    public void ascend() {
    5.90 -        path.remove(path.size() - 1);
    5.91 -    }
    5.92 -
    5.93 -    /**
    5.94 -     * Return the closest ancestor of the leaf that is of the given type
    5.95 -     */
    5.96 -    public PythonTree getTypedAncestor(Class clz) {
    5.97 -        return getTypedAncestor(clz, null);
    5.98 -    }
    5.99 -
   5.100 -    /**
   5.101 -     * Return the closest ancestor of the given node that is of the given type
   5.102 -     */
   5.103 -    public PythonTree getTypedAncestor(Class clz, PythonTree from) {
   5.104 -        int i = path.size() - 1;
   5.105 -
   5.106 -        // First find the given starting point
   5.107 -        if (from != null) {
   5.108 -            for (; i >= 0; i--) {
   5.109 -                PythonTree node = path.get(i);
   5.110 -
   5.111 -                if (node == from) {
   5.112 -                    break;
   5.113 -                }
   5.114 -            }
   5.115 -        }
   5.116 -
   5.117 -        for (; i >= 0; i--) {
   5.118 -            PythonTree node = path.get(i);
   5.119 -
   5.120 -            if (clz.isInstance(node)) {
   5.121 -                return node;
   5.122 -            }
   5.123 -        }
   5.124 -
   5.125 -        return null; // not found
   5.126 -    }
   5.127 -
   5.128 -    /**
   5.129 -     * Return true iff this path contains a node of the given node type
   5.130 -     *
   5.131 -     * @param nodeType The nodeType to check
   5.132 -     * @return true if the given nodeType is found in the path
   5.133 -     */
   5.134 -    public boolean contains(Class clz) {
   5.135 -        return getTypedAncestor(clz) != null;
   5.136 -    }
   5.137 -
   5.138 -//    /**
   5.139 -//     * Find the position closest to the given offset in the AST. Place the path from the leaf up to the path in the
   5.140 -//     * passed in path list.
   5.141 -//     */
   5.142 -//    @SuppressWarnings("unchecked")
   5.143 -//    public PythonTree findPathTo(PythonTree node, int offset) {
   5.144 -//        PythonTree result = find(node, offset);
   5.145 -//        path.add(node);
   5.146 -//
   5.147 -//        // Reverse the list such that node is on top
   5.148 -//        // When I get time rewrite the find method to build the list that way in the first place
   5.149 -//        Collections.reverse(path);
   5.150 -//
   5.151 -//        return result;
   5.152 -//    }
   5.153 -//
   5.154 -//    @SuppressWarnings("unchecked")
   5.155 -//    private PythonTree find(PythonTree node, int offset) {
   5.156 -//        int begin = node.getSourceStart();
   5.157 -//        int end = node.getSourceEnd();
   5.158 -//
   5.159 -//        if ((offset >= begin) && (offset <= end)) {
   5.160 -//            for (PythonTree child = node.getFirstChild(); child != null; child = child.getNext()) {
   5.161 -//                PythonTree found = find(child, offset);
   5.162 -//
   5.163 -//                if (found != null) {
   5.164 -//                    path.add(child);
   5.165 -//
   5.166 -//                    return found;
   5.167 -//                }
   5.168 -//            }
   5.169 -//
   5.170 -//            return node;
   5.171 -//        } else {
   5.172 -//        for (PythonTree child = node.getFirstChild(); child != null; child = child.getNext()) {
   5.173 -//                PythonTree found = find(child, offset);
   5.174 -//
   5.175 -//                if (found != null) {
   5.176 -//                    path.add(child);
   5.177 -//
   5.178 -//                    return found;
   5.179 -//                }
   5.180 -//            }
   5.181 -//
   5.182 -//            return null;
   5.183 -//        }
   5.184 -//    }
   5.185 -//
   5.186 -//    /**
   5.187 -//     * Find the path to the given node in the AST
   5.188 -//     */
   5.189 -//    @SuppressWarnings("unchecked")
   5.190 -//    public boolean find(PythonTree node, PythonTree target) {
   5.191 -//        if (node == target) {
   5.192 -//            return true;
   5.193 -//        }
   5.194 -//
   5.195 -//        for (PythonTree child = node.getFirstChild(); child != null; child = child.getNext()) {
   5.196 -//            boolean found = find(child, target);
   5.197 -//
   5.198 -//            if (found) {
   5.199 -//                path.add(child);
   5.200 -//
   5.201 -//                return found;
   5.202 -//            }
   5.203 -//        }
   5.204 -//
   5.205 -//        return false;
   5.206 -//    }
   5.207 -    @Override
   5.208 -    public String toString() {
   5.209 -        StringBuilder sb = new StringBuilder();
   5.210 -        sb.append("Path(");
   5.211 -        sb.append(path.size());
   5.212 -        sb.append(")=[");
   5.213 -
   5.214 -        for (PythonTree n : path) {
   5.215 -            String name = n.toString();
   5.216 -            name = name.substring(name.lastIndexOf('.') + 1);
   5.217 -            sb.append(name);
   5.218 -            sb.append(":");
   5.219 -        }
   5.220 -
   5.221 -        sb.append("]");
   5.222 -
   5.223 -        return sb.toString();
   5.224 -    }
   5.225 -
   5.226 -    public PythonTree leaf() {
   5.227 -        if (path.size() == 0) {
   5.228 -            return null;
   5.229 -        } else {
   5.230 -            return path.get(path.size() - 1);
   5.231 -        }
   5.232 -    }
   5.233 -
   5.234 -    public PythonTree leafParent() {
   5.235 -        if (path.size() < 2) {
   5.236 -            return null;
   5.237 -        } else {
   5.238 -            return path.get(path.size() - 2);
   5.239 -        }
   5.240 -    }
   5.241 -
   5.242 -    public PythonTree leafGrandParent() {
   5.243 -        if (path.size() < 3) {
   5.244 -            return null;
   5.245 -        } else {
   5.246 -            return path.get(path.size() - 3);
   5.247 -        }
   5.248 -    }
   5.249 -
   5.250 -    /**
   5.251 -     * Return the top/module level node -- this is not the module node
   5.252 -     * itself but the first node below it.
   5.253 -     */
   5.254 -    public PythonTree topModuleLevel() {
   5.255 -        if (path.size() >= 2) {
   5.256 -            return path.get(1);
   5.257 -        } else {
   5.258 -            return null;
   5.259 -        }
   5.260 -    }
   5.261 -
   5.262 -    public PythonTree root() {
   5.263 -        if (path.size() == 0) {
   5.264 -            return null;
   5.265 -        } else {
   5.266 -            return path.get(0);
   5.267 -        }
   5.268 -    }
   5.269 -
   5.270 -    /** Return an iterator that returns the elements from the leaf back up to the root */
   5.271 -    @Override
   5.272 -    public Iterator<PythonTree> iterator() {
   5.273 -        return new LeafToRootIterator(path);
   5.274 -    }
   5.275 -
   5.276 -    /** REturn an iterator that starts at the root and walks down to the leaf */
   5.277 -    public ListIterator<PythonTree> rootToLeaf() {
   5.278 -        return path.listIterator();
   5.279 -    }
   5.280 -
   5.281 -    /** Return an iterator that walks from the leaf back up to the root */
   5.282 -    public ListIterator<PythonTree> leafToRoot() {
   5.283 -        return new LeafToRootIterator(path);
   5.284 -    }
   5.285 -
   5.286 -    private static class LeafToRootIterator implements ListIterator<PythonTree> {
   5.287 -        private final ListIterator<PythonTree> it;
   5.288 -
   5.289 -        private LeafToRootIterator(ArrayList<PythonTree> path) {
   5.290 -            it = path.listIterator(path.size());
   5.291 -        }
   5.292 -
   5.293 -        @Override
   5.294 -        public boolean hasNext() {
   5.295 -            return it.hasPrevious();
   5.296 -        }
   5.297 -
   5.298 -        @Override
   5.299 -        public PythonTree next() {
   5.300 -            return it.previous();
   5.301 -        }
   5.302 -
   5.303 -        @Override
   5.304 -        public boolean hasPrevious() {
   5.305 -            return it.hasNext();
   5.306 -        }
   5.307 -
   5.308 -        @Override
   5.309 -        public PythonTree previous() {
   5.310 -            return it.next();
   5.311 -        }
   5.312 -
   5.313 -        @Override
   5.314 -        public int nextIndex() {
   5.315 -            return it.previousIndex();
   5.316 -        }
   5.317 -
   5.318 -        @Override
   5.319 -        public int previousIndex() {
   5.320 -            return it.nextIndex();
   5.321 -        }
   5.322 -
   5.323 -        @Override
   5.324 -        public void remove() {
   5.325 -            throw new UnsupportedOperationException("Not supported yet.");
   5.326 -        }
   5.327 -
   5.328 -        @Override
   5.329 -        public void set(PythonTree arg0) {
   5.330 -            throw new UnsupportedOperationException("Not supported yet.");
   5.331 -        }
   5.332 -
   5.333 -        @Override
   5.334 -        public void add(PythonTree arg0) {
   5.335 -            throw new UnsupportedOperationException("Not supported yet.");
   5.336 -        }
   5.337 -    }
   5.338 -
   5.339 -    private static class FindByOffsetVisitor extends Visitor {
   5.340 -        private int targetOffset;
   5.341 -        private ArrayList<PythonTree> path = new ArrayList<>();
   5.342 -
   5.343 -        private FindByOffsetVisitor(int targetOffset) {
   5.344 -            this.targetOffset = targetOffset;
   5.345 -        }
   5.346 -
   5.347 -        @Override
   5.348 -        public void traverse(PythonTree node) throws Exception {
   5.349 -            if (targetOffset >= node.getCharStartIndex() && targetOffset <= node.getCharStopIndex()) {
   5.350 -//                if (targetOffset == node.getCharStopIndex() && node.getClass() == FunctionDef.class) {
   5.351 -//                    // For functions, don't include the last offset, since we can end up with
   5.352 -//                    // functions that overlap - caret at the start position will add BOTH functions
   5.353 -//                    // which we don't want
   5.354 -//                } else {
   5.355 -                path.add(node);
   5.356 -//                }
   5.357 -                super.traverse(node);
   5.358 -            }
   5.359 -        }
   5.360 -
   5.361 -        AstPath getPath() {
   5.362 -            return new AstPath(path);
   5.363 -        }
   5.364 -    }
   5.365 -
   5.366 -    public static AstPath get(PythonTree root, int offset) {
   5.367 -        FindByOffsetVisitor finder = new FindByOffsetVisitor(offset);
   5.368 -        try {
   5.369 -            finder.visit(root);
   5.370 -            AstPath path = finder.getPath();
   5.371 -            if (path.path.size() == 0) {
   5.372 -                path.path.add(root);
   5.373 -            }
   5.374 -
   5.375 -            return path;
   5.376 -        } catch (Exception ex) {
   5.377 -            Exceptions.printStackTrace(ex);
   5.378 -        }
   5.379 -
   5.380 -        return null;
   5.381 -    }
   5.382 -
   5.383 -    private static class FindByNodeVisitor extends Visitor {
   5.384 -        private PythonTree target;
   5.385 -        private int startOffset;
   5.386 -        private int endOffset;
   5.387 -        private ArrayList<PythonTree> path = new ArrayList<>();
   5.388 -        private boolean found;
   5.389 -
   5.390 -        private FindByNodeVisitor(PythonTree target) {
   5.391 -            this.target = target;
   5.392 -            this.startOffset = target.getCharStartIndex();
   5.393 -            this.endOffset = target.getCharStopIndex();
   5.394 -        }
   5.395 -
   5.396 -        @Override
   5.397 -        public void traverse(PythonTree node) throws Exception {
   5.398 -            if (found) {
   5.399 -                return;
   5.400 -            }
   5.401 -            if (node == target) {
   5.402 -                path.add(node);
   5.403 -                found = true;
   5.404 -                return;
   5.405 -            }
   5.406 -            if (startOffset >= node.getCharStartIndex() && endOffset <= node.getCharStopIndex()) {
   5.407 -                path.add(node);
   5.408 -                node.traverse(this);
   5.409 -                if (found) {
   5.410 -                    return;
   5.411 -                }
   5.412 -                path.remove(path.size() - 1);
   5.413 -            }
   5.414 -        }
   5.415 -
   5.416 -        AstPath getPath() {
   5.417 -            return new AstPath(path);
   5.418 -        }
   5.419 -    }
   5.420 -
   5.421 -    /**
   5.422 -     * Find the path to the given node in the AST
   5.423 -     */
   5.424 -    public static AstPath get(PythonTree root, PythonTree target) {
   5.425 -        FindByNodeVisitor finder = new FindByNodeVisitor(target);
   5.426 -        try {
   5.427 -            finder.visit(root);
   5.428 -            AstPath path = finder.getPath();
   5.429 -            if (path.path.size() == 0) {
   5.430 -                path.path.add(root);
   5.431 -            }
   5.432 -
   5.433 -            return path;
   5.434 -        } catch (Exception ex) {
   5.435 -            Exceptions.printStackTrace(ex);
   5.436 -            return null;
   5.437 -        }
   5.438 -    }
   5.439 -}
     6.1 --- a/python.editor/src/org/netbeans/modules/python/editor/GoToSuperTypeAction.java	Sat Sep 12 23:03:15 2015 -0700
     6.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/GoToSuperTypeAction.java	Sun Sep 13 11:47:42 2015 +0200
     6.3 @@ -43,6 +43,8 @@
     6.4   */
     6.5  package org.netbeans.modules.python.editor;
     6.6  
     6.7 +import org.netbeans.modules.python.source.PythonParserResult;
     6.8 +import org.netbeans.modules.python.source.PythonAstUtils;
     6.9  import java.awt.Component;
    6.10  import java.awt.Cursor;
    6.11  import java.awt.Image;
     7.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonAstUtils.java	Sat Sep 12 23:03:15 2015 -0700
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,1007 +0,0 @@
     7.4 -/*
     7.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     7.6 - *
     7.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
     7.8 - *
     7.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    7.10 - * Other names may be trademarks of their respective owners.
    7.11 - *
    7.12 - * The contents of this file are subject to the terms of either the GNU
    7.13 - * General Public License Version 2 only ("GPL") or the Common
    7.14 - * Development and Distribution License("CDDL") (collectively, the
    7.15 - * "License"). You may not use this file except in compliance with the
    7.16 - * License. You can obtain a copy of the License at
    7.17 - * http://www.netbeans.org/cddl-gplv2.html
    7.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    7.19 - * specific language governing permissions and limitations under the
    7.20 - * License.  When distributing the software, include this License Header
    7.21 - * Notice in each file and include the License file at
    7.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    7.23 - * particular file as subject to the "Classpath" exception as provided
    7.24 - * by Oracle in the GPL Version 2 section of the License file that
    7.25 - * accompanied this code. If applicable, add the following below the
    7.26 - * License Header, with the fields enclosed by brackets [] replaced by
    7.27 - * your own identifying information:
    7.28 - * "Portions Copyrighted [year] [name of copyright owner]"
    7.29 - *
    7.30 - * Contributor(s):
    7.31 - *
    7.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
    7.33 - */
    7.34 -package org.netbeans.modules.python.editor;
    7.35 -
    7.36 -import java.util.ArrayList;
    7.37 -import java.util.Collections;
    7.38 -import java.util.HashSet;
    7.39 -import java.util.Iterator;
    7.40 -import java.util.List;
    7.41 -import java.util.Set;
    7.42 -import java.util.logging.Level;
    7.43 -import java.util.logging.Logger;
    7.44 -import javax.swing.text.BadLocationException;
    7.45 -import javax.swing.text.Document;
    7.46 -import org.netbeans.api.lexer.LanguagePath;
    7.47 -import org.netbeans.api.lexer.TokenHierarchy;
    7.48 -import org.netbeans.api.lexer.TokenSequence;
    7.49 -import org.netbeans.api.lexer.TokenUtilities;
    7.50 -import org.netbeans.editor.BaseDocument;
    7.51 -import org.netbeans.editor.Finder;
    7.52 -import org.netbeans.editor.FinderFactory;
    7.53 -import org.netbeans.modules.csl.api.ElementKind;
    7.54 -import org.netbeans.modules.csl.api.OffsetRange;
    7.55 -import org.netbeans.modules.csl.api.StructureItem;
    7.56 -import org.netbeans.modules.csl.spi.GsfUtilities;
    7.57 -import org.netbeans.modules.csl.spi.ParserResult;
    7.58 -import org.netbeans.modules.parsing.api.ParserManager;
    7.59 -import org.netbeans.modules.parsing.api.ResultIterator;
    7.60 -import org.netbeans.modules.parsing.api.Source;
    7.61 -import org.netbeans.modules.parsing.api.UserTask;
    7.62 -import org.netbeans.modules.parsing.spi.ParseException;
    7.63 -import org.netbeans.modules.python.editor.elements.IndexedElement;
    7.64 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
    7.65 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
    7.66 -import org.netbeans.modules.python.editor.lexer.PythonCommentTokenId;
    7.67 -import org.netbeans.modules.python.editor.scopes.ScopeInfo;
    7.68 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
    7.69 -import org.netbeans.modules.python.editor.scopes.SymInfo;
    7.70 -import org.openide.filesystems.FileObject;
    7.71 -import org.openide.util.Exceptions;
    7.72 -import org.python.antlr.PythonTree;
    7.73 -import org.python.antlr.Visitor;
    7.74 -import org.python.antlr.ast.Assign;
    7.75 -import org.python.antlr.ast.Attribute;
    7.76 -import org.python.antlr.ast.Call;
    7.77 -import org.python.antlr.ast.ClassDef;
    7.78 -import org.python.antlr.ast.Expr;
    7.79 -import org.python.antlr.ast.FunctionDef;
    7.80 -import org.python.antlr.ast.Import;
    7.81 -import org.python.antlr.ast.ImportFrom;
    7.82 -import org.python.antlr.ast.Module;
    7.83 -import org.python.antlr.ast.Name;
    7.84 -import org.python.antlr.ast.Str;
    7.85 -import org.python.antlr.ast.arguments;
    7.86 -import org.python.antlr.base.expr;
    7.87 -import org.python.antlr.base.stmt;
    7.88 -
    7.89 -/**
    7.90 - * Utility functions for dealing with the Jython AST
    7.91 - *
    7.92 - * @author Tor Norbye
    7.93 - */
    7.94 -public class PythonAstUtils {
    7.95 -    private PythonAstUtils() {
    7.96 -        // This is just a utility class, no instances expected so private constructor
    7.97 -    }
    7.98 -
    7.99 -    public static int getAstOffset(ParserResult result, int lexOffset) {
   7.100 -        if (result != null) {
   7.101 -            return result.getSnapshot().getEmbeddedOffset(lexOffset);
   7.102 -        }
   7.103 -
   7.104 -        return lexOffset;
   7.105 -    }
   7.106 -
   7.107 -    public static OffsetRange getAstOffsets(ParserResult result, OffsetRange lexicalRange) {
   7.108 -        if (result != null) {
   7.109 -            int rangeStart = lexicalRange.getStart();
   7.110 -            int start = result.getSnapshot().getEmbeddedOffset(rangeStart);
   7.111 -            if (start == rangeStart) {
   7.112 -                return lexicalRange;
   7.113 -            } else if (start == -1) {
   7.114 -                return OffsetRange.NONE;
   7.115 -            } else {
   7.116 -                // Assumes the translated range maintains size
   7.117 -                return new OffsetRange(start, start + lexicalRange.getLength());
   7.118 -            }
   7.119 -        }
   7.120 -        return lexicalRange;
   7.121 -    }
   7.122 -
   7.123 -    public static PythonParserResult getParseResult(ParserResult result) {
   7.124 -        if(result == null || !(result instanceof PythonParserResult)) {
   7.125 -            return null;
   7.126 -        } else {
   7.127 -            return ((PythonParserResult)result);
   7.128 -        }
   7.129 -    }
   7.130 -
   7.131 -    public static PythonTree getRoot(ParserResult r) {
   7.132 -        assert r instanceof PythonParserResult;
   7.133 -
   7.134 -        PythonParserResult result = (PythonParserResult)r;
   7.135 -
   7.136 -        return result.getRoot();
   7.137 -    }
   7.138 -
   7.139 -    /**
   7.140 -     * Return a range that matches the given node's source buffer range
   7.141 -     */
   7.142 -    @SuppressWarnings("unchecked")
   7.143 -    public static OffsetRange getNameRange(PythonParserResult info, PythonTree node) {
   7.144 -//        final int type = node.getType();
   7.145 -//        switch (type) {
   7.146 -//        case Token.FUNCTION: {
   7.147 -//            if (node.hasChildren()) {
   7.148 -//                for (PythonTree child = node.getFirstChild(); child != null; child = child.getNext()) {
   7.149 -//                    if (child.getType() == Token.FUNCNAME) {
   7.150 -//                        return getNameRange(child);
   7.151 -//                    }
   7.152 -//                }
   7.153 -//            }
   7.154 -//
   7.155 -//            return getRange(node);
   7.156 -//        }
   7.157 -//        case Token.NAME:
   7.158 -//        case Token.BINDNAME:
   7.159 -//        case Token.FUNCNAME:
   7.160 -//        case Token.PARAMETER:
   7.161 -//        case Token.OBJLITNAME:
   7.162 -//            int start = node.getSourceStart();
   7.163 -//            String name = node.getString();
   7.164 -//            return new OffsetRange(start, start+name.length());
   7.165 -//        case Token.CALL:
   7.166 -//            PythonTree namePythonTree = findCallNamePythonTree(node);
   7.167 -//            if (namePythonTree != null) {
   7.168 -//                return getNameRange(namePythonTree);
   7.169 -//            }
   7.170 -//        }
   7.171 -
   7.172 -        // XXX Is there a faster way to determine if it's a function,
   7.173 -        // e.g. some kind of "kind" or "id" or "type" enum attribute on the tree node
   7.174 -        if (node instanceof FunctionDef) {
   7.175 -            FunctionDef def = (FunctionDef)node;
   7.176 -            //node.getType();
   7.177 -
   7.178 -            int defStart = def.getCharStartIndex();
   7.179 -
   7.180 -            // Turns out that when you have decorators, the function start offset
   7.181 -            // -includes- the decorators which precede the "def" keyword, thus we
   7.182 -            // have to scan forwards to find the true beginning.
   7.183 -            List<expr> decorators = def.getInternalDecorator_list();
   7.184 -            if (decorators != null && decorators.size() > 0) {
   7.185 -                int maxEnd = 0;
   7.186 -                for (expr expr : decorators) {
   7.187 -                    int exprEnd = expr.getCharStopIndex();
   7.188 -                    if (exprEnd > maxEnd) {
   7.189 -                        maxEnd = exprEnd;
   7.190 -                    }
   7.191 -                }
   7.192 -                if (decorators.size() > 1) {
   7.193 -                    maxEnd++;
   7.194 -                }
   7.195 -                defStart = maxEnd;
   7.196 -
   7.197 -                // At first I was justlooking for the largest end offset of the decorators,
   7.198 -                // but if you have additional comments etc. that won't work right, so
   7.199 -                // in this case, go and look at the actual document
   7.200 -                if (info != null) {
   7.201 -                    BaseDocument doc = GsfUtilities.getDocument(info.getSnapshot().getSource().getFileObject(), false);
   7.202 -                    if (doc != null) {
   7.203 -                        int lexOffset = PythonLexerUtils.getLexerOffset(info, defStart);
   7.204 -                        int limitOffset = PythonLexerUtils.getLexerOffset(info, def.getCharStopIndex());
   7.205 -                        if (lexOffset != -1 && limitOffset != -1) {
   7.206 -                            Finder finder = new FinderFactory.StringFwdFinder("def ", true);
   7.207 -                            try {
   7.208 -                                int foundOffset = doc.find(finder, lexOffset, limitOffset);
   7.209 -                                if (foundOffset != -1) {
   7.210 -                                    defStart = foundOffset;
   7.211 -                                }
   7.212 -                            } catch (BadLocationException ex) {
   7.213 -                                Exceptions.printStackTrace(ex);
   7.214 -                            }
   7.215 -                        }
   7.216 -                    }
   7.217 -                }
   7.218 -            }
   7.219 -
   7.220 -            // HACK: There's no separate node for the name offset itself, so I need
   7.221 -            // to figure it out. For now assume that it's exactly 4 characters away
   7.222 -            // from the beginning of "def" - def plus space. If there are multiple spaces
   7.223 -            // this won't work. I ought to look in the document and ensure that the character
   7.224 -            // there in fact is the start of the name, and if not, search forwards for it.
   7.225 -            int DELTA = 4; // HACK:
   7.226 -            int start = defStart + DELTA;
   7.227 -            int end = start + def.getInternalName().length();
   7.228 -
   7.229 -            // TODO - look up offset
   7.230 -
   7.231 -            return new OffsetRange(start, end);
   7.232 -        } else if (node instanceof ClassDef) {
   7.233 -            ClassDef def = (ClassDef)node;
   7.234 -            //node.getType();
   7.235 -
   7.236 -            // HACK: There's no separate node for the name offset itself, so I need
   7.237 -            // to figure it out. For now assume that it's exactly 6 characters away
   7.238 -            // from the beginning of "class" - class plus space. If there are multiple spaces
   7.239 -            // this won't work. I ought to look in the document and ensure that the character
   7.240 -            // there in fact is the start of the name, and if not, search forwards for it.
   7.241 -            int DELTA = 6; // HACK:
   7.242 -            int start = def.getCharStartIndex() + DELTA;
   7.243 -            int end = start + def.getInternalName().length();
   7.244 -
   7.245 -            // TODO - look up offset
   7.246 -
   7.247 -            return new OffsetRange(start, end);
   7.248 -        } else if (node instanceof Attribute) {
   7.249 -            Attribute attr = (Attribute)node;
   7.250 -            return getNameRange(info, attr.getInternalValue());
   7.251 -        } else if (node instanceof Call) {
   7.252 -            Call call = (Call)node;
   7.253 -            if (call.getInternalFunc() instanceof Name) {
   7.254 -                return getNameRange(info, call.getInternalFunc());
   7.255 -            } else if (call.getInternalFunc() instanceof Attribute) {
   7.256 -                // The call name is in the value part of the name.value part
   7.257 -                Attribute attr = (Attribute)call.getInternalFunc();
   7.258 -                int start = attr.getInternalValue().getCharStopIndex() + 1; // +1: Skip .
   7.259 -                String name = attr.getInternalAttr();
   7.260 -                return new OffsetRange(start, start + name.length());
   7.261 -            } else {
   7.262 -                String name = getCallName(call);
   7.263 -                if (name != null) {
   7.264 -                    int start = call.getCharStartIndex();
   7.265 -                    return new OffsetRange(start, start + name.length());
   7.266 -                }
   7.267 -            }
   7.268 -        }
   7.269 -
   7.270 -        return getRange(node);
   7.271 -    }
   7.272 -
   7.273 -    /**
   7.274 -     * Return a range that matches the given node's source buffer range
   7.275 -     */
   7.276 -    @SuppressWarnings("unchecked")
   7.277 -    public static OffsetRange getRange(PythonTree node) {
   7.278 -        final int start = node.getCharStartIndex();
   7.279 -        final int end = node.getCharStopIndex();
   7.280 -
   7.281 -//        assert end >= start : "Invalid offsets for " + node + ": start=" + start + " and end=" + end;
   7.282 -        if (end < start) {
   7.283 -            Logger logger = Logger.getLogger(PythonAstUtils.class.getName());
   7.284 -            logger.log(Level.WARNING, "Invalid offsets for " + node + ": start=" + start + " and end=" + end);
   7.285 -            return new OffsetRange(start, start);
   7.286 -        }
   7.287 -
   7.288 -        return new OffsetRange(start, end);
   7.289 -    }
   7.290 -
   7.291 -    public static boolean isNameNode(PythonTree node) {
   7.292 -        if (node instanceof Name) {
   7.293 -            return true;
   7.294 -        }
   7.295 -
   7.296 -        return false;
   7.297 -    }
   7.298 -
   7.299 -    /** Return if a function is a staticmethod **/
   7.300 -    public static boolean isStaticMethod(PythonTree node) {
   7.301 -        if (node instanceof FunctionDef) {
   7.302 -            FunctionDef def = (FunctionDef)node;
   7.303 -            List<expr> decorators = def.getInternalDecorator_list();
   7.304 -            if (decorators != null && decorators.size() > 0) {
   7.305 -                for (expr decorator : decorators) {
   7.306 -                    if (decorator instanceof Name) {
   7.307 -                        String decoratorName = ((Name)decorator).getText();
   7.308 -                        if (decoratorName.equals("staticmethod")) { // NOI18N
   7.309 -                            return true;
   7.310 -                        }
   7.311 -                    }
   7.312 -                }
   7.313 -            }
   7.314 -        }
   7.315 -
   7.316 -        return false;
   7.317 -    }
   7.318 -
   7.319 -    /** Compute the module/class name for the given node path */
   7.320 -    public static String getFqnName(AstPath path) {
   7.321 -        StringBuilder sb = new StringBuilder();
   7.322 -
   7.323 -        Iterator<PythonTree> it = path.rootToLeaf();
   7.324 -
   7.325 -        while (it.hasNext()) {
   7.326 -            PythonTree node = it.next();
   7.327 -
   7.328 -            if (node instanceof ClassDef) {
   7.329 -                if (sb.length() > 0) {
   7.330 -                    sb.append('.'); // NOI18N
   7.331 -                }
   7.332 -                ClassDef cls = (ClassDef)node;
   7.333 -                sb.append(cls.getInternalName());
   7.334 -            }
   7.335 -        }
   7.336 -
   7.337 -        return sb.toString();
   7.338 -    }
   7.339 -
   7.340 -    /** Return the node for the local scope containing the given node */
   7.341 -    public static PythonTree getLocalScope(AstPath path) {
   7.342 -        for (PythonTree node : path) {
   7.343 -            if (node instanceof FunctionDef) {
   7.344 -                return node;
   7.345 -            }
   7.346 -        }
   7.347 -
   7.348 -        return path.root();
   7.349 -    }
   7.350 -
   7.351 -    public static PythonTree getClassScope(AstPath path) {
   7.352 -        for (PythonTree node : path) {
   7.353 -            if (node instanceof ClassDef) {
   7.354 -                return node;
   7.355 -            }
   7.356 -        }
   7.357 -
   7.358 -        return path.root();
   7.359 -    }
   7.360 -
   7.361 -    public static ClassDef getClassDef(AstPath path) {
   7.362 -        for (PythonTree node : path) {
   7.363 -            if (node instanceof ClassDef) {
   7.364 -                return (ClassDef)node;
   7.365 -            }
   7.366 -        }
   7.367 -
   7.368 -        return null;
   7.369 -    }
   7.370 -
   7.371 -    public static boolean isClassMethod(AstPath path, FunctionDef def) {
   7.372 -        // Check to see if (a) the function is inside a class, and (b) it's
   7.373 -        // not nested in a function
   7.374 -        for (PythonTree node : path) {
   7.375 -            if (node instanceof ClassDef) {
   7.376 -                return true;
   7.377 -            }
   7.378 -            // Nested method private to this one?
   7.379 -            if (node instanceof FunctionDef && node != def) {
   7.380 -                return false;
   7.381 -            }
   7.382 -        }
   7.383 -
   7.384 -        return false;
   7.385 -    }
   7.386 -
   7.387 -    public static FunctionDef getFuncDef(AstPath path) {
   7.388 -        for (PythonTree node : path) {
   7.389 -            if (node instanceof FunctionDef) {
   7.390 -                return (FunctionDef)node;
   7.391 -            }
   7.392 -        }
   7.393 -
   7.394 -        return null;
   7.395 -    }
   7.396 -
   7.397 -    /**
   7.398 -     * Return true iff this call looks like a "getter". If we're not sure,
   7.399 -     * return the default value passed into this method, unknownDefault. 
   7.400 -     */
   7.401 -    public static boolean isGetter(Call call, boolean unknownDefault) {
   7.402 -        String name = PythonAstUtils.getCallName(call);
   7.403 -        if (name == null) {
   7.404 -            return unknownDefault;
   7.405 -        }
   7.406 -
   7.407 -        return name.startsWith("get") || name.startsWith("_get"); // NOI18N
   7.408 -    }
   7.409 -
   7.410 -    public static String getCallName(Call call) {
   7.411 -        expr func = call.getInternalFunc();
   7.412 -
   7.413 -        return getExprName(func);
   7.414 -    }
   7.415 -
   7.416 -    public static String getExprName(expr type) {
   7.417 -        if (type instanceof Attribute) {
   7.418 -            Attribute attr = (Attribute)type;
   7.419 -            return attr.getInternalAttr();
   7.420 -        } else if (type instanceof Name) {
   7.421 -            return ((Name)type).getInternalId();
   7.422 -        } else if (type instanceof Call) {
   7.423 -            Call call = (Call)type;
   7.424 -            return getExprName(call.getInternalFunc());
   7.425 -            //} else if (type instanceof Str) {
   7.426 -            //    return ((Str)type).getText();
   7.427 -        } else {
   7.428 -            return null;
   7.429 -        }
   7.430 -    }
   7.431 -
   7.432 -    public static String getName(PythonTree node) {
   7.433 -        if (node instanceof Name) {
   7.434 -            return ((Name)node).getInternalId();
   7.435 -        }
   7.436 -        if (node instanceof Attribute) {
   7.437 -            Attribute attrib = (Attribute)node;
   7.438 -            String prefix = getName(attrib.getInternalValue());
   7.439 -            return (prefix + '.' + attrib.getInternalAttr());
   7.440 -        }
   7.441 -        NameVisitor visitor = new NameVisitor();
   7.442 -        try {
   7.443 -            Object result = visitor.visit(node);
   7.444 -            if (result instanceof String) {
   7.445 -                return (String)result;
   7.446 -            } else {
   7.447 -                // TODO HANDLE THIS!
   7.448 -            }
   7.449 -        } catch (Exception ex) {
   7.450 -            Exceptions.printStackTrace(ex);
   7.451 -        }
   7.452 -
   7.453 -        return null;
   7.454 -    }
   7.455 -
   7.456 -    public static List<String> getParameters(FunctionDef def) {
   7.457 -        arguments args = def.getInternalArgs();
   7.458 -        List<String> params = new ArrayList<>();
   7.459 -
   7.460 -        NameVisitor visitor = new NameVisitor();
   7.461 -
   7.462 -        for (expr e : args.getInternalArgs()) {
   7.463 -            try {
   7.464 -                Object result = visitor.visit(e);
   7.465 -                if (result instanceof String) {
   7.466 -                    params.add((String)result);
   7.467 -                } else {
   7.468 -                    // TODO HANDLE THIS!
   7.469 -                }
   7.470 -            } catch (Exception ex) {
   7.471 -                Exceptions.printStackTrace(ex);
   7.472 -            }
   7.473 -        }
   7.474 -
   7.475 -        String vararg = args.getInternalVararg();
   7.476 -        if (vararg != null) {
   7.477 -            params.add(vararg);
   7.478 -        }
   7.479 -        String kwarg = args.getInternalKwarg();
   7.480 -        if (kwarg != null) {
   7.481 -            params.add(kwarg);
   7.482 -        }
   7.483 -
   7.484 -        return params;
   7.485 -    }
   7.486 -
   7.487 -    private static Str searchForDocNode(stmt stmt) {
   7.488 -        if (stmt instanceof Expr) {
   7.489 -            Expr expr = (Expr)stmt;
   7.490 -            expr value = expr.getInternalValue();
   7.491 -            if (value instanceof Str) {
   7.492 -                return (Str)value;
   7.493 -            }
   7.494 -        }
   7.495 -
   7.496 -        return null;
   7.497 -    }
   7.498 -
   7.499 -    public static Str getDocumentationNode(PythonTree node) {
   7.500 -        // DocString processing.
   7.501 -        // See http://www.python.org/dev/peps/pep-0257/
   7.502 -
   7.503 -        // For modules, it's the first Str in the document.
   7.504 -        // For classes and methods, it's the first Str in the object.
   7.505 -        // For others, nothing.
   7.506 -
   7.507 -        if (node instanceof FunctionDef) {
   7.508 -            // Function
   7.509 -            FunctionDef def = (FunctionDef)node;
   7.510 -            List<stmt> body = def.getInternalBody();
   7.511 -            if (body != null && body.size() > 0) {
   7.512 -                return searchForDocNode(body.get(0));
   7.513 -            }
   7.514 -        } else if (node instanceof ClassDef) {
   7.515 -            // Class
   7.516 -            ClassDef def = (ClassDef)node;
   7.517 -            List<stmt> body = def.getInternalBody();
   7.518 -            if (body != null && body.size() > 0) {
   7.519 -                return searchForDocNode(body.get(0));
   7.520 -            }
   7.521 -        } else if (node instanceof Module) {
   7.522 -            // Module
   7.523 -            Module module = (Module)node;
   7.524 -            List<stmt> body = module.getInternalBody();
   7.525 -            if (body != null && body.size() > 0) {
   7.526 -                return searchForDocNode(body.get(0));
   7.527 -            }
   7.528 -        }
   7.529 -        // TODO: As per http://www.python.org/dev/peps/pep-0257/ I should
   7.530 -        // also look for "additional docstrings" (Str node following a Str node)
   7.531 -        // and Assign str nodes
   7.532 -
   7.533 -        return null;
   7.534 -    }
   7.535 -
   7.536 -    public static String getStrContent(Str str) {
   7.537 -        String doc = str.getText();
   7.538 -
   7.539 -        // Strip quotes
   7.540 -        // and U and/or R for unicode/raw string. U must always preceede r if present.
   7.541 -        if (doc.startsWith("ur") || doc.startsWith("UR") || // NOI18N
   7.542 -                doc.startsWith("Ur") || doc.startsWith("uR")) { // NOI18N
   7.543 -            doc = doc.substring(2);
   7.544 -        } else if (doc.startsWith("r") || doc.startsWith("u") || // NOI18N
   7.545 -                doc.startsWith("R") || doc.startsWith("U")) { // NOI18N
   7.546 -            doc = doc.substring(1);
   7.547 -        }
   7.548 -
   7.549 -        if (doc.startsWith("\"\"\"") && doc.endsWith("\"\"\"")) { // NOI18N
   7.550 -            doc = doc.substring(3, doc.length() - 3);
   7.551 -        } else if (doc.startsWith("r\"\"\"") && doc.endsWith("\"\"\"")) { // NOI18N
   7.552 -            doc = doc.substring(4, doc.length() - 3);
   7.553 -        } else if (doc.startsWith("'''") && doc.endsWith("'''")) { // NOI18N
   7.554 -            doc = doc.substring(3, doc.length() - 3);
   7.555 -        } else if (doc.startsWith("r'''") && doc.endsWith("'''")) { // NOI18N
   7.556 -            doc = doc.substring(4, doc.length() - 3);
   7.557 -        } else if (doc.startsWith("\"") && doc.endsWith("\"")) { // NOI18N
   7.558 -            doc = doc.substring(1, doc.length() - 1);
   7.559 -        } else if (doc.startsWith("'") && doc.endsWith("'")) { // NOI18N
   7.560 -            doc = doc.substring(1, doc.length() - 1);
   7.561 -        }
   7.562 -
   7.563 -        return doc;
   7.564 -    }
   7.565 -
   7.566 -    public static String getDocumentation(PythonTree node) {
   7.567 -        Str str = getDocumentationNode(node);
   7.568 -        if (str != null) {
   7.569 -            return getStrContent(str);
   7.570 -        }
   7.571 -
   7.572 -        return null;
   7.573 -    }
   7.574 -
   7.575 -    public static PythonTree getForeignNode(final IndexedElement o, PythonParserResult[] parserResultRet) {
   7.576 -        FileObject fo = o.getFileObject();
   7.577 -
   7.578 -        if (fo == null) {
   7.579 -            return null;
   7.580 -        }
   7.581 -        
   7.582 -        Source source = Source.create(fo);
   7.583 -        if(source == null) {
   7.584 -            return null;
   7.585 -        }
   7.586 -        final PythonParserResult[] resultHolder = new PythonParserResult[1];
   7.587 -        try {
   7.588 -            ParserManager.parse(Collections.singleton(source), new UserTask() {
   7.589 -                
   7.590 -                @Override
   7.591 -                public void run(ResultIterator resultIterator) throws Exception {
   7.592 -                    resultHolder[0] = (PythonParserResult) resultIterator.getParserResult();
   7.593 -                }
   7.594 -            });
   7.595 -        } catch (ParseException ex) {
   7.596 -            Exceptions.printStackTrace(ex);
   7.597 -        }
   7.598 -
   7.599 -        PythonParserResult info = resultHolder[0];
   7.600 -        if (parserResultRet != null) {
   7.601 -            parserResultRet[0] = info;
   7.602 -        }
   7.603 -        PythonParserResult result = getParseResult(info);
   7.604 -        if (result == null) {
   7.605 -            return null;
   7.606 -        }
   7.607 -
   7.608 -        PythonTree root = getRoot(result);
   7.609 -        if (root == null) {
   7.610 -            return null;
   7.611 -        }
   7.612 -
   7.613 -        if (o.getKind() == ElementKind.MODULE && root instanceof Module) {
   7.614 -            return root;
   7.615 -        }
   7.616 -
   7.617 -        String signature = o.getSignature();
   7.618 -
   7.619 -        if (signature == null) {
   7.620 -            return null;
   7.621 -        }
   7.622 -
   7.623 -        SymbolTable symbolTable = result.getSymbolTable();
   7.624 -        SymInfo sym = symbolTable.findBySignature(o.getKind(), signature);
   7.625 -        if (sym != null && sym.node != null) {
   7.626 -            // Temporary diagnostic checking
   7.627 -            //assert ((o.getKind() != ElementKind.CONSTRUCTOR && o.getKind() != ElementKind.METHOD) ||
   7.628 -            //        sym.node instanceof FunctionDef);
   7.629 -            //assert o.getKind() != ElementKind.CLASS || sym.node instanceof ClassDef;
   7.630 -
   7.631 -            return sym.node;
   7.632 -        }
   7.633 -
   7.634 -        // TODO - check args etc.
   7.635 -//        String name = o.getName();
   7.636 -//        boolean lookForFunction = o.getKind() == ElementKind.CONSTRUCTOR || o.getKind() == ElementKind.METHOD;
   7.637 -//        if (lookForFunction) {
   7.638 -//            for (AstElement element : result.getStructure().getElements()) {
   7.639 -//                if (element.getName().equals(name) && element.getSignature().equals(signature)) {
   7.640 -//                        return element.getNode();
   7.641 -//                    }
   7.642 -//                }
   7.643 -//            }
   7.644 -//        }
   7.645 -
   7.646 -        ElementKind kind = o.getKind();
   7.647 -        List<PythonStructureItem> items = PythonStructureScanner.analyze(info).getElements();
   7.648 -        if (items != null) {
   7.649 -            return find(items, signature, kind);
   7.650 -        } else {
   7.651 -            return null;
   7.652 -        }
   7.653 -    }
   7.654 -
   7.655 -    private static PythonTree find(List<? extends StructureItem> items, String signature, ElementKind kind) {
   7.656 -        for (StructureItem item : items) {
   7.657 -            ElementKind childKind = item.getKind();
   7.658 -            if (childKind == kind &&
   7.659 -                    item instanceof PythonStructureItem &&
   7.660 -                    signature.equals(((PythonStructureItem)item).getSignature())) {
   7.661 -                return ((PythonStructureItem)item).getNode();
   7.662 -            }
   7.663 -            if (childKind == ElementKind.CLASS && signature.contains(item.getName())) {
   7.664 -                @SuppressWarnings("unchecked")
   7.665 -                List<? extends StructureItem> children = item.getNestedItems();
   7.666 -                PythonTree result = find(children, signature, kind);
   7.667 -                if (result != null) {
   7.668 -                    return result;
   7.669 -                }
   7.670 -            }
   7.671 -        }
   7.672 -
   7.673 -        return null;
   7.674 -    }
   7.675 -
   7.676 -    public static Set<OffsetRange> getAllOffsets(PythonParserResult info, AstPath path, int lexOffset, String name, boolean abortOnFree) {
   7.677 -        if (path == null) {
   7.678 -            path = AstPath.get(PythonAstUtils.getRoot(info), lexOffset);
   7.679 -        }
   7.680 -        PythonTree scope = PythonAstUtils.getLocalScope(path);
   7.681 -        SymbolTable symbolTable = PythonAstUtils.getParseResult(info).getSymbolTable();
   7.682 -        List<PythonTree> nodes = symbolTable.getOccurrences(scope, name, abortOnFree);
   7.683 -        if (nodes == null) {
   7.684 -            return null;
   7.685 -        }
   7.686 -        Set<OffsetRange> offsets = new HashSet<>();
   7.687 -        Document doc = GsfUtilities.getDocument(info.getSnapshot().getSource().getFileObject(), false);
   7.688 -        if (doc == null) {
   7.689 -            return Collections.emptySet();
   7.690 -        }
   7.691 -        for (PythonTree node : nodes) {
   7.692 -            OffsetRange astRange = PythonAstUtils.getNameRange(info, node);
   7.693 -            OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
   7.694 -
   7.695 -            if (node instanceof Import || node instanceof ImportFrom) {
   7.696 -                // Try to find the exact spot
   7.697 -                if (abortOnFree) {
   7.698 -                    return null;
   7.699 -                } else {
   7.700 -                    lexRange = PythonLexerUtils.getImportNameOffset((BaseDocument)doc, lexRange, node, name);
   7.701 -                }
   7.702 -            } else if (abortOnFree && (node instanceof FunctionDef || node instanceof ClassDef)) {
   7.703 -                return null;
   7.704 -            }
   7.705 -
   7.706 -            if (lexRange != OffsetRange.NONE) {
   7.707 -                offsets.add(lexRange);
   7.708 -            }
   7.709 -        }
   7.710 -        // Look for type variables
   7.711 -        ScopeInfo scopeInfo = symbolTable.getScopeInfo(scope);
   7.712 -        if (scopeInfo != null) {
   7.713 -            SymInfo sym = scopeInfo.tbl.get(name);
   7.714 -            if (sym != null && sym.isVariable(false)) {
   7.715 -                // Look for type declarations that can apply to this variable
   7.716 -                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, PythonAstUtils.getRange(scope));
   7.717 -                if (lexRange != OffsetRange.NONE) {
   7.718 -                    BaseDocument bdoc = (BaseDocument)doc;
   7.719 -                    try {
   7.720 -                        bdoc.readLock(); // For TokenHierarchy usage
   7.721 -                        TokenHierarchy hi = TokenHierarchy.get(doc);
   7.722 -                        LanguagePath languagePath = LanguagePath.get(LanguagePath.get(PythonTokenId.language()), PythonCommentTokenId.language());
   7.723 -                        int startOffset = Math.min(lexRange.getStart(), doc.getLength());
   7.724 -                        if (scope instanceof Module) {
   7.725 -                            startOffset = 0; // Pick up comments before code starts
   7.726 -                        }
   7.727 -                        int endOffset = Math.min(lexRange.getEnd(), doc.getLength());
   7.728 -                        @SuppressWarnings("unchecked")
   7.729 -                        List<TokenSequence<? extends PythonCommentTokenId>> tsl = hi.tokenSequenceList(languagePath, startOffset, endOffset);
   7.730 -                        for (TokenSequence<? extends PythonCommentTokenId> ts : tsl) {
   7.731 -                            ts.moveStart();
   7.732 -                            while (ts.moveNext()) {
   7.733 -                                PythonCommentTokenId id = ts.token().id();
   7.734 -                                if (id == PythonCommentTokenId.TYPEKEY) {
   7.735 -                                    if (ts.moveNext() && // skip separator
   7.736 -                                            ts.moveNext()) {
   7.737 -                                        if (ts.token().id() == PythonCommentTokenId.VARNAME) {
   7.738 -                                            if (TokenUtilities.equals(ts.token().text(), name)) {
   7.739 -                                                int start = ts.offset();
   7.740 -                                                OffsetRange nameRange = new OffsetRange(start, start + name.length());
   7.741 -                                                offsets.add(nameRange);
   7.742 -                                            }
   7.743 -                                        }
   7.744 -                                    }
   7.745 -                                }
   7.746 -                            }
   7.747 -                        }
   7.748 -                    } finally {
   7.749 -                        bdoc.readUnlock();
   7.750 -                    }
   7.751 -
   7.752 -                }
   7.753 -            }
   7.754 -        }
   7.755 -
   7.756 -        return offsets;
   7.757 -    }
   7.758 -
   7.759 -    private static final class NameVisitor extends Visitor {
   7.760 -        @Override
   7.761 -        public Object visitName(Name name) throws Exception {
   7.762 -            return name.getInternalId();
   7.763 -        }
   7.764 -    }
   7.765 -
   7.766 -    public static Set<OffsetRange> getLocalVarOffsets(PythonParserResult info, int lexOffset) {
   7.767 -        int astOffset = getAstOffset(info, lexOffset);
   7.768 -        if (astOffset != -1) {
   7.769 -            PythonTree root = getRoot(info);
   7.770 -            if (root != null) {
   7.771 -                AstPath path = AstPath.get(root, astOffset);
   7.772 -                if (path != null) {
   7.773 -                    PythonTree closest = path.leaf();
   7.774 -                    PythonTree scope = getLocalScope(path);
   7.775 -                    String name = ((Name)closest).getInternalId();
   7.776 -
   7.777 -                    return getLocalVarOffsets(info, scope, name);
   7.778 -                }
   7.779 -            }
   7.780 -        }
   7.781 -
   7.782 -        return Collections.emptySet();
   7.783 -    }
   7.784 -
   7.785 -    public static Set<OffsetRange> getLocalVarOffsets(PythonParserResult info, PythonTree scope, String name) {
   7.786 -        LocalVarVisitor visitor = new LocalVarVisitor(info, name, false, true);
   7.787 -        try {
   7.788 -            visitor.visit(scope);
   7.789 -            return visitor.getOffsets();
   7.790 -        } catch (Exception ex) {
   7.791 -            Exceptions.printStackTrace(ex);
   7.792 -            return Collections.emptySet();
   7.793 -        }
   7.794 -    }
   7.795 -
   7.796 -    public static List<Name> getLocalVarNodes(PythonParserResult info, PythonTree scope, String name) {
   7.797 -        LocalVarVisitor visitor = new LocalVarVisitor(info, name, true, false);
   7.798 -        try {
   7.799 -            visitor.visit(scope);
   7.800 -            return visitor.getVars();
   7.801 -        } catch (Exception ex) {
   7.802 -            Exceptions.printStackTrace(ex);
   7.803 -            return Collections.emptyList();
   7.804 -        }
   7.805 -    }
   7.806 -
   7.807 -    public static List<Name> getLocalVarAssignNodes(PythonParserResult info, PythonTree scope, String name) {
   7.808 -        LocalVarAssignVisitor visitor = new LocalVarAssignVisitor(info, name, true, false);
   7.809 -        try {
   7.810 -            visitor.visit(scope);
   7.811 -            return visitor.getVars();
   7.812 -        } catch (Exception ex) {
   7.813 -            Exceptions.printStackTrace(ex);
   7.814 -            return Collections.emptyList();
   7.815 -        }
   7.816 -    }
   7.817 -
   7.818 -    private static class LocalVarVisitor extends Visitor {
   7.819 -        private List<Name> vars = new ArrayList<>();
   7.820 -        private Set<OffsetRange> offsets = new HashSet<>();
   7.821 -        private String name;
   7.822 -        private PythonParserResult info;
   7.823 -        private boolean collectNames;
   7.824 -        private boolean collectOffsets;
   7.825 -        private PythonTree parent;
   7.826 -
   7.827 -        private LocalVarVisitor(PythonParserResult info, String name, boolean collectNames, boolean collectOffsets) {
   7.828 -            this.info = info;
   7.829 -            this.name = name;
   7.830 -            this.collectNames = collectNames;
   7.831 -            this.collectOffsets = collectOffsets;
   7.832 -        }
   7.833 -
   7.834 -        @Override
   7.835 -        public void traverse(PythonTree node) throws Exception {
   7.836 -            PythonTree oldParent = parent;
   7.837 -            parent = node;
   7.838 -            super.traverse(node);
   7.839 -            parent = oldParent;
   7.840 -        }
   7.841 -
   7.842 -        @Override
   7.843 -        public Object visitName(Name node) throws Exception {
   7.844 -            if (parent instanceof Call && ((Call)parent).getInternalFunc() == node) {
   7.845 -                return super.visitName(node);
   7.846 -            }
   7.847 -
   7.848 -            if ((name == null && !PythonUtils.isClassName(node.getInternalId(), false)) ||
   7.849 -                    (name != null && name.equals(node.getInternalId()))) {
   7.850 -                if (collectOffsets) {
   7.851 -                    OffsetRange astRange = PythonAstUtils.getNameRange(info, node);
   7.852 -                    OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
   7.853 -                    if (lexRange != OffsetRange.NONE) {
   7.854 -                        offsets.add(astRange);
   7.855 -                    }
   7.856 -                }
   7.857 -                if (collectNames) {
   7.858 -                    vars.add(node);
   7.859 -                }
   7.860 -            }
   7.861 -
   7.862 -            return super.visitName(node);
   7.863 -        }
   7.864 -
   7.865 -        public Set<OffsetRange> getOffsets() {
   7.866 -            return offsets;
   7.867 -        }
   7.868 -
   7.869 -        public List<Name> getVars() {
   7.870 -            return vars;
   7.871 -        }
   7.872 -    }
   7.873 -
   7.874 -    private static class LocalVarAssignVisitor extends Visitor {
   7.875 -        private List<Name> vars = new ArrayList<>();
   7.876 -        private Set<OffsetRange> offsets = new HashSet<>();
   7.877 -        private String name;
   7.878 -        private PythonParserResult info;
   7.879 -        private boolean collectNames;
   7.880 -        private boolean collectOffsets;
   7.881 -        private PythonTree parent;
   7.882 -
   7.883 -        private LocalVarAssignVisitor(PythonParserResult info, String name, boolean collectNames, boolean collectOffsets) {
   7.884 -            this.info = info;
   7.885 -            this.name = name;
   7.886 -            this.collectNames = collectNames;
   7.887 -            this.collectOffsets = collectOffsets;
   7.888 -        }
   7.889 -
   7.890 -        @Override
   7.891 -        public Object visitName(Name node) throws Exception {
   7.892 -            if (parent instanceof FunctionDef || parent instanceof Assign) {
   7.893 -                if ((name == null && !PythonUtils.isClassName(node.getInternalId(), false)) ||
   7.894 -                        (name != null && name.equals(node.getInternalId()))) {
   7.895 -                    if (collectOffsets) {
   7.896 -                        OffsetRange astRange = PythonAstUtils.getNameRange(info, node);
   7.897 -                        OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
   7.898 -                        if (lexRange != OffsetRange.NONE) {
   7.899 -                            offsets.add(astRange);
   7.900 -                        }
   7.901 -                    }
   7.902 -                    if (collectNames) {
   7.903 -                        vars.add(node);
   7.904 -                    }
   7.905 -                }
   7.906 -            }
   7.907 -
   7.908 -            return super.visitName(node);
   7.909 -        }
   7.910 -
   7.911 -        @Override
   7.912 -        public void traverse(PythonTree node) throws Exception {
   7.913 -            PythonTree oldParent = parent;
   7.914 -            parent = node;
   7.915 -            super.traverse(node);
   7.916 -            parent = oldParent;
   7.917 -        }
   7.918 -
   7.919 -        public Set<OffsetRange> getOffsets() {
   7.920 -            return offsets;
   7.921 -        }
   7.922 -
   7.923 -        public List<Name> getVars() {
   7.924 -            return vars;
   7.925 -        }
   7.926 -    }
   7.927 -
   7.928 -    /** Collect nodes of the given types (node.nodeId==NodeTypes.x) under the given root */
   7.929 -    public static void addNodesByType(PythonTree root, Class[] nodeClasses, List<PythonTree> result) {
   7.930 -        try {
   7.931 -            new NodeTypeVisitor(result, nodeClasses).visit(root);
   7.932 -        } catch (Exception ex) {
   7.933 -            Exceptions.printStackTrace(ex);
   7.934 -        }
   7.935 -    }
   7.936 -
   7.937 -    private static class NodeTypeVisitor extends Visitor {
   7.938 -        private Class[] nodeClasses;
   7.939 -        private List<PythonTree> result;
   7.940 -
   7.941 -        NodeTypeVisitor(List<PythonTree> result, Class[] nodeClasses) {
   7.942 -            this.result = result;
   7.943 -            this.nodeClasses = nodeClasses;
   7.944 -        }
   7.945 -
   7.946 -        @Override
   7.947 -        public void traverse(PythonTree node) throws Exception {
   7.948 -            for (Class nodeClasse : nodeClasses) {
   7.949 -                if (node.getClass() == nodeClasse) {
   7.950 -                    result.add(node);
   7.951 -                    break;
   7.952 -                }
   7.953 -            }
   7.954 -
   7.955 -            super.traverse(node);
   7.956 -        }
   7.957 -    }
   7.958 -
   7.959 -    public static Name getParentClassFromNode(AstPath path, PythonTree from, String name) {
   7.960 -        ClassDef curClass = (ClassDef)path.getTypedAncestor(ClassDef.class, from);
   7.961 -        if (curClass == null) {
   7.962 -            return null;
   7.963 -        }
   7.964 -
   7.965 -        List<expr> baseClasses = curClass.getInternalBases();
   7.966 -        if (baseClasses == null) {
   7.967 -            return null; // no inheritance ;
   7.968 -        }
   7.969 -        int ii = 0;
   7.970 -        while (ii < baseClasses.size()) {
   7.971 -            if (baseClasses.get(ii) instanceof Name) {
   7.972 -                Name cur = (Name)baseClasses.get(ii);
   7.973 -                if (cur.getInternalId().equals(name)) {
   7.974 -                    return cur;
   7.975 -                }
   7.976 -            }
   7.977 -            ii++;
   7.978 -        }
   7.979 -        return null;
   7.980 -    }
   7.981 -
   7.982 -    /**
   7.983 -     * Look for the caret offset in the parameter list; return the
   7.984 -     * index of the parameter that contains it.
   7.985 -     */
   7.986 -    public static int findArgumentIndex(Call call, int astOffset, AstPath path) {
   7.987 -
   7.988 -        // On the name part in the call rather than the args?
   7.989 -        if (astOffset <= call.getInternalFunc().getCharStopIndex()) {
   7.990 -            return -1;
   7.991 -        }
   7.992 -        List<expr> args = call.getInternalArgs();
   7.993 -        if (args != null) {
   7.994 -            int index = 0;
   7.995 -            for (; index < args.size(); index++) {
   7.996 -                expr et = args.get(index);
   7.997 -                if (et.getCharStopIndex() >= astOffset) {
   7.998 -                    return index;
   7.999 -                }
  7.1000 -            }
  7.1001 -        }
  7.1002 -
  7.1003 -        // TODO what about the other stuff in there -- 
  7.1004 -        //call.keywords;
  7.1005 -        //call.kwargs;
  7.1006 -        //call.starargs;
  7.1007 -
  7.1008 -        return -1;
  7.1009 -    }
  7.1010 -}
     8.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonCodeCompleter.java	Sat Sep 12 23:03:15 2015 -0700
     8.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonCodeCompleter.java	Sun Sep 13 11:47:42 2015 +0200
     8.3 @@ -30,6 +30,12 @@
     8.4   */
     8.5  package org.netbeans.modules.python.editor;
     8.6  
     8.7 +import org.netbeans.modules.python.source.PythonUtils;
     8.8 +import org.netbeans.modules.python.source.AstPath;
     8.9 +import org.netbeans.modules.python.source.PythonIndex;
    8.10 +import org.netbeans.modules.python.source.RstFormatter;
    8.11 +import org.netbeans.modules.python.source.PythonAstUtils;
    8.12 +import org.netbeans.modules.python.source.PythonParserResult;
    8.13  import java.util.ArrayList;
    8.14  import java.util.Collections;
    8.15  import java.util.HashSet;
    8.16 @@ -45,12 +51,12 @@
    8.17  import javax.swing.text.JTextComponent;
    8.18  import org.netbeans.api.editor.EditorRegistry;
    8.19  import org.netbeans.api.editor.completion.Completion;
    8.20 -import org.netbeans.modules.python.editor.elements.Element;
    8.21 -import org.netbeans.modules.python.editor.elements.IndexedElement;
    8.22 -import org.netbeans.modules.python.editor.elements.IndexedMethod;
    8.23 -import org.netbeans.modules.python.editor.lexer.Call;
    8.24 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
    8.25 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
    8.26 +import org.netbeans.modules.python.source.elements.Element;
    8.27 +import org.netbeans.modules.python.source.elements.IndexedElement;
    8.28 +import org.netbeans.modules.python.source.elements.IndexedMethod;
    8.29 +import org.netbeans.modules.python.source.lexer.Call;
    8.30 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
    8.31 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
    8.32  import org.netbeans.api.lexer.Token;
    8.33  import org.netbeans.api.lexer.TokenHierarchy;
    8.34  import org.netbeans.api.lexer.TokenId;
    8.35 @@ -74,13 +80,13 @@
    8.36  import org.netbeans.modules.editor.indent.api.IndentUtils;
    8.37  import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
    8.38  import org.netbeans.modules.python.api.PythonMIMEResolver;
    8.39 -import org.netbeans.modules.python.editor.PythonParser.Sanitize;
    8.40 -import org.netbeans.modules.python.editor.elements.IndexedPackage;
    8.41 -import org.netbeans.modules.python.editor.imports.ImportManager;
    8.42 -import org.netbeans.modules.python.editor.lexer.PythonCommentTokenId;
    8.43 -import org.netbeans.modules.python.editor.lexer.PythonLexer;
    8.44 -import org.netbeans.modules.python.editor.options.CodeStyle;
    8.45 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
    8.46 +import org.netbeans.modules.python.source.PythonParser.Sanitize;
    8.47 +import org.netbeans.modules.python.source.elements.IndexedPackage;
    8.48 +import org.netbeans.modules.python.source.ImportManager;
    8.49 +import org.netbeans.modules.python.source.lexer.PythonCommentTokenId;
    8.50 +import org.netbeans.modules.python.source.lexer.PythonLexer;
    8.51 +import org.netbeans.modules.python.source.CodeStyle;
    8.52 +import org.netbeans.modules.python.source.scopes.SymbolTable;
    8.53  import org.openide.filesystems.FileObject;
    8.54  import org.openide.util.Exceptions;
    8.55  import org.openide.util.ImageUtilities;
    8.56 @@ -305,8 +311,8 @@
    8.57                  return completionResult;
    8.58              }
    8.59  
    8.60 -            org.netbeans.modules.python.editor.lexer.Call call =
    8.61 -                    org.netbeans.modules.python.editor.lexer.Call.getCallType(doc, th, lexOffset);
    8.62 +            org.netbeans.modules.python.source.lexer.Call call =
    8.63 +                    org.netbeans.modules.python.source.lexer.Call.getCallType(doc, th, lexOffset);
    8.64              request.call = call;
    8.65  
    8.66              if ((fqn != null) &&
    8.67 @@ -1088,7 +1094,7 @@
    8.68          PythonParserResult info = request.result;
    8.69          String prefix = request.prefix;
    8.70          QuerySupport.Kind kind = request.kind;
    8.71 -        org.netbeans.modules.python.editor.lexer.Call call = request.call;
    8.72 +        org.netbeans.modules.python.source.lexer.Call call = request.call;
    8.73  
    8.74          // Only call local and inherited methods if we don't have an LHS, such as Foo::
    8.75          if (call.getLhs() == null) {
    8.76 @@ -1187,7 +1193,7 @@
    8.77       * @todo Look for self or this or super; these should be limited to inherited.
    8.78       */
    8.79      private boolean completeObjectMethod(List<CompletionProposal> proposals, CompletionRequest request, String fqn,
    8.80 -            org.netbeans.modules.python.editor.lexer.Call call) {
    8.81 +            org.netbeans.modules.python.source.lexer.Call call) {
    8.82  
    8.83          PythonIndex index = request.index;
    8.84          String prefix = request.prefix;
    8.85 @@ -1211,8 +1217,8 @@
    8.86          if ((index != null) && (ts != null)) {
    8.87              boolean skipPrivate = true;
    8.88  
    8.89 -            if ((call == org.netbeans.modules.python.editor.lexer.Call.LOCAL) ||
    8.90 -                    (call == org.netbeans.modules.python.editor.lexer.Call.NONE)) {
    8.91 +            if ((call == org.netbeans.modules.python.source.lexer.Call.LOCAL) ||
    8.92 +                    (call == org.netbeans.modules.python.source.lexer.Call.NONE)) {
    8.93                  return false;
    8.94              }
    8.95  
    8.96 @@ -1563,6 +1569,41 @@
    8.97  
    8.98          return true;
    8.99      }
   8.100 +    
   8.101 +    // Keywords - according to http://docs.python.org/ref/keywords.html
   8.102 +    static final String[] PYTHON_KEYWORDS = new String[]{
   8.103 +        "and", // NOI18N
   8.104 +        "as", // NOI18N
   8.105 +        "assert", // NOI18N
   8.106 +        "break", // NOI18N
   8.107 +        "class", // NOI18N
   8.108 +        "continue", // NOI18N
   8.109 +        "def", // NOI18N
   8.110 +        "del", // NOI18N
   8.111 +        "elif", // NOI18N
   8.112 +        "else", // NOI18N
   8.113 +        "except", // NOI18N
   8.114 +        "exec", // NOI18N
   8.115 +        "finally", // NOI18N
   8.116 +        "for", // NOI18N
   8.117 +        "from", // NOI18N
   8.118 +        "global", // NOI18N
   8.119 +        "if", // NOI18N
   8.120 +        "import", // NOI18N
   8.121 +        "in", // NOI18N
   8.122 +        "is", // NOI18N
   8.123 +        "lambda", // NOI18N
   8.124 +        "not", // NOI18N
   8.125 +        "or", // NOI18N
   8.126 +        "pass", // NOI18N
   8.127 +        "print", // NOI18N
   8.128 +        "raise", // NOI18N
   8.129 +        "return", // NOI18N
   8.130 +        "try", // NOI18N
   8.131 +        "while", // NOI18N
   8.132 +        "with", // NOI18N
   8.133 +        "yield", // NOI18N
   8.134 +    };
   8.135  
   8.136      private void completeKeywords(List<CompletionProposal> proposals, CompletionRequest request) {
   8.137          // No keywords possible in the RHS of a call (except for "this"?)
   8.138 @@ -1573,8 +1614,8 @@
   8.139          String prefix = request.prefix;
   8.140  
   8.141  
   8.142 -        for (int i = 0, n = PythonUtils.PYTHON_KEYWORDS.length; i < n; i++) {
   8.143 -            String keyword = PythonUtils.PYTHON_KEYWORDS[i];
   8.144 +        for (int i = 0, n = PYTHON_KEYWORDS.length; i < n; i++) {
   8.145 +            String keyword = PYTHON_KEYWORDS[i];
   8.146              if (startsWith(keyword, prefix)) {
   8.147                  KeywordItem item = new KeywordItem(keyword, null, request, Integer.toString(10000 + i));
   8.148  
   8.149 @@ -1830,7 +1871,7 @@
   8.150          private PythonParserResult result;
   8.151          private QueryType queryType;
   8.152          private FileObject fileObject;
   8.153 -        private org.netbeans.modules.python.editor.lexer.Call call;
   8.154 +        private org.netbeans.modules.python.source.lexer.Call call;
   8.155          private boolean inCall;
   8.156          private String fqn;
   8.157          private String searchUrl;
   8.158 @@ -2601,7 +2642,7 @@
   8.159  
   8.160              if (item instanceof PythonCompletionItem) {
   8.161                  PythonCompletionItem pythonItem = (PythonCompletionItem)item;
   8.162 -                org.netbeans.modules.python.editor.lexer.Call call = pythonItem.request.call;
   8.163 +                org.netbeans.modules.python.source.lexer.Call call = pythonItem.request.call;
   8.164                  // Only insert imports when we add new top-level items
   8.165                  if (pythonItem.getAddImport() != null) {
   8.166                      String module = pythonItem.getAddImport();
     9.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonDeclarationFinder.java	Sat Sep 12 23:03:15 2015 -0700
     9.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonDeclarationFinder.java	Sun Sep 13 11:47:42 2015 +0200
     9.3 @@ -30,6 +30,11 @@
     9.4   */
     9.5  package org.netbeans.modules.python.editor;
     9.6  
     9.7 +import org.netbeans.modules.python.source.PythonUtils;
     9.8 +import org.netbeans.modules.python.source.AstPath;
     9.9 +import org.netbeans.modules.python.source.PythonIndex;
    9.10 +import org.netbeans.modules.python.source.PythonAstUtils;
    9.11 +import org.netbeans.modules.python.source.PythonParserResult;
    9.12  import java.net.MalformedURLException;
    9.13  import java.net.URL;
    9.14  import java.util.Collections;
    9.15 @@ -38,11 +43,11 @@
    9.16  import java.util.Set;
    9.17  import javax.swing.text.BadLocationException;
    9.18  import javax.swing.text.Document;
    9.19 -import org.netbeans.modules.python.editor.elements.IndexedElement;
    9.20 -import org.netbeans.modules.python.editor.elements.IndexedMethod;
    9.21 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
    9.22 -import org.netbeans.modules.python.editor.lexer.PythonStringTokenId;
    9.23 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
    9.24 +import org.netbeans.modules.python.source.elements.IndexedElement;
    9.25 +import org.netbeans.modules.python.source.elements.IndexedMethod;
    9.26 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
    9.27 +import org.netbeans.modules.python.source.lexer.PythonStringTokenId;
    9.28 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
    9.29  import org.netbeans.api.lexer.Token;
    9.30  import org.netbeans.api.lexer.TokenHierarchy;
    9.31  import org.netbeans.api.lexer.TokenId;
    9.32 @@ -57,9 +62,9 @@
    9.33  import org.netbeans.modules.csl.api.OffsetRange;
    9.34  import org.netbeans.modules.csl.spi.ParserResult;
    9.35  import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
    9.36 -import org.netbeans.modules.python.editor.lexer.PythonLexer;
    9.37 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
    9.38 -import org.netbeans.modules.python.editor.scopes.SymInfo;
    9.39 +import org.netbeans.modules.python.source.lexer.PythonLexer;
    9.40 +import org.netbeans.modules.python.source.scopes.SymbolTable;
    9.41 +import org.netbeans.modules.python.source.scopes.SymInfo;
    9.42  import org.openide.filesystems.FileObject;
    9.43  import org.openide.filesystems.FileStateInvalidException;
    9.44  import org.openide.util.Exceptions;
    9.45 @@ -406,8 +411,8 @@
    9.46              }
    9.47  
    9.48              final TokenHierarchy<Document> th = TokenHierarchy.get(document);
    9.49 -            org.netbeans.modules.python.editor.lexer.Call call =
    9.50 -                    org.netbeans.modules.python.editor.lexer.Call.getCallType(doc, th, lexOffset);
    9.51 +            org.netbeans.modules.python.source.lexer.Call call =
    9.52 +                    org.netbeans.modules.python.source.lexer.Call.getCallType(doc, th, lexOffset);
    9.53              
    9.54              FileObject fileObject = info.getSnapshot().getSource().getFileObject();
    9.55  
    10.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonExample.py	Sat Sep 12 23:03:15 2015 -0700
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,10 +0,0 @@
    10.4 -"""Sample Module"""
    10.5 -import foo
    10.6 -CONSTANT = "VALUE"
    10.7 -
    10.8 -class Foo(Bar):
    10.9 -    """Class doc"""
   10.10 -
   10.11 -    def __init__(self,args=''):
   10.12 -        # Comment
   10.13 -        print 1+2.0
    11.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonFormatter.java	Sat Sep 12 23:03:15 2015 -0700
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,657 +0,0 @@
    11.4 -/*
    11.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    11.6 - *
    11.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    11.8 - *
    11.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   11.10 - * Other names may be trademarks of their respective owners.
   11.11 - *
   11.12 - * The contents of this file are subject to the terms of either the GNU
   11.13 - * General Public License Version 2 only ("GPL") or the Common
   11.14 - * Development and Distribution License("CDDL") (collectively, the
   11.15 - * "License"). You may not use this file except in compliance with the
   11.16 - * License. You can obtain a copy of the License at
   11.17 - * http://www.netbeans.org/cddl-gplv2.html
   11.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   11.19 - * specific language governing permissions and limitations under the
   11.20 - * License.  When distributing the software, include this License Header
   11.21 - * Notice in each file and include the License file at
   11.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   11.23 - * particular file as subject to the "Classpath" exception as provided
   11.24 - * by Oracle in the GPL Version 2 section of the License file that
   11.25 - * accompanied this code. If applicable, add the following below the
   11.26 - * License Header, with the fields enclosed by brackets [] replaced by
   11.27 - * your own identifying information:
   11.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   11.29 - *
   11.30 - * If you wish your version of this file to be governed by only the CDDL
   11.31 - * or only the GPL Version 2, indicate your decision by adding
   11.32 - * "[Contributor] elects to include this software in this distribution
   11.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   11.34 - * single choice of license, a recipient has the option to distribute
   11.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   11.36 - * to extend the choice of license to its licensees as provided above.
   11.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   11.38 - * Version 2 license, then the option applies only if the new code is
   11.39 - * made subject to such option by the copyright holder.
   11.40 - *
   11.41 - * Contributor(s):
   11.42 - *
   11.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   11.44 - */
   11.45 -package org.netbeans.modules.python.editor;
   11.46 -
   11.47 -import java.util.ArrayList;
   11.48 -import java.util.Collections;
   11.49 -import java.util.HashMap;
   11.50 -import java.util.List;
   11.51 -import java.util.Map;
   11.52 -import javax.swing.text.BadLocationException;
   11.53 -import javax.swing.text.Document;
   11.54 -import javax.swing.text.JTextComponent;
   11.55 -import org.netbeans.api.editor.EditorRegistry;
   11.56 -import org.netbeans.api.lexer.TokenSequence;
   11.57 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   11.58 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   11.59 -import org.netbeans.api.lexer.Token;
   11.60 -import org.netbeans.api.lexer.TokenId;
   11.61 -import org.netbeans.api.lexer.TokenUtilities;
   11.62 -import org.netbeans.editor.BaseDocument;
   11.63 -import org.netbeans.editor.Utilities;
   11.64 -import org.netbeans.modules.csl.api.EditList;
   11.65 -import org.netbeans.modules.csl.api.Formatter;
   11.66 -import org.netbeans.modules.csl.spi.GsfUtilities;
   11.67 -import org.netbeans.modules.csl.spi.ParserResult;
   11.68 -import org.netbeans.modules.editor.indent.api.IndentUtils;
   11.69 -import org.netbeans.modules.editor.indent.spi.Context;
   11.70 -import org.netbeans.modules.python.editor.imports.ImportManager;
   11.71 -import org.netbeans.modules.python.editor.options.CodeStyle;
   11.72 -import org.openide.util.Exceptions;
   11.73 -
   11.74 -/**
   11.75 - * Implement formatting for Python. Since there are no {}'s etc. to uniquely
   11.76 - * impose indentation on Python, this formatter really just tries to enforce
   11.77 - * spaces-versus-tabs, and indentation width. E.g. it uses the existing indentation
   11.78 - * to determine whether the next line should be idented more, same or less as the
   11.79 - * current line and then enforces the current space and indent size settings.
   11.80 - *
   11.81 - * @todo Implement pretty printing: inserting newlines, removing spaces inside
   11.82 - *  parentheses, etc. See the recommendations in
   11.83 - *   http://www.python.org/dev/peps/pep-0008/
   11.84 - *  Do import statement cleanup too.
   11.85 - * @todo Line up comment lines (# as a suffix, continued from a previous line)
   11.86 - * @todo Handle continuation lines with extra indentation
   11.87 - * @todo Line up list initializations better?
   11.88 - * 
   11.89 - * @author Tor Norbye
   11.90 - */
   11.91 -public class PythonFormatter implements Formatter {
   11.92 -    private int indentSize;
   11.93 -    private int continuationIndentSize;
   11.94 -    private CodeStyle codeStyle;
   11.95 -
   11.96 -    public PythonFormatter() {
   11.97 -    }
   11.98 -
   11.99 -    public PythonFormatter(CodeStyle codeStyle) {
  11.100 -        this.codeStyle = codeStyle;
  11.101 -    }
  11.102 -
  11.103 -    @Override
  11.104 -    public void reformat(Context context, ParserResult compilationInfo) {
  11.105 -
  11.106 -        // No AST pretty printing yet
  11.107 -        // I should offer to go and do space insert/removal around commas, parentheses, etc.
  11.108 -        //  as well as balancing long argument lists across lines
  11.109 -        Document document = context.document();
  11.110 -        int startOffset = context.startOffset();
  11.111 -        int endOffset = context.endOffset();
  11.112 -
  11.113 -        reformat(context, document, startOffset, endOffset, (PythonParserResult) compilationInfo);
  11.114 -    }
  11.115 -
  11.116 -    public void reformat(final Context context, Document document, int startOffset, int endOffset, PythonParserResult info) {
  11.117 -        if (codeStyle == null) {
  11.118 -            codeStyle = CodeStyle.getDefault(context.document());
  11.119 -        }
  11.120 -        if (info != null && codeStyle != null && codeStyle.formatImports() && !GsfUtilities.isCodeTemplateEditing(document) &&
  11.121 -                PythonAstUtils.getParseResult(info) != null) {
  11.122 -            new ImportManager(info, (BaseDocument)document, codeStyle).cleanup(null, startOffset, endOffset, false);
  11.123 -        }
  11.124 -
  11.125 -        if (codeStyle != null) {
  11.126 -            cleanup(document, info, startOffset, endOffset);
  11.127 -        }
  11.128 -
  11.129 -        reindent(context, document, startOffset, endOffset);
  11.130 -    }
  11.131 -
  11.132 -    @Override
  11.133 -    public boolean needsParserResult() {
  11.134 -//        if (SourceUtils.isScanInProgress()) {
  11.135 -//            return false;
  11.136 -//        }
  11.137 -
  11.138 -        // If we're going to format imports, then yes, we need the parser result
  11.139 -        JTextComponent target = EditorRegistry.lastFocusedComponent();
  11.140 -        if (target != null) {
  11.141 -            CodeStyle cs = CodeStyle.getDefault(target.getDocument());
  11.142 -            return cs != null ? cs.formatImports() : false;
  11.143 -        }
  11.144 -        return false;
  11.145 -    }
  11.146 -
  11.147 -    @Override
  11.148 -    public int indentSize() {
  11.149 -        // 4 spaces: See http://www.python.org/dev/peps/pep-0008/
  11.150 -        return 4;
  11.151 -    }
  11.152 -
  11.153 -    @Override
  11.154 -    public int hangingIndentSize() {
  11.155 -        return 4;
  11.156 -    }
  11.157 -
  11.158 -    // Challenge: Two inconsistently formatted
  11.159 -    // Idea: Given a list of offsets and indentation, produce a graph (or recurse) where I mark all
  11.160 -    // siblings the exact same level
  11.161 -
  11.162 -    // Algorithm:
  11.163 -    //   Find smallest indent: That's the top level
  11.164 -    //   Build a graph? Each indent line.
  11.165 -    //
  11.166 -    @Override
  11.167 -    public void reindent(final Context context) {
  11.168 -        Document document = context.document();
  11.169 -        int startOffset = context.startOffset();
  11.170 -        int endOffset = context.endOffset();
  11.171 -
  11.172 -        reindent(context, document, startOffset, endOffset);
  11.173 -    }
  11.174 -
  11.175 -    @SuppressWarnings("deprecation") // For doc.getFormatter()
  11.176 -    public void reindent(final Context context, Document document, int startOffset, int endOffset) {
  11.177 -        endOffset = Math.min(endOffset, document.getLength());
  11.178 -        startOffset = Math.min(startOffset, endOffset);
  11.179 -
  11.180 -        continuationIndentSize = indentSize = IndentUtils.indentLevelSize(document);
  11.181 -
  11.182 -
  11.183 -        final BaseDocument doc = (BaseDocument)document;
  11.184 -        try {
  11.185 -            // Plan: Go through the lines, one by one, and compute the indentation levels relative to each other,
  11.186 -            // then normalize them (except inside strings), then apply!!
  11.187 -            // Also track whether we are used for newline indentation and if so, do smart bracket stuff
  11.188 -
  11.189 -            // Current indentation for the given line. -1 means that it should be left alone (e.g.
  11.190 -            // we don't mess with multiline string literals.
  11.191 -            final List<Integer> offsets = new ArrayList<>();
  11.192 -
  11.193 -            // Current indentation for the given line. -1 means that it should be left alone (e.g.
  11.194 -            // we don't mess with multiline string literals. Other negative numbers are offsets
  11.195 -            // pointing at a particular left parenthesis that this line should be aligned with
  11.196 -            final List<Integer> indentation = new ArrayList<>();
  11.197 -            final List<Integer> lParenOffsets = new ArrayList<>();
  11.198 -
  11.199 -            try {
  11.200 -                doc.readLock(); // For token hierarchy usage
  11.201 -
  11.202 -                TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(doc, startOffset);
  11.203 -
  11.204 -                int currentOffset = Utilities.getRowStart(doc, startOffset);
  11.205 -                int balance = 0;
  11.206 -                while (currentOffset <= endOffset) {
  11.207 -                    if (!(Utilities.isRowEmpty(doc, currentOffset) || Utilities.isRowWhite(doc, currentOffset))) {
  11.208 -                        Token<? extends PythonTokenId> token = PythonLexerUtils.getToken(doc, currentOffset);
  11.209 -                        int indent = GsfUtilities.getLineIndent(doc, currentOffset);
  11.210 -                        if (token != null) {
  11.211 -                            if (token.id() == PythonTokenId.STRING_LITERAL || token.id() == PythonTokenId.STRING_END) {
  11.212 -                                indent = -1;
  11.213 -                            }
  11.214 -                        }
  11.215 -
  11.216 -                        if (indent != -1) {
  11.217 -                            if (balance <= 0) {
  11.218 -                                indentation.add(indent);
  11.219 -                                offsets.add(currentOffset);
  11.220 -                            } else {
  11.221 -                                assert balance <= lParenOffsets.size();
  11.222 -                                int parenOffset = lParenOffsets.get(lParenOffsets.size()-balance);
  11.223 -                                indentation.add(-parenOffset);
  11.224 -                                offsets.add(currentOffset);
  11.225 -                            }
  11.226 -                        }
  11.227 -                    }
  11.228 -
  11.229 -                    // TODO - look up the tokens to make sure we don't have a problem with literal nodes
  11.230 -
  11.231 -                    if (currentOffset > doc.getLength()) {
  11.232 -                        break;
  11.233 -                    }
  11.234 -
  11.235 -                    // Update the line balance
  11.236 -                    int begin = Utilities.getRowStart(doc, currentOffset);
  11.237 -                    int end = Utilities.getRowEnd(doc, currentOffset);
  11.238 -
  11.239 -                    ts.move(begin);
  11.240 -
  11.241 -                    if (ts.moveNext()) {
  11.242 -                        do {
  11.243 -                            Token<? extends PythonTokenId> token = ts.token();
  11.244 -                            TokenId id = token.id();
  11.245 -
  11.246 -                            if (id == PythonTokenId.LPAREN) {
  11.247 -                                balance++;
  11.248 -                                lParenOffsets.add(ts.offset());
  11.249 -                            } else if (id == PythonTokenId.RPAREN) {
  11.250 -                                balance--;
  11.251 -                                if (!lParenOffsets.isEmpty()) {
  11.252 -                                    lParenOffsets.remove(lParenOffsets.size()-1);
  11.253 -                                }
  11.254 -                            }
  11.255 -                        } while (ts.moveNext() && (ts.offset() <= end));
  11.256 -                    }
  11.257 -
  11.258 -                    currentOffset = Utilities.getRowEnd(doc, currentOffset) + 1;
  11.259 -                }
  11.260 -            } finally {
  11.261 -                doc.readUnlock();
  11.262 -            }
  11.263 -
  11.264 -            // Nothing to do
  11.265 -            if (offsets.size() == 0) {
  11.266 -                return;
  11.267 -            }
  11.268 -
  11.269 -            assert indentation.size() == offsets.size();
  11.270 -
  11.271 -            final Map<Integer, Integer> offsetToLevel = new HashMap<>();
  11.272 -            final Map<Integer,Integer> offsetToIndex = new HashMap<>();
  11.273 -            List<Integer> parentIndentations = new ArrayList<>();
  11.274 -            int currentParentIndent = -1;
  11.275 -            int currentLevel = -1;
  11.276 -
  11.277 -            int firstIndent = indentation.get(0);
  11.278 -            List<Integer> sorted = new ArrayList<>(indentation);
  11.279 -            Collections.sort(sorted);
  11.280 -            // Attempt to shift the computed indentation to fit the right indentation levels
  11.281 -            // that are currently in the file?
  11.282 -            int firstNonNeg = 0;
  11.283 -            for (; firstNonNeg < sorted.size(); firstNonNeg++) {
  11.284 -                if (sorted.get(firstNonNeg) >= 0) {
  11.285 -                    break;
  11.286 -                }
  11.287 -            }
  11.288 -            boolean shiftToCurrent = true;
  11.289 -            if (firstIndent > sorted.get(firstNonNeg)) {
  11.290 -                shiftToCurrent = false;
  11.291 -                // The start is not at the top level... e.g. we have something like
  11.292 -                //      foo
  11.293 -                //   else
  11.294 -                //      bar
  11.295 -                // (e.g. we are formatting a fragment of code which doesn't include
  11.296 -                // the top). Here we need to find the "true" top levels, so we
  11.297 -                // push levels on to the stack
  11.298 -                int prev = -1;
  11.299 -                for (int indent : sorted) {
  11.300 -                    if (prev == indent) {
  11.301 -                        continue;
  11.302 -                    }
  11.303 -                    prev = indent;
  11.304 -                    if (indent < firstIndent) {
  11.305 -                        parentIndentations.add(currentParentIndent);
  11.306 -                        currentParentIndent = indent;
  11.307 -                        currentLevel++;
  11.308 -                    } else {
  11.309 -                        break;
  11.310 -                    }
  11.311 -                }
  11.312 -            }
  11.313 -
  11.314 -
  11.315 -            // TODO: What if I start in the middle of an expression such that I outdent
  11.316 -            // more than I indent? I have to build up the index levels if necessary
  11.317 -            // Go count popping levels
  11.318 -
  11.319 -            for (int i = 0, n = offsets.size(); i < n; i++) {
  11.320 -                int offset = offsets.get(i);
  11.321 -                int indent = indentation.get(i);
  11.322 -                if (indent == -1) {
  11.323 -                    // Leave line alone
  11.324 -                    offsetToLevel.put(offset, -1);
  11.325 -                    continue;
  11.326 -                }
  11.327 -                offsetToIndex.put(offset, i);
  11.328 -
  11.329 -                if (indent < 0) {
  11.330 -                    // Want to keep everything the same as the prev, plus delta
  11.331 -                } else if (indent > currentParentIndent) {
  11.332 -                    // New level
  11.333 -                    currentLevel++;
  11.334 -                    parentIndentations.add(currentParentIndent);
  11.335 -                    currentParentIndent = indent;
  11.336 -                } else if (indent < currentParentIndent) {
  11.337 -                    while (currentParentIndent > indent) {
  11.338 -                        currentLevel--;
  11.339 -                        if (parentIndentations.size() > 0) {
  11.340 -                            currentParentIndent = parentIndentations.remove(parentIndentations.size() - 1);
  11.341 -                        } else {
  11.342 -                            currentParentIndent = indent;
  11.343 -                        }
  11.344 -                    }
  11.345 -                }
  11.346 -
  11.347 -                offsetToLevel.put(offset, currentLevel);
  11.348 -            }
  11.349 -
  11.350 -            // Compute relative shift
  11.351 -            int firstLineIndent = indentation.get(0);
  11.352 -            int firstLineLevel = offsetToLevel.get(offsets.get(0));
  11.353 -            int computedIndent = firstLineLevel * indentSize;
  11.354 -            final int relativeShift = shiftToCurrent ? computedIndent - firstLineIndent : 0;
  11.355 -
  11.356 -            doc.runAtomic(new Runnable() {
  11.357 -                @Override
  11.358 -                public void run() {
  11.359 -                    int[] computedIndents = new int[offsets.size()];
  11.360 -                    // Process backwards so I don't have to worry about updating offsets affected by
  11.361 -                    // indentation changes
  11.362 -                    for (int i = offsets.size() - 1; i >= 0; i--) {
  11.363 -                        int indent = indentation.get(i);
  11.364 -                        if (indent == -1) {
  11.365 -                            // Leave line alone
  11.366 -                            continue;
  11.367 -                        }
  11.368 -                        if (indent >= 0) {
  11.369 -                            int offset = offsets.get(i);
  11.370 -                            int level = offsetToLevel.get(offset);
  11.371 -                            int computedIndent = level * indentSize - relativeShift;
  11.372 -                            if (computedIndent < 0) {
  11.373 -                                computedIndent = 0;
  11.374 -                            }
  11.375 -                            computedIndents[i] =computedIndent;
  11.376 -                        } else {
  11.377 -                            computedIndents[i] = -1;
  11.378 -                        }
  11.379 -                    }
  11.380 -
  11.381 -                    for (int i = offsets.size() - 1; i >= 0; i--) {
  11.382 -                        int indent = indentation.get(i);
  11.383 -                        if (indent < -1) {
  11.384 -                            try {
  11.385 -                                // Negative offset pointing to a left parenthesis we should align with
  11.386 -                                int parenOffset = -indent;
  11.387 -                                int lineStart = Utilities.getRowStart(doc, parenOffset);
  11.388 -                                if (lineStart != -1) {
  11.389 -                                    int parenLineIndent = computedIndents[offsetToIndex.get(lineStart)];
  11.390 -                                    assert parenLineIndent >= 0;
  11.391 -                                    int textBegin = Utilities.getRowFirstNonWhite(doc, lineStart);
  11.392 -                                    assert textBegin != -1;
  11.393 -                                    // Indent to new indentation + text up to paren plus the paren itself
  11.394 -                                    int newIndent = parenLineIndent + (parenOffset-textBegin) + 1;
  11.395 -                                    computedIndents[i] = newIndent;
  11.396 -                                }
  11.397 -                            } catch (BadLocationException ble) {
  11.398 -                                Exceptions.printStackTrace(ble);
  11.399 -                            }
  11.400 -                        }
  11.401 -                    }
  11.402 -
  11.403 -                    // Process backwards so I don't have to worry about updating offsets affected by
  11.404 -                    // indentation changes
  11.405 -                    for (int i = offsets.size() - 1; i >= 0; i--) {
  11.406 -                        int indent = indentation.get(i);
  11.407 -                        if (indent == -1) {
  11.408 -                            // Leave line alone
  11.409 -                            continue;
  11.410 -                        }
  11.411 -                        int offset = offsets.get(i);
  11.412 -                        int computedIndent = computedIndents[i];
  11.413 -                        if (computedIndent < 0) {
  11.414 -                            computedIndent = 0;
  11.415 -                        }
  11.416 -
  11.417 -                        if (computedIndent != indent) {
  11.418 -                            try {
  11.419 -                                context.modifyIndent(offset, computedIndent);
  11.420 -                            } catch (BadLocationException ex) {
  11.421 -                                Exceptions.printStackTrace(ex);
  11.422 -                            }
  11.423 -                        }
  11.424 -                    }
  11.425 -                }
  11.426 -            });
  11.427 -        } catch (BadLocationException ble) {
  11.428 -            Exceptions.printStackTrace(ble);
  11.429 -        }
  11.430 -    }
  11.431 -
  11.432 -    private boolean isLinePrefix(BaseDocument doc, int offset) throws BadLocationException {
  11.433 -        return Utilities.getRowFirstNonWhite(doc, offset) == offset;
  11.434 -    }
  11.435 -
  11.436 -    private void cleanup(Document document, PythonParserResult info, int startOffset, int endOffset) {
  11.437 -        BaseDocument doc = (BaseDocument)document;
  11.438 -        final EditList edits = new EditList(doc);
  11.439 -        try {
  11.440 -            doc.readLock(); // For token hierarchy usage
  11.441 -
  11.442 -            TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(doc, startOffset);
  11.443 -            if (ts == null) {
  11.444 -                return;
  11.445 -            }
  11.446 -
  11.447 -            ts.move(startOffset);
  11.448 -
  11.449 -
  11.450 -
  11.451 -            // TODO:
  11.452 -            // Control whether I collapse spaces to a single space, or just ensure there is at least one
  11.453 -            // "None", "1", "At least 1", "Leave Alone"
  11.454 -
  11.455 -            // TODO: Insert and remove needed or unnecessary parentheses!
  11.456 -            // TODO: Alignment! Especially of trailing line comments on adjacent lines!
  11.457 -            // TODO: Collapse blank newlines!
  11.458 -            boolean addSpaceAroundOperators = true;
  11.459 -            boolean removeSpaceInsideParens = true; // also applies to braces and brackets
  11.460 -            boolean addSpaceAfterComma = true;
  11.461 -            //    boolean spaceArondParens = false;
  11.462 -            //    boolean spaceBeforeArgs = false; // before parentheses in a call
  11.463 -            boolean removeSpaceBeforeSep = true; // before comma, semicolon or colon
  11.464 -            //    boolean alignAssignments = false; // Only one space around assignments
  11.465 -            boolean removeSpaceInParamAssign = true; // Around assignment in parameter list, e.g.
  11.466 -            boolean collapseSpaces = true;
  11.467 -            //def complex(real, imag=0.0):
  11.468 -            //       return magic(r=real, i=imag)
  11.469 -            if (codeStyle != null) {
  11.470 -                addSpaceAroundOperators = codeStyle.addSpaceAroundOperators();
  11.471 -                removeSpaceInsideParens = codeStyle.removeSpaceInsideParens();
  11.472 -                addSpaceAfterComma = codeStyle.addSpaceAfterComma();
  11.473 -                removeSpaceBeforeSep = codeStyle.removeSpaceBeforeSep();
  11.474 -                removeSpaceInParamAssign = codeStyle.removeSpaceInParamAssign();
  11.475 -                collapseSpaces = codeStyle.collapseSpaces();
  11.476 -            }
  11.477 -
  11.478 -            // TODO - back up to the nearest function or class or beginning of the document to get the right
  11.479 -            // parenthesis balance.
  11.480 -            int parenBalance = 0;
  11.481 -
  11.482 -            Token<? extends PythonTokenId> prev = null;
  11.483 -            Token<? extends PythonTokenId> token = null;
  11.484 -            Token<? extends PythonTokenId> next = null;
  11.485 -            int tokenOffset = 0;
  11.486 -            int nextOffset = 0;
  11.487 -            int prevOffset = -1;
  11.488 -            if (ts.moveNext()) {
  11.489 -                token = ts.token();
  11.490 -                tokenOffset = ts.offset();
  11.491 -                if (ts.moveNext()) {
  11.492 -                    next = ts.token();
  11.493 -                    nextOffset = ts.offset();
  11.494 -                } else {
  11.495 -                    return;
  11.496 -                }
  11.497 -            }
  11.498 -            boolean prevRemoved = false;
  11.499 -            boolean tokenRemoved = false;
  11.500 -            boolean nextRemoved = false;
  11.501 -            while (token != null) {
  11.502 -                TokenId prevId = prev != null ? prev.id() : null;
  11.503 -                TokenId id = token.id();
  11.504 -                TokenId nextId = next != null ? next.id() : null;
  11.505 -
  11.506 -                if (id == PythonTokenId.LPAREN) {
  11.507 -                    parenBalance++;
  11.508 -                } else if (id == PythonTokenId.RPAREN) {
  11.509 -                    parenBalance--;
  11.510 -                }
  11.511 -
  11.512 -                if (removeSpaceInsideParens) {
  11.513 -                    if (id == PythonTokenId.LPAREN) {
  11.514 -                        if (nextId == PythonTokenId.WHITESPACE && !nextRemoved) {
  11.515 -                            edits.replace(nextOffset, next.length(), null, false, 0);
  11.516 -                            nextRemoved = true;
  11.517 -                        }
  11.518 -                    } else if (id == PythonTokenId.RPAREN) {
  11.519 -                        if (prevId == PythonTokenId.WHITESPACE && !prevRemoved && !isLinePrefix(doc, tokenOffset)) {
  11.520 -                            // I don't remove space in front of paren's at the beginning of the line; these might have
  11.521 -                            // been aligned with indented content above
  11.522 -                            edits.replace(prevOffset, prev.length(), null, false, 0);
  11.523 -                            prevRemoved = true;
  11.524 -                        }
  11.525 -                    } else if (id == PythonTokenId.LBRACKET) {
  11.526 -                        if (nextId == PythonTokenId.WHITESPACE && !nextRemoved) {
  11.527 -                            edits.replace(nextOffset, next.length(), null, false, 0);
  11.528 -                            nextRemoved = true;
  11.529 -                        }
  11.530 -                    } else if (id == PythonTokenId.RBRACKET) {
  11.531 -                        if (prevId == PythonTokenId.WHITESPACE && !prevRemoved && !isLinePrefix(doc, tokenOffset)) {
  11.532 -                            edits.replace(prevOffset, prev.length(), null, false, 0);
  11.533 -                            prevRemoved = true;
  11.534 -                        }
  11.535 -                    } else if (id == PythonTokenId.LBRACE) {
  11.536 -                        if (nextId == PythonTokenId.WHITESPACE && !nextRemoved) {
  11.537 -                            edits.replace(nextOffset, next.length(), null, false, 0);
  11.538 -                            nextRemoved = true;
  11.539 -                        }
  11.540 -                    } else if (id == PythonTokenId.RBRACE) {
  11.541 -                        if (prevId == PythonTokenId.WHITESPACE && !prevRemoved && !isLinePrefix(doc, tokenOffset)) {
  11.542 -                            edits.replace(prevOffset, prev.length(), null, false, 0);
  11.543 -                            prevRemoved = true;
  11.544 -                        }
  11.545 -                    }
  11.546 -                }
  11.547 -
  11.548 -                if (addSpaceAfterComma) {
  11.549 -                    if (id == PythonTokenId.COMMA) {
  11.550 -                        if (collapseSpaces && nextId == PythonTokenId.WHITESPACE && next.length() > 1) {
  11.551 -                            edits.replace(nextOffset, next.length() - 1, null, false, 1); // NOI18N
  11.552 -                        } else if (next == null ||
  11.553 -                                (nextId != PythonTokenId.WHITESPACE && nextId != PythonTokenId.NEWLINE)) {
  11.554 -                            edits.replace(nextOffset, 0, " ", false, 1); // NOI18N
  11.555 -                        }
  11.556 -                    }
  11.557 -                }
  11.558 -
  11.559 -                if (removeSpaceBeforeSep &&
  11.560 -                        (id == PythonTokenId.COMMA || id == PythonTokenId.COLON ||
  11.561 -                        (id == PythonTokenId.ANY_OPERATOR && TokenUtilities.equals(token.text(), ";"))) && // NOI18N
  11.562 -                        prevId == PythonTokenId.WHITESPACE && !prevRemoved && !isLinePrefix(doc, tokenOffset)) {
  11.563 -                    edits.replace(prevOffset, prev.length(), null, false, 2);
  11.564 -                    prevRemoved = true;
  11.565 -                }
  11.566 -
  11.567 -                if (addSpaceAroundOperators && id == PythonTokenId.ANY_OPERATOR) {
  11.568 -                    CharSequence seq = token.text();
  11.569 -
  11.570 -                    // These aren't binary, and ; isn't really an operator and has its own setting
  11.571 -                    if (!(TokenUtilities.equals(seq, "@") || // NOI18N
  11.572 -                            TokenUtilities.equals(seq, "`") || // NOI18N
  11.573 -                            TokenUtilities.equals(seq, ";"))) { // NOI18N
  11.574 -
  11.575 -                        boolean insertSpace = true;
  11.576 -                        if (removeSpaceInParamAssign && TokenUtilities.equals(seq, "=")) { // NOI18N
  11.577 -                            // Special handling: keyword arguments should typically NOT
  11.578 -                            // have space inserted
  11.579 -                            if (parenBalance > 0) {
  11.580 -                                insertSpace = false;
  11.581 -                                // Remove spaces around the =
  11.582 -                                if (prevId == PythonTokenId.WHITESPACE && !prevRemoved) {
  11.583 -                                    edits.replace(prevOffset, prev.length(), null, false, 5); // NOI18N
  11.584 -                                    prevRemoved = true;
  11.585 -                                }
  11.586 -                                if (nextId == PythonTokenId.WHITESPACE && !nextRemoved) {
  11.587 -                                    edits.replace(nextOffset, next.length(), null, false, 6); // NOI18N
  11.588 -                                    nextRemoved = true;
  11.589 -                                }
  11.590 -                            }
  11.591 -                        }
  11.592 -
  11.593 -                        if (insertSpace && TokenUtilities.equals(seq, "-")/* && (nextId == PythonTokenId.FLOAT_LITERAL || nextId == PythonTokenId.INT_LITERAL)*/) {
  11.594 -                            // Leave -'s alone for now. The code is a little unclear on the difference between
  11.595 -                            //  x-1 and =-1 etc. For numbers (floating and integer) the minus isn't part of the lexical token for the number;
  11.596 -                            // it's a separate operator. However, it's tricky to tell this apart from the binary subtraction, since it depends
  11.597 -                            // on what came before. For now play it safe an leave these alone.
  11.598 -                            // TODO - implement this properly.
  11.599 -                            insertSpace = false;
  11.600 -                        }
  11.601 -
  11.602 -                        if (insertSpace && TokenUtilities.equals(seq, "*")) { // NOI18N
  11.603 -                            // "*" in (*foo) doesn't mean multiplication; it's not a binary operator here,
  11.604 -                            // it's many args.
  11.605 -                            if (prevId == PythonTokenId.COMMA || prevId == PythonTokenId.LPAREN) {
  11.606 -                                insertSpace = false;
  11.607 -                            }
  11.608 -                        }
  11.609 -
  11.610 -                        if (insertSpace) {
  11.611 -                            // Ensure that we have space on both sides
  11.612 -                            if (collapseSpaces && prevId == PythonTokenId.WHITESPACE && next.length() > 1 &&
  11.613 -                                    !isLinePrefix(doc, tokenOffset)) {
  11.614 -                                edits.replace(prevOffset, prev.length() - 1, null, false, 1); // NOI18N
  11.615 -                            } else if (prevId != PythonTokenId.WHITESPACE) {
  11.616 -                                edits.replace(tokenOffset, 0, " ", false, 3); // NOI18N
  11.617 -                            }
  11.618 -
  11.619 -                            if (collapseSpaces && nextId == PythonTokenId.WHITESPACE && next.length() > 1) {
  11.620 -                                edits.replace(nextOffset, next.length() - 1, null, false, 1); // NOI18N
  11.621 -                            } else if (nextId != PythonTokenId.WHITESPACE && nextId != PythonTokenId.NEWLINE) {
  11.622 -                                edits.replace(nextOffset, 0, " ", false, 4); // NOI18N
  11.623 -                            }
  11.624 -                        }
  11.625 -                    }
  11.626 -                }
  11.627 -
  11.628 -                if (tokenOffset + token.length() >= endOffset) {
  11.629 -                    break;
  11.630 -                }
  11.631 -
  11.632 -                prevRemoved = tokenRemoved;
  11.633 -                tokenRemoved = nextRemoved;
  11.634 -                nextRemoved = false;
  11.635 -
  11.636 -                prev = token;
  11.637 -                token = next;
  11.638 -                prevOffset = tokenOffset;
  11.639 -                tokenOffset = nextOffset;
  11.640 -                if (ts.moveNext()) {
  11.641 -                    next = ts.token();
  11.642 -                    nextOffset = ts.offset();
  11.643 -                } else {
  11.644 -                    next = null;
  11.645 -                }
  11.646 -            }
  11.647 -        } catch (BadLocationException ble) {
  11.648 -            Exceptions.printStackTrace(ble);
  11.649 -        } finally {
  11.650 -            doc.readUnlock();
  11.651 -        }
  11.652 -
  11.653 -        doc.runAtomic(new Runnable() {
  11.654 -            @Override
  11.655 -            public void run() {
  11.656 -                edits.apply();
  11.657 -            }
  11.658 -        });
  11.659 -    }
  11.660 -}
    12.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonHintOptions.java	Sat Sep 12 23:03:15 2015 -0700
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,72 +0,0 @@
    12.4 -/*
    12.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    12.6 - *
    12.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    12.8 - *
    12.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   12.10 - * Other names may be trademarks of their respective owners.
   12.11 - *
   12.12 - * The contents of this file are subject to the terms of either the GNU
   12.13 - * General Public License Version 2 only ("GPL") or the Common
   12.14 - * Development and Distribution License("CDDL") (collectively, the
   12.15 - * "License"). You may not use this file except in compliance with the
   12.16 - * License. You can obtain a copy of the License at
   12.17 - * http://www.netbeans.org/cddl-gplv2.html
   12.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   12.19 - * specific language governing permissions and limitations under the
   12.20 - * License.  When distributing the software, include this License Header
   12.21 - * Notice in each file and include the License file at
   12.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   12.23 - * particular file as subject to the "Classpath" exception as provided
   12.24 - * by Oracle in the GPL Version 2 section of the License file that
   12.25 - * accompanied this code. If applicable, add the following below the
   12.26 - * License Header, with the fields enclosed by brackets [] replaced by
   12.27 - * your own identifying information:
   12.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   12.29 - *
   12.30 - * Contributor(s):
   12.31 - *
   12.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   12.33 - */
   12.34 -package org.netbeans.modules.python.editor;
   12.35 -
   12.36 -import org.netbeans.modules.csl.api.HintsProvider;
   12.37 -import org.netbeans.modules.csl.api.HintsProvider.HintsManager;
   12.38 -import org.netbeans.modules.python.api.PythonMIMEResolver;
   12.39 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   12.40 -import org.netbeans.spi.options.AdvancedOption;
   12.41 -import org.netbeans.spi.options.OptionsPanelController;
   12.42 -import org.openide.util.NbBundle;
   12.43 -
   12.44 -/**
   12.45 - * Hint settings for Python
   12.46 - */
   12.47 -public class PythonHintOptions extends AdvancedOption {
   12.48 -    OptionsPanelController panelController;
   12.49 -
   12.50 -    @Override
   12.51 -    public String getDisplayName() {
   12.52 -        return NbBundle.getMessage(PythonHintOptions.class, "CTL_Hints_DisplayName"); // NOI18N
   12.53 -    }
   12.54 -
   12.55 -    @Override
   12.56 -    public String getTooltip() {
   12.57 -        return NbBundle.getMessage(PythonHintOptions.class, "CTL_Hints_ToolTip"); // NOI18N
   12.58 -    }
   12.59 -
   12.60 -    @Override
   12.61 -    public synchronized OptionsPanelController create() {
   12.62 -        if (panelController == null) {
   12.63 -            HintsManager manager = HintsProvider.HintsManager.getManagerForMimeType(PythonMIMEResolver.PYTHON_MIME_TYPE);
   12.64 -            assert manager != null;
   12.65 -            panelController = manager.getOptionsController();
   12.66 -        }
   12.67 -
   12.68 -        return panelController;
   12.69 -    }
   12.70 -
   12.71 -    //TODO: temporary solution, this should be solved on GSF level
   12.72 -    public static OptionsPanelController createStatic() {
   12.73 -        return new PythonHintOptions().create();
   12.74 -    }
   12.75 -}
    13.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonIndex.java	Sat Sep 12 23:03:15 2015 -0700
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,1470 +0,0 @@
    13.4 -/*
    13.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    13.6 - *
    13.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    13.8 - *
    13.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   13.10 - * Other names may be trademarks of their respective owners.
   13.11 - *
   13.12 - * The contents of this file are subject to the terms of either the GNU
   13.13 - * General Public License Version 2 only ("GPL") or the Common
   13.14 - * Development and Distribution License("CDDL") (collectively, the
   13.15 - * "License"). You may not use this file except in compliance with the
   13.16 - * License. You can obtain a copy of the License at
   13.17 - * http://www.netbeans.org/cddl-gplv2.html
   13.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   13.19 - * specific language governing permissions and limitations under the
   13.20 - * License.  When distributing the software, include this License Header
   13.21 - * Notice in each file and include the License file at
   13.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   13.23 - * particular file as subject to the "Classpath" exception as provided
   13.24 - * by Oracle in the GPL Version 2 section of the License file that
   13.25 - * accompanied this code. If applicable, add the following below the
   13.26 - * License Header, with the fields enclosed by brackets [] replaced by
   13.27 - * your own identifying information:
   13.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   13.29 - *
   13.30 - * Contributor(s):
   13.31 - *
   13.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   13.33 - */
   13.34 -package org.netbeans.modules.python.editor;
   13.35 -
   13.36 -import java.io.File;
   13.37 -import java.io.IOException;
   13.38 -import java.net.MalformedURLException;
   13.39 -import java.net.URL;
   13.40 -import java.util.ArrayList;
   13.41 -import java.util.Arrays;
   13.42 -import java.util.Collection;
   13.43 -import java.util.Collections;
   13.44 -import java.util.EnumSet;
   13.45 -import java.util.HashMap;
   13.46 -import java.util.HashSet;
   13.47 -import java.util.Iterator;
   13.48 -import java.util.List;
   13.49 -import java.util.Map;
   13.50 -import java.util.Set;
   13.51 -import java.util.WeakHashMap;
   13.52 -import java.util.logging.Level;
   13.53 -import java.util.logging.Logger;
   13.54 -import org.netbeans.api.project.Project;
   13.55 -import org.netbeans.modules.csl.api.ElementKind;
   13.56 -import org.netbeans.modules.parsing.spi.indexing.PathRecognizer;
   13.57 -import org.netbeans.modules.parsing.spi.indexing.support.IndexResult;
   13.58 -import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
   13.59 -import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.CAMEL_CASE;
   13.60 -import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.CASE_INSENSITIVE_PREFIX;
   13.61 -import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.CASE_INSENSITIVE_REGEXP;
   13.62 -import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.PREFIX;
   13.63 -import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.REGEXP;
   13.64 -import org.netbeans.modules.python.editor.elements.IndexedElement;
   13.65 -import org.netbeans.modules.python.api.PythonPlatform;
   13.66 -import org.netbeans.modules.python.api.PythonPlatformManager;
   13.67 -import org.netbeans.modules.python.editor.elements.IndexedPackage;
   13.68 -import org.netbeans.modules.python.editor.imports.ImportManager;
   13.69 -import org.openide.filesystems.FileObject;
   13.70 -import org.openide.filesystems.FileStateInvalidException;
   13.71 -import org.openide.filesystems.URLMapper;
   13.72 -import org.openide.modules.InstalledFileLocator;
   13.73 -import org.openide.util.Exceptions;
   13.74 -import org.openide.util.Lookup;
   13.75 -import org.python.antlr.ast.Import;
   13.76 -import org.python.antlr.ast.ImportFrom;
   13.77 -import org.python.antlr.ast.alias;
   13.78 -
   13.79 -/**
   13.80 - *
   13.81 - * @author alley
   13.82 - * @author Tor Norbye
   13.83 - */
   13.84 -public class PythonIndex {
   13.85 -//    public static final Set<SearchScope> ALL_SCOPE = EnumSet.allOf(SearchScope.class);
   13.86 -//    public static final Set<SearchScope> SOURCE_SCOPE = EnumSet.of(SearchScope.SOURCE);
   13.87 -    static final String CLUSTER_URL = "cluster:"; // NOI18N
   13.88 -    static final String PYTHONHOME_URL = "python:"; // NOI18N
   13.89 -    private static final String STUB_MISSING = "stub_missing"; // NOI18N
   13.90 -
   13.91 -    // The "functions" module is always imported by the interpreter, and ditto
   13.92 -    // for exceptions, constants, etc.
   13.93 -    public static Set<String> BUILTIN_MODULES = new HashSet<>();
   13.94 -
   13.95 -
   13.96 -    private static final Logger LOG = Logger.getLogger(PythonIndex.class.getName());
   13.97 -    public static final String OBJECT = "object"; // NOI18N
   13.98 -    static Map<String, Set<String>> wildcardImports = new HashMap<>();
   13.99 -    static Set<String> systemModules;
  13.100 -    // TODO - make weak?
  13.101 -    static Set<String> availableClasses;
  13.102 -    private static String clusterUrl = null;
  13.103 -    static {
  13.104 -        //BUILTIN_MODULES.add("objects"); // NOI18N -- just links to the others
  13.105 -        BUILTIN_MODULES.add("stdtypes"); // NOI18N
  13.106 -        //BUILTIN_MODULES.add("types"); // NOI18N
  13.107 -        BUILTIN_MODULES.add("exceptions"); // NOI18N
  13.108 -        BUILTIN_MODULES.add("functions"); // NOI18N
  13.109 -        BUILTIN_MODULES.add("constants"); // NOI18N
  13.110 -    }
  13.111 -
  13.112 -    public static PythonIndex get(Collection<FileObject> roots) {
  13.113 -        // XXX no cache - is it needed?
  13.114 -        LOG.log(Level.FINE, "PythonIndex for roots: {0}", roots); //NOI18N
  13.115 -        return new PythonIndex(QuerySupportFactory.get(roots), false);
  13.116 -    }
  13.117 -    
  13.118 -    public static PythonIndex get(Project project) {
  13.119 -        Set<String> sourceIds = new HashSet<>();
  13.120 -        Set<String> libraryIds = new HashSet<>();
  13.121 -        Collection<? extends PathRecognizer> lookupAll = Lookup.getDefault().lookupAll(PathRecognizer.class);
  13.122 -        for (PathRecognizer pathRecognizer : lookupAll) {
  13.123 -            Set<String> source = pathRecognizer.getSourcePathIds();
  13.124 -            if (source != null) {
  13.125 -                sourceIds.addAll(source);
  13.126 -            }
  13.127 -            Set<String> library = pathRecognizer.getLibraryPathIds();
  13.128 -            if (library != null) {
  13.129 -                libraryIds.addAll(library);
  13.130 -            }
  13.131 -        }
  13.132 -
  13.133 -        final Collection<FileObject> findRoots = QuerySupport.findRoots(project,
  13.134 -                sourceIds,
  13.135 -                libraryIds,
  13.136 -                Collections.<String>emptySet());
  13.137 -        return PythonIndex.get(findRoots);
  13.138 -    }
  13.139 -    
  13.140 -    private static final WeakHashMap<FileObject, PythonIndex> INDEX_CACHE = new WeakHashMap<>();
  13.141 -    public static PythonIndex get(FileObject fo) {
  13.142 -        PythonIndex index = INDEX_CACHE.get(fo);
  13.143 -        if (index == null) {
  13.144 -            LOG.log(Level.FINE, "Creating PythonIndex for FileObject: {0}", fo); //NOI18N
  13.145 -            index = new PythonIndex(QuerySupportFactory.get(fo), true);
  13.146 -            INDEX_CACHE.put(fo, index);
  13.147 -        }
  13.148 -        return index;
  13.149 -    }
  13.150 -
  13.151 -    public static boolean isBuiltinModule(String module) {
  13.152 -        return BUILTIN_MODULES.contains(module) || STUB_MISSING.equals(module);
  13.153 -    }
  13.154 -
  13.155 -    // For testing only
  13.156 -    public static void setClusterUrl(String url) {
  13.157 -        clusterUrl = url;
  13.158 -    }
  13.159 -
  13.160 -    static String getPreindexUrl(String url) {
  13.161 -        // TODO - look up the correct platform to use!
  13.162 -        final PythonPlatformManager manager = PythonPlatformManager.getInstance();
  13.163 -        final String platformName = manager.getDefaultPlatform();
  13.164 -        PythonPlatform platform = manager.getPlatform(platformName);
  13.165 -        if (platform != null) {
  13.166 -            String s = platform.getHomeUrl();
  13.167 -            if (s != null) {
  13.168 -                if (url.startsWith(s)) {
  13.169 -                    url = PYTHONHOME_URL + url.substring(s.length());
  13.170 -                    return url;
  13.171 -                }
  13.172 -            }
  13.173 -        }
  13.174 -        
  13.175 -        String s = getClusterUrl();
  13.176 -        
  13.177 -        if (url.startsWith(s)) {
  13.178 -            return CLUSTER_URL + url.substring(s.length());
  13.179 -        }
  13.180 -        
  13.181 -        if (url.startsWith("jar:file:")) { // NOI18N
  13.182 -            String sub = url.substring(4);
  13.183 -            if (sub.startsWith(s)) {
  13.184 -                return CLUSTER_URL + sub.substring(s.length());
  13.185 -            }
  13.186 -        }
  13.187 -        
  13.188 -        return url;
  13.189 -    }
  13.190 -
  13.191 -/** Get the FileObject corresponding to a URL returned from the index */
  13.192 -    public static FileObject getFileObject(String url) {
  13.193 -        return getFileObject(url, null);
  13.194 -    }
  13.195 -
  13.196 -    public static FileObject getFileObject(String url, FileObject context) {
  13.197 -        try {
  13.198 -            if (url.startsWith(PYTHONHOME_URL)) {
  13.199 -                Iterator<String> it = null;
  13.200 -                
  13.201 -                // TODO - look up the right platform for the given project
  13.202 -                //if (context != null) {
  13.203 -                //    Project project = FileOwnerQuery.getOwner(context);
  13.204 -                //    if (project != null) {
  13.205 -                //        PythonPlatform platform = PythonPlatform.platformFor(project);
  13.206 -                //        if (platform != null) {
  13.207 -                //            it = Collections.singleton(platform).iterator();
  13.208 -                //        }
  13.209 -                //    }
  13.210 -                //}
  13.211 -                
  13.212 -                PythonPlatformManager manager = PythonPlatformManager.getInstance();
  13.213 -                if (it == null) {
  13.214 -                    it = manager.getPlatformList().iterator();
  13.215 -                }
  13.216 -                while (it.hasNext()) {
  13.217 -                    String name = it.next();
  13.218 -                    PythonPlatform platform = manager.getPlatform(name);
  13.219 -                    if (platform != null) {
  13.220 -                        String u = platform.getHomeUrl();
  13.221 -                        if (u != null) {
  13.222 -                            try {
  13.223 -                                u = u + url.substring(PYTHONHOME_URL.length());
  13.224 -                                FileObject fo = URLMapper.findFileObject(new URL(u));
  13.225 -                                if (fo != null) {
  13.226 -                                    return fo;
  13.227 -                                }
  13.228 -                            } catch (MalformedURLException mue) {
  13.229 -                                Exceptions.printStackTrace(mue);
  13.230 -                            }
  13.231 -                        }
  13.232 -                    }
  13.233 -                }
  13.234 -                
  13.235 -                return null;
  13.236 -            } else if (url.startsWith(CLUSTER_URL)) {
  13.237 -                url = getClusterUrl() + url.substring(CLUSTER_URL.length()); // NOI18N
  13.238 -                if (url.contains(".egg!/")) { // NOI18N
  13.239 -                    url = "jar:" + url; // NOI18N
  13.240 -                }
  13.241 -            }
  13.242 -            
  13.243 -            return URLMapper.findFileObject(new URL(url));
  13.244 -        } catch (MalformedURLException ex) {
  13.245 -            Exceptions.printStackTrace(ex);
  13.246 -        }
  13.247 -        
  13.248 -        return null;
  13.249 -    }
  13.250 -    
  13.251 -    static String getClusterUrl() {
  13.252 -        if (clusterUrl == null) {
  13.253 -            File f =
  13.254 -                    InstalledFileLocator.getDefault().locate("modules/org-netbeans-modules-python-editor.jar", null, false); // NOI18N
  13.255 -            
  13.256 -            if (f == null) {
  13.257 -                throw new RuntimeException("Can't find cluster");
  13.258 -            }
  13.259 -            
  13.260 -            f = new File(f.getParentFile().getParentFile().getAbsolutePath());
  13.261 -            
  13.262 -            try {
  13.263 -                f = f.getCanonicalFile();
  13.264 -                clusterUrl = f.toURI().toURL().toExternalForm();
  13.265 -            } catch (IOException ioe) {
  13.266 -                Exceptions.printStackTrace(ioe);
  13.267 -            }
  13.268 -        }
  13.269 -
  13.270 -        return clusterUrl;
  13.271 -    }
  13.272 -
  13.273 -    private final QuerySupport index;
  13.274 -    private final boolean updateCache;
  13.275 -    
  13.276 -    /** Creates a new instance of PythonIndex */
  13.277 -    private PythonIndex(QuerySupport index, boolean updateCache) {
  13.278 -        this.index = index;
  13.279 -        this.updateCache = updateCache;
  13.280 -    }
  13.281 -    
  13.282 -    private boolean search(String fieldName, String fieldValue, QuerySupport.Kind kind, Set<? super IndexResult> result, final String... fieldsToLoad) {
  13.283 -        try {
  13.284 -            result.addAll(index.query(fieldName, fieldValue, kind, fieldsToLoad));
  13.285 -            return true;
  13.286 -        } catch (IOException ioe) {
  13.287 -            Exceptions.printStackTrace(ioe);
  13.288 -
  13.289 -            return false;
  13.290 -        } catch (UnsupportedOperationException iuoe) {
  13.291 -            return false;
  13.292 -        }
  13.293 -    }
  13.294 -
  13.295 -    public Set<IndexedElement> getModules(String name, final QuerySupport.Kind kind) {
  13.296 -        final Set<IndexResult> result = new HashSet<>();
  13.297 -
  13.298 -        //        if (!isValid()) {
  13.299 -        //            LOGGER.fine(String.format("LuceneIndex[%s] is invalid!\n", this.toString()));
  13.300 -        //            return;
  13.301 -        //        }
  13.302 -
  13.303 -        // TODO - handle case insensitive searches etc?
  13.304 -        String field = PythonIndexer.FIELD_MODULE_NAME;
  13.305 -
  13.306 -        search(field, name, kind, result, PythonIndexer.FIELD_MODULE_ATTR_NAME, PythonIndexer.FIELD_MODULE_NAME);
  13.307 -
  13.308 -        final Set<IndexedElement> modules = new HashSet<>();
  13.309 -
  13.310 -        for (IndexResult map : result) {
  13.311 -            URL url = map.getUrl();
  13.312 -            if (url == null) {
  13.313 -                continue;
  13.314 -            }
  13.315 -            String path = url.toExternalForm();
  13.316 -            String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
  13.317 -            if (STUB_MISSING.equals(module)) {
  13.318 -                continue;
  13.319 -            }
  13.320 -
  13.321 -            IndexedElement element = new IndexedElement(module, ElementKind.MODULE, path, null, null, null);
  13.322 -
  13.323 -            String attrs = map.getValue(PythonIndexer.FIELD_MODULE_ATTR_NAME);
  13.324 -            if (attrs != null && attrs.indexOf('D') != -1) {
  13.325 -                element.setFlags(IndexedElement.DEPRECATED);
  13.326 -            }
  13.327 -
  13.328 -            String rhs = path.substring(path.lastIndexOf('/') + 1);
  13.329 -            element.setRhs(rhs);
  13.330 -            modules.add(element);
  13.331 -        }
  13.332 -
  13.333 -        return modules;
  13.334 -    }
  13.335 -
  13.336 -    public Set<IndexedPackage> getPackages(String name, final QuerySupport.Kind kind) {
  13.337 -        final Set<IndexResult> result = new HashSet<>();
  13.338 -
  13.339 -        String field = PythonIndexer.FIELD_MODULE_NAME;
  13.340 -        search(field, name, kind, result, PythonIndexer.FIELD_MODULE_NAME);
  13.341 -
  13.342 -        final Set<IndexedPackage> packages = new HashSet<>();
  13.343 -
  13.344 -        for (IndexResult map : result) {
  13.345 -            String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
  13.346 -
  13.347 -            String pkgName = null;
  13.348 -            String pkg = null;
  13.349 -
  13.350 -            int nextNextDot = -1;
  13.351 -            int lastDot = module.lastIndexOf('.');
  13.352 -            int nameLength = name.length();
  13.353 -            if (nameLength < lastDot) {
  13.354 -                int nextDot = module.indexOf('.', nameLength);
  13.355 -                if (nextDot != -1) {
  13.356 -                    pkg = module.substring(0, nextDot);
  13.357 -                    nextNextDot = module.indexOf('.', nextDot + 1);
  13.358 -                    int start = module.lastIndexOf('.', name.length());
  13.359 -                    if (start == -1) {
  13.360 -                        start = 0;
  13.361 -                    } else {
  13.362 -                        start++;
  13.363 -                    }
  13.364 -                    pkgName = module.substring(start, nextDot);
  13.365 -                }
  13.366 -            } else if (lastDot != -1) {
  13.367 -                pkgName = module.substring(lastDot + 1);
  13.368 -                pkg = module;
  13.369 -            }
  13.370 -
  13.371 -            if (pkgName != null) {
  13.372 -                String url = map.getUrl().toExternalForm();
  13.373 -                IndexedPackage element = new IndexedPackage(pkgName, pkg, url, nextNextDot != -1);
  13.374 -                element.setRhs("");
  13.375 -                packages.add(element);
  13.376 -            }
  13.377 -        }
  13.378 -
  13.379 -        return packages;
  13.380 -    }
  13.381 -    
  13.382 -    public Set<IndexedElement> getClasses(String name, final QuerySupport.Kind kind, PythonParserResult context, boolean includeDuplicates) {
  13.383 -        final Set<IndexResult> result = new HashSet<>();
  13.384 -
  13.385 -        //        if (!isValid()) {
  13.386 -        //            LOGGER.fine(String.format("LuceneIndex[%s] is invalid!\n", this.toString()));
  13.387 -        //            return;
  13.388 -        //        }
  13.389 -        String field;
  13.390 -
  13.391 -        switch (kind) {
  13.392 -            case EXACT:
  13.393 -            case PREFIX:
  13.394 -            case CAMEL_CASE:
  13.395 -            case REGEXP:
  13.396 -                field = PythonIndexer.FIELD_CLASS_NAME;
  13.397 -                
  13.398 -                break;
  13.399 -                
  13.400 -            case CASE_INSENSITIVE_PREFIX:
  13.401 -            case CASE_INSENSITIVE_REGEXP:
  13.402 -            case CASE_INSENSITIVE_CAMEL_CASE:
  13.403 -                field = PythonIndexer.FIELD_CASE_INSENSITIVE_CLASS_NAME;
  13.404 -                
  13.405 -                break;
  13.406 -                
  13.407 -            default:
  13.408 -                throw new UnsupportedOperationException(kind.toString());
  13.409 -        }
  13.410 -
  13.411 -        search(field, name, kind, result, PythonIndexer.FIELD_IN, PythonIndexer.FIELD_CLASS_ATTR_NAME, PythonIndexer.FIELD_CLASS_NAME);
  13.412 -
  13.413 -        Set<String> uniqueClasses = includeDuplicates ? null : new HashSet<String>();
  13.414 -
  13.415 -        final Set<IndexedElement> classes = new HashSet<>();
  13.416 -
  13.417 -        for (IndexResult map : result) {
  13.418 -            String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
  13.419 -            if (clz == null) {
  13.420 -                // A module without classes
  13.421 -                continue;
  13.422 -            }
  13.423 -            String url = map.getUrl().toExternalForm();
  13.424 -            String module = map.getValue(PythonIndexer.FIELD_IN);
  13.425 -            boolean isBuiltin = isBuiltinModule(module);
  13.426 -
  13.427 -            String fqn = clz; // No further namespaces in Python, right?
  13.428 -            if (!includeDuplicates) {
  13.429 -                if (!uniqueClasses.contains(fqn)) { // use a map to point right to the class
  13.430 -                    uniqueClasses.add(fqn);
  13.431 -                    IndexedElement element = new IndexedElement(clz, ElementKind.CLASS, url, module, null, null);
  13.432 -                    if (isBuiltin) {
  13.433 -                        element.setRhs("<i>builtin</i>");
  13.434 -                    }
  13.435 -                    String attrs = map.getValue(PythonIndexer.FIELD_CLASS_ATTR_NAME);
  13.436 -                    if (attrs != null) {
  13.437 -                        int flags = IndexedElement.decode(attrs, 0, 0);
  13.438 -                        element.setFlags(flags);
  13.439 -                    }
  13.440 -                    element.setInherited(true);
  13.441 -
  13.442 -                    classes.add(element);
  13.443 -                } // else: Possibly pick the best version... based on which items have documentation attributes etc.
  13.444 -            } else {
  13.445 -                IndexedElement element = new IndexedElement(clz, ElementKind.CLASS, url, module, null, null);
  13.446 -                classes.add(element);
  13.447 -            }
  13.448 -        }
  13.449 -
  13.450 -        return classes;
  13.451 -    }
  13.452 -
  13.453 -//    /** Return the most distant method in the hierarchy that is overriding the given method, or null
  13.454 -//     * @todo Make this method actually compute most distant ancestor
  13.455 -//     * @todo Use arglist arity comparison to reject methods that are not overrides...
  13.456 -//     */
  13.457 -//    public IndexedMethod getOverridingMethod(String className, String methodName) {
  13.458 -//        Set<IndexedElement> methods = getInheritedElements(className, methodName, QuerySupport.Kind.EXACT);
  13.459 -//
  13.460 -//        // TODO - this is only returning ONE match, not the most distant one. I really need to
  13.461 -//        // produce a PythonIndex method for this which can walk in there and do a decent job!
  13.462 -//
  13.463 -//        for (IndexedElement method : methods) {
  13.464 -//            if (method.getKind() == ElementKind.METHOD || method.getKind() == ElementKind.CONSTRUCTOR) {
  13.465 -//                // getInheritedMethods may return methods ON fqn itself
  13.466 -//                if (!method.getIn().equals(className)) {
  13.467 -//                    return (IndexedMethod)method;
  13.468 -//                }
  13.469 -//            }
  13.470 -//        }
  13.471 -//
  13.472 -//        return null;
  13.473 -//    }
  13.474 -    /** Get the super implementation of the given method */
  13.475 -    public Set<IndexedElement> getOverridingMethods(String className, String function) {
  13.476 -        Set<IndexedElement> methods = getInheritedElements(className, function, QuerySupport.Kind.EXACT, true);
  13.477 -
  13.478 -        // TODO - remove all methods that are in the same file
  13.479 -        if (methods.size() > 0) {
  13.480 -            Set<IndexedElement> result = new HashSet<>(methods.size());
  13.481 -            for (IndexedElement element : methods) {
  13.482 -                if (!className.equals(element.getClz())) {
  13.483 -                    result.add(element);
  13.484 -                }
  13.485 -            }
  13.486 -            methods = result;
  13.487 -        }
  13.488 -
  13.489 -        return methods;
  13.490 -//        // TODO - this is only returning ONE match, not the most distant one. I really need to
  13.491 -//        // produce a PythonIndex method for this which can walk in there and do a decent job!
  13.492 -//
  13.493 -//        for (IndexedElement method : methods) {
  13.494 -//            if (method.getKind() == ElementKind.METHOD || method.getKind() == ElementKind.CONSTRUCTOR) {
  13.495 -//                // getInheritedMethods may return methods ON fqn itself
  13.496 -//                if (!method.getIn().equals(className)) {
  13.497 -//                    return (IndexedMethod)method;
  13.498 -//                }
  13.499 -//            }
  13.500 -//        }
  13.501 -//
  13.502 -//        return null;
  13.503 -    }
  13.504 -
  13.505 -    /** Get the super class of the given class */
  13.506 -    public Set<IndexedElement> getSuperClasses(String className) {
  13.507 -        final Set<IndexResult> result = new HashSet<>();
  13.508 -
  13.509 -        search(PythonIndexer.FIELD_CLASS_NAME, className, QuerySupport.Kind.EXACT, result, PythonIndexer.FIELD_EXTENDS_NAME, PythonIndexer.FIELD_CLASS_NAME);
  13.510 -
  13.511 -        Set<String> classNames = new HashSet<>();
  13.512 -        for (IndexResult map : result) {
  13.513 -            String[] extendsClasses = map.getValues(PythonIndexer.FIELD_EXTENDS_NAME);
  13.514 -            if (extendsClasses != null && extendsClasses.length > 0) {
  13.515 -                for (String clzName : extendsClasses) {
  13.516 -                    classNames.add(clzName);
  13.517 -                }
  13.518 -            }
  13.519 -        }
  13.520 -
  13.521 -        String[] terms = { PythonIndexer.FIELD_IN, PythonIndexer.FIELD_CLASS_NAME };
  13.522 -
  13.523 -        Set<IndexedElement> superClasses = new HashSet<>();
  13.524 -
  13.525 -        for (String superClz : classNames) {
  13.526 -            result.clear();
  13.527 -            search(PythonIndexer.FIELD_CLASS_NAME, superClz, QuerySupport.Kind.EXACT, result, terms);
  13.528 -            for (IndexResult map : result) {
  13.529 -                assert superClz.equals(map.getValue(PythonIndexer.FIELD_CLASS_NAME));
  13.530 -                String url = map.getUrl().toExternalForm();
  13.531 -                String module = map.getValue(PythonIndexer.FIELD_IN);
  13.532 -                IndexedElement clz = new IndexedElement(superClz, ElementKind.CLASS, url, module, null, null);
  13.533 -                superClasses.add(clz);
  13.534 -            }
  13.535 -        }
  13.536 -
  13.537 -        return superClasses;
  13.538 -    }
  13.539 -
  13.540 -    /**
  13.541 -     * Get the set of inherited (through super classes and mixins) for the given fully qualified class name.
  13.542 -     * @param classFqn FQN: module1::module2::moduleN::class
  13.543 -     * @param prefix If kind is QuerySupport.Kind.PREFIX/CASE_INSENSITIVE_PREFIX, a prefix to filter methods by. Else,
  13.544 -     *    if kind is QuerySupport.Kind.EXACT filter methods by the exact name.
  13.545 -     * @param kind Whether the prefix field should be taken as a prefix or a whole name
  13.546 -     */
  13.547 -    public Set<IndexedElement> getInheritedElements(String classFqn, String prefix, QuerySupport.Kind kind) {
  13.548 -        return getInheritedElements(classFqn, prefix, kind, false);
  13.549 -    }
  13.550 -
  13.551 -    public Set<IndexedElement> getInheritedElements(String classFqn, String prefix, QuerySupport.Kind kind, boolean includeOverrides) {
  13.552 -        boolean haveRedirected = false;
  13.553 -
  13.554 -        if (classFqn == null) {
  13.555 -            classFqn = OBJECT;
  13.556 -            haveRedirected = true;
  13.557 -        }
  13.558 -
  13.559 -        //String field = PythonIndexer.FIELD_FQN_NAME;
  13.560 -        Set<IndexedElement> elements = new HashSet<>();
  13.561 -        Set<String> scannedClasses = new HashSet<>();
  13.562 -        Set<String> seenSignatures = new HashSet<>();
  13.563 -
  13.564 -        if (prefix == null) {
  13.565 -            prefix = "";
  13.566 -        }
  13.567 -
  13.568 -//        String searchUrl = null;
  13.569 -//        if (context != null) {
  13.570 -//            try {
  13.571 -//                searchUrl = context.getFile().getFileObject().getURL().toExternalForm();
  13.572 -//            } catch (FileStateInvalidException ex) {
  13.573 -//                Exceptions.printStackTrace(ex);
  13.574 -//            }
  13.575 -//        }
  13.576 -
  13.577 -        addMethodsFromClass(prefix, kind, classFqn, elements, seenSignatures, scannedClasses,
  13.578 -                haveRedirected, false, includeOverrides, 0);
  13.579 -
  13.580 -        return elements;
  13.581 -    }
  13.582 -
  13.583 -    /** Return whether the specific class referenced (classFqn) was found or not. This is
  13.584 -     * not the same as returning whether any classes were added since it may add
  13.585 -     * additional methods from parents (Object/Class).
  13.586 -     */
  13.587 -    private boolean addMethodsFromClass(String prefix, QuerySupport.Kind kind, String classFqn, Set<IndexedElement> elements, Set<String> seenSignatures, Set<String> scannedClasses, boolean haveRedirected, boolean inheriting, boolean includeOverrides, int depth) {
  13.588 -        // Prevent problems with circular includes or redundant includes
  13.589 -        if (scannedClasses.contains(classFqn)) {
  13.590 -            return false;
  13.591 -        }
  13.592 -
  13.593 -        scannedClasses.add(classFqn);
  13.594 -
  13.595 -        String searchField = PythonIndexer.FIELD_CLASS_NAME;
  13.596 -
  13.597 -        Set<IndexResult> result = new HashSet<>();
  13.598 -
  13.599 -        String[] terms = {PythonIndexer.FIELD_IN,
  13.600 -                          PythonIndexer.FIELD_EXTENDS_NAME,
  13.601 -                          PythonIndexer.FIELD_MEMBER,
  13.602 -                          PythonIndexer.FIELD_CLASS_NAME};
  13.603 -        
  13.604 -        
  13.605 -        search(searchField, classFqn, QuerySupport.Kind.EXACT, result, terms);
  13.606 -
  13.607 -        boolean foundIt = result.size() > 0;
  13.608 -
  13.609 -        // If this is a bogus class entry (no search rsults) don't continue
  13.610 -        if (!foundIt) {
  13.611 -            return foundIt;
  13.612 -        }
  13.613 -
  13.614 -        List<String> extendsClasses = null;
  13.615 -
  13.616 -        String classIn = null;
  13.617 -        int fqnIndex = classFqn.lastIndexOf("::"); // NOI18N
  13.618 -
  13.619 -        if (fqnIndex != -1) {
  13.620 -            classIn = classFqn.substring(0, fqnIndex);
  13.621 -        }
  13.622 -        int prefixLength = prefix.length();
  13.623 -
  13.624 -        for (IndexResult map : result) {
  13.625 -            assert map != null;
  13.626 -
  13.627 -            String url = map.getUrl().toExternalForm();
  13.628 -            String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
  13.629 -            String module = map.getValue(PythonIndexer.FIELD_IN);
  13.630 -
  13.631 -            if (extendsClasses == null) {
  13.632 -                String[] ext = map.getValues(PythonIndexer.FIELD_EXTENDS_NAME);
  13.633 -                if (ext != null && ext.length > 0) {
  13.634 -                    if (extendsClasses == null) {
  13.635 -                        extendsClasses = Arrays.asList(ext);
  13.636 -                    } else {
  13.637 -                        extendsClasses = new ArrayList<>(extendsClasses);
  13.638 -                        extendsClasses.addAll(Arrays.asList(ext));
  13.639 -                    }
  13.640 -                }
  13.641 -            }
  13.642 -
  13.643 -            String[] members = map.getValues(PythonIndexer.FIELD_MEMBER);
  13.644 -
  13.645 -            if (members != null) {
  13.646 -                for (String signature : members) {
  13.647 -                    // Prevent duplicates when method is redefined
  13.648 -                    if (includeOverrides || !seenSignatures.contains(signature)) {
  13.649 -                        if (signature.startsWith(prefix)) {
  13.650 -                            if (kind == QuerySupport.Kind.EXACT) {
  13.651 -                                if (signature.charAt(prefixLength) != ';') {
  13.652 -                                    continue;
  13.653 -                                }
  13.654 -                            } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !signature.regionMatches(true, 0, prefix, 0, prefix.length())) {
  13.655 -                                continue;
  13.656 -                            } else {
  13.657 -                                // REGEXP, CAMELCASE filtering etc. not supported here
  13.658 -                                assert (kind == QuerySupport.Kind.PREFIX) ||
  13.659 -                                        (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
  13.660 -                            }
  13.661 -
  13.662 -                            if (!includeOverrides) {
  13.663 -                                seenSignatures.add(signature);
  13.664 -                            }
  13.665 -                            IndexedElement element = IndexedElement.create(signature, module, url, clz);
  13.666 -                            // TODO - filter out private? Or let code completer do that? Probably should, in case
  13.667 -                            // we have more rights when inheriting
  13.668 -                            element.setSmart(!haveRedirected);
  13.669 -                            element.setInherited(inheriting);
  13.670 -                            if (includeOverrides) {
  13.671 -                                element.setOrder(depth);
  13.672 -                            }
  13.673 -                            elements.add(element);
  13.674 -                        }
  13.675 -                    }
  13.676 -                }
  13.677 -            }
  13.678 -        }
  13.679 -
  13.680 -        if (classFqn.equals(OBJECT)) {
  13.681 -            return foundIt;
  13.682 -        }
  13.683 -
  13.684 -        if (extendsClasses == null || extendsClasses.size() == 0) {
  13.685 -            addMethodsFromClass(prefix, kind, OBJECT, elements, seenSignatures, scannedClasses,
  13.686 -                    true, true, includeOverrides, depth + 1);
  13.687 -        } else {
  13.688 -            // We're not sure we have a fully qualified path, so try some different candidates
  13.689 -            for (String extendsClass : extendsClasses) {
  13.690 -                if (!addMethodsFromClass(prefix, kind, extendsClass, elements, seenSignatures,
  13.691 -                        scannedClasses, haveRedirected, true, includeOverrides, depth + 1)) {
  13.692 -                    // Search by classIn
  13.693 -                    String fqn = classIn;
  13.694 -
  13.695 -                    while (fqn != null) {
  13.696 -                        if (addMethodsFromClass(prefix, kind, fqn + "::" + extendsClass, elements,
  13.697 -                                seenSignatures, scannedClasses, haveRedirected, true, includeOverrides, depth + 1)) {
  13.698 -                            break;
  13.699 -                        }
  13.700 -
  13.701 -                        int f = fqn.lastIndexOf("::"); // NOI18N
  13.702 -
  13.703 -                        if (f == -1) {
  13.704 -                            break;
  13.705 -                        } else {
  13.706 -                            fqn = fqn.substring(0, f);
  13.707 -                        }
  13.708 -                    }
  13.709 -                }
  13.710 -            }
  13.711 -        }
  13.712 -
  13.713 -        return foundIt;
  13.714 -    }
  13.715 -    
  13.716 -    
  13.717 -    public Set<IndexedElement> getAllMembers(String name, QuerySupport.Kind kind, PythonParserResult context, boolean includeDuplicates) {
  13.718 -        final Set<IndexResult> result = new HashSet<>();
  13.719 -        // TODO - handle case sensitivity better...
  13.720 -        String field = PythonIndexer.FIELD_MEMBER;
  13.721 -        QuerySupport.Kind originalKind = kind;
  13.722 -        if (kind == QuerySupport.Kind.EXACT) {
  13.723 -            // I can't do exact searches on methods because the method
  13.724 -            // entries include signatures etc. So turn this into a prefix
  13.725 -            // search and then compare chopped off signatures with the name
  13.726 -            kind = QuerySupport.Kind.PREFIX;
  13.727 -        }
  13.728 -
  13.729 -        String searchUrl = null;
  13.730 -        if (context != null) {
  13.731 -            searchUrl = context.getSnapshot().getSource().getFileObject().toURL().toExternalForm();
  13.732 -        }
  13.733 -
  13.734 -        String[] terms = {PythonIndexer.FIELD_IN,
  13.735 -                          PythonIndexer.FIELD_EXTENDS_NAME,
  13.736 -                          PythonIndexer.FIELD_MEMBER,
  13.737 -                          PythonIndexer.FIELD_CLASS_NAME};
  13.738 -
  13.739 -        search(field, name, kind, result, terms);
  13.740 -
  13.741 -//        Set<String> uniqueClasses = null;
  13.742 -//        if (includeDuplicates) {
  13.743 -//            uniqueClasses = null;
  13.744 -//        } else if (uniqueClasses == null) {
  13.745 -//            uniqueClasses = new HashSet<String>();
  13.746 -//        }
  13.747 -
  13.748 -        final Set<IndexedElement> members = new HashSet<>();
  13.749 -        int nameLength = name.length();
  13.750 -
  13.751 -        for (IndexResult map : result) {
  13.752 -            String[] signatures = map.getValues(PythonIndexer.FIELD_MEMBER);
  13.753 -            if (signatures != null && signatures.length > 0) {
  13.754 -                String url = map.getUrl().toExternalForm();
  13.755 -                String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
  13.756 -                String module = map.getValue(PythonIndexer.FIELD_IN);
  13.757 -                boolean inherited = searchUrl == null || !searchUrl.equals(url);
  13.758 -
  13.759 -                for (String signature : signatures) {
  13.760 -                    if (originalKind == QuerySupport.Kind.EXACT) {
  13.761 -                        if (signature.charAt(nameLength) != ';') {
  13.762 -                            continue;
  13.763 -                        }
  13.764 -                    } else if (originalKind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !signature.regionMatches(true, 0, name, 0, name.length())) {
  13.765 -                        continue;
  13.766 -                    } else {
  13.767 -                        // REGEXP, CAMELCASE filtering etc. not supported here
  13.768 -                        assert (originalKind == QuerySupport.Kind.PREFIX) ||
  13.769 -                                (originalKind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
  13.770 -                    }
  13.771 -
  13.772 -                    IndexedElement element = IndexedElement.create(signature, module, url, clz);
  13.773 -                    element.setInherited(inherited);
  13.774 -                    members.add(element);
  13.775 -                }
  13.776 -            }
  13.777 -        }
  13.778 -
  13.779 -        return members;
  13.780 -    }
  13.781 -    
  13.782 -    public Set<IndexedElement> getAllElements(String name, QuerySupport.Kind kind, PythonParserResult context, boolean includeDuplicates) {
  13.783 -        final Set<IndexResult> result = new HashSet<>();
  13.784 -        // TODO - handle case sensitivity better...
  13.785 -        String field = PythonIndexer.FIELD_ITEM;
  13.786 -        QuerySupport.Kind originalKind = kind;
  13.787 -        if (kind == QuerySupport.Kind.EXACT) {
  13.788 -            // I can't do exact searches on methods because the method
  13.789 -            // entries include signatures etc. So turn this into a prefix
  13.790 -            // search and then compare chopped off signatures with the name
  13.791 -            kind = QuerySupport.Kind.PREFIX;
  13.792 -        }
  13.793 -
  13.794 -        String searchUrl = null;
  13.795 -        if (context != null) {
  13.796 -            searchUrl = context.getSnapshot().getSource().getFileObject().toURL().toExternalForm();
  13.797 -        }
  13.798 -
  13.799 -        String[] terms = { PythonIndexer.FIELD_ITEM,
  13.800 -                           PythonIndexer.FIELD_MODULE_NAME };
  13.801 -
  13.802 -        search(field, name, kind, result, terms);
  13.803 -
  13.804 -        final Set<IndexedElement> elements = new HashSet<>();
  13.805 -        int nameLength = name.length();
  13.806 -
  13.807 -        for (IndexResult map : result) {
  13.808 -            String[] signatures = map.getValues(PythonIndexer.FIELD_ITEM);
  13.809 -            if (signatures != null && signatures.length > 0) {
  13.810 -                String url = map.getUrl().toExternalForm();
  13.811 -                String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
  13.812 -                boolean inherited = searchUrl == null || !searchUrl.equals(url);
  13.813 -
  13.814 -                for (String signature : signatures) {
  13.815 -                    if (originalKind == QuerySupport.Kind.EXACT) {
  13.816 -                        if (signature.charAt(nameLength) != ';') {
  13.817 -                            continue;
  13.818 -                        }
  13.819 -                    } else if (originalKind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !signature.regionMatches(true, 0, name, 0, name.length())) {
  13.820 -                        continue;
  13.821 -                    } else {
  13.822 -                        // REGEXP, CAMELCASE filtering etc. not supported here
  13.823 -                        assert (originalKind == QuerySupport.Kind.PREFIX) ||
  13.824 -                                (originalKind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
  13.825 -                    }
  13.826 -
  13.827 -                    IndexedElement element = IndexedElement.create(signature, module, url, null);
  13.828 -                    if (element.isPrivate() && !url.equals(searchUrl)) {
  13.829 -                        continue;
  13.830 -                    }
  13.831 -                    element.setInherited(inherited);
  13.832 -                    elements.add(element);
  13.833 -                }
  13.834 -            }
  13.835 -        }
  13.836 -
  13.837 -        return elements;
  13.838 -    }
  13.839 -
  13.840 -    public Set<String> getBuiltinSymbols() {
  13.841 -        Set<String> modules = new HashSet<>();
  13.842 -
  13.843 -        // The "functions" module is always imported by the interpreter, and ditto
  13.844 -        // for exceptions, constants, etc.
  13.845 -        //modules.add("objects"); // NOI18N -- just links to the others
  13.846 -        modules.addAll(BUILTIN_MODULES);
  13.847 -
  13.848 -        Set<String> symbols = new HashSet<>(250);
  13.849 -
  13.850 -        String[] terms = { PythonIndexer.FIELD_MODULE_NAME,
  13.851 -                           PythonIndexer.FIELD_ITEM };
  13.852 -
  13.853 -        // Look up all symbols
  13.854 -        for (String module : modules) {
  13.855 -            final Set<IndexResult> result = new HashSet<>();
  13.856 -            // TODO - handle case sensitivity better...
  13.857 -            String field = PythonIndexer.FIELD_MODULE_NAME;
  13.858 -            QuerySupport.Kind kind = QuerySupport.Kind.EXACT;
  13.859 -
  13.860 -            search(field, module, kind, result, terms);
  13.861 -
  13.862 -            for (IndexResult map : result) {
  13.863 -                String[] signatures = map.getValues(PythonIndexer.FIELD_ITEM);
  13.864 -                if (signatures != null) {
  13.865 -                    for (String signature : signatures) {
  13.866 -                        int semi = signature.indexOf(';');
  13.867 -                        assert semi != -1;
  13.868 -                        int flags = IndexedElement.decode(signature, semi + 3, 0);
  13.869 -                        if ((flags & IndexedElement.PRIVATE) != 0) {
  13.870 -                            // Skip private symbols - can't import those
  13.871 -                            continue;
  13.872 -                        }
  13.873 -                        String name = signature.substring(0, semi);
  13.874 -                        symbols.add(name);
  13.875 -                    }
  13.876 -                }
  13.877 -            }
  13.878 -        }
  13.879 -
  13.880 -        // Computed as described below
  13.881 -        String[] MISSING = {
  13.882 -            "Ellipsis", "False", "IndentationError", "None", "NotImplemented", "TabError", // NOI18N
  13.883 -            "True", "__debug__", "__doc__", "__name__", "copyright", "credits", "exit", "license", // NOI18N
  13.884 -            "quit" // NOI18N
  13.885 -        };
  13.886 -        for (String s : MISSING) {
  13.887 -            symbols.add(s);
  13.888 -        }
  13.889 -        symbols.add("__builtins__"); // NOI18N
  13.890 -        symbols.add("__file__"); // NOI18N
  13.891 -
  13.892 -        //// COMPUTING MISSING SYMBOLS:
  13.893 -        //// My builtin .rst files don't seem to define all the builtin symbols that the Python
  13.894 -        //// interpreter is configured with.  I generated these pretty trivially; run
  13.895 -        //// python and type "dir(__builtins__)" and you end up a list like the below:
  13.896 -        ////String[] EXTRA_BUILTINS = {"ArithmeticError", "AssertionError", "AttributeError", "BaseException",
  13.897 -        //    "DeprecationWarning", "EOFError", "Ellipsis", "EnvironmentError", "Exception", "False",
  13.898 -        //    "FloatingPointError", "FutureWarning", "GeneratorExit", "IOError", "ImportError",
  13.899 -        //    "ImportWarning", "IndentationError", "IndexError", "KeyError", "KeyboardInterrupt",
  13.900 -        //    "LookupError", "MemoryError", "NameError", "None", "NotImplemented", "NotImplementedError",
  13.901 -        //    "OSError", "OverflowError", "PendingDeprecationWarning", "ReferenceError", "RuntimeError",
  13.902 -        //    "RuntimeWarning", "StandardError", "StopIteration", "SyntaxError", "SyntaxWarning", "SystemError",
  13.903 -        //    "SystemExit", "TabError", "True", "TypeError", "UnboundLocalError", "UnicodeDecodeError",
  13.904 -        //    "UnicodeEncodeError", "UnicodeError", "UnicodeTranslateError", "UnicodeWarning", "UserWarning",
  13.905 -        //    "ValueError", "Warning", "ZeroDivisionError", "__debug__", "__doc__", "__import__", "__name__",
  13.906 -        //    "abs", "all", "any", "apply", "basestring", "bool", "buffer", "callable", "chr", "classmethod",
  13.907 -        //    "cmp", "coerce", "compile", "complex", "copyright", "credits", "delattr", "dict", "dir", "divmod",
  13.908 -        //    "enumerate", "eval", "execfile", "exit", "file", "filter", "float", "frozenset", "getattr",
  13.909 -        //    "globals", "hasattr", "hash", "help", "hex", "id", "input", "int", "intern", "isinstance",
  13.910 -        //    "issubclass", "iter", "len", "license", "list", "locals", "long", "map", "max", "min", "object",
  13.911 -        //    "oct", "open", "ord", "pow", "property", "quit", "range", "raw_input", "reduce", "reload",
  13.912 -        //    "repr", "reversed", "round", "set", "setattr", "slice", "sorted", "staticmethod", "str", "sum",
  13.913 -        //    "super", "tuple", "type", "unichr", "unicode", "vars", "xrange", "zip"};
  13.914 -        //// Most of these will be defined by my index search. However, for the missing ones, let's add them
  13.915 -        //// in. The following code computes the delta and produces a source-like string for it.
  13.916 -        //// It also counts the total symbol map size so we can pick a reasonable default:
  13.917 -        //List<String> asList = Arrays.asList(EXTRA_BUILTINS);
  13.918 -        //Set<String> asSet = new HashSet<String>(asList);
  13.919 -        //asSet.removeAll(symbols);
  13.920 -        //List<String> missing = new ArrayList<String>(asSet);
  13.921 -        //Collections.sort(missing);
  13.922 -        //int width = 0;
  13.923 -        //StringBuilder sb = new StringBuilder();
  13.924 -        //for (String s : missing) {
  13.925 -        //    sb.append('"');
  13.926 -        //    sb.append(s);
  13.927 -        //    sb.append('"');
  13.928 -        //    sb.append(',');
  13.929 -        //    sb.append(' ');
  13.930 -        //    width += s.length()+4;
  13.931 -        //    if (width > 70) {
  13.932 -        //        sb.append("\n");
  13.933 -        //        width = 0;
  13.934 -        //    }
  13.935 -        //}
  13.936 -        //String missingCode = "String[] MISSING = {\n" + sb.toString() + "\n};\n";
  13.937 -        //symbols.addAll(asList);
  13.938 -        //int requiredSetSize = symbols.size();
  13.939 -
  13.940 -        return symbols;
  13.941 -    }
  13.942 -
  13.943 -    @SuppressWarnings("unchecked")
  13.944 -    public Set<String> getImportsFor(String ident, boolean includeSymbol) {
  13.945 -        Set<String> modules = new HashSet<>(10);
  13.946 -
  13.947 -        final Set<IndexResult> result = new HashSet<>();
  13.948 -        search(PythonIndexer.FIELD_MODULE_NAME, ident, QuerySupport.Kind.EXACT, result, PythonIndexer.FIELD_MODULE_NAME);
  13.949 -        for (IndexResult map : result) {
  13.950 -            String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
  13.951 -            if (module != null) {
  13.952 -                // TODO - record more information about this, such as the FQN
  13.953 -                // so it's easier for the user to disambiguate
  13.954 -                modules.add(module);
  13.955 -            }
  13.956 -        }
  13.957 -
  13.958 -        // TODO - handle case sensitivity better...
  13.959 -        String field = PythonIndexer.FIELD_ITEM;
  13.960 -        QuerySupport.Kind kind = QuerySupport.Kind.PREFIX; // We're storing encoded signatures so not exact matches
  13.961 -
  13.962 -        String[] terms = { PythonIndexer.FIELD_ITEM,
  13.963 -                           PythonIndexer.FIELD_MODULE_NAME };
  13.964 -
  13.965 -        result.clear();
  13.966 -        search(field, ident, kind, result, terms);
  13.967 -        String match = ident + ";";
  13.968 -
  13.969 -        MapSearch:
  13.970 -        for (IndexResult map : result) {
  13.971 -            String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
  13.972 -            if (module == null) {
  13.973 -                continue;
  13.974 -            }
  13.975 -
  13.976 -            if (module.indexOf('-') != -1) {
  13.977 -                // Don't include modules with -; these aren't real module
  13.978 -                // names (usually python scripts in directories containing a dash
  13.979 -                // that I incorrectly compute a module name for
  13.980 -                continue;
  13.981 -            }
  13.982 -
  13.983 -            String[] members = map.getValues(PythonIndexer.FIELD_ITEM);
  13.984 -            if (members == null || members.length == 0) {
  13.985 -                continue;
  13.986 -            }
  13.987 -
  13.988 -            int semi = match.length() - 1;
  13.989 -
  13.990 -            for (String signature : members) {
  13.991 -                if (signature.startsWith(match)) {
  13.992 -                    if (includeSymbol) {
  13.993 -                        int flags = IndexedElement.decode(signature, semi + 3, 0);
  13.994 -                        if ((flags & IndexedElement.PRIVATE) != 0) {
  13.995 -                            // Skip private symbols - can't import those
  13.996 -                            continue;
  13.997 -                        }
  13.998 -                        String sig = ident;
  13.999 -                        char type = signature.charAt(semi + 1);
 13.1000 -                        if (type == 'F') {
 13.1001 -                            int sigStart = signature.indexOf(';', semi + 3) + 1;
 13.1002 -                            int sigEnd = signature.indexOf(';', sigStart);
 13.1003 -                            sig = ident + "(" + signature.substring(sigStart, sigEnd) + ")"; // NOI18N
 13.1004 -                        } else if (type == 'I') {
 13.1005 -                            // Don't provide modules that just -import- the symbol
 13.1006 -                            continue;
 13.1007 -                        }
 13.1008 -                        if (!sig.equals(module)) {
 13.1009 -                            modules.add(module + ": " + sig); // NOI18N
 13.1010 -                        } else {
 13.1011 -                            modules.add(module);
 13.1012 -                        }
 13.1013 -                    } else {
 13.1014 -                        modules.add(module);
 13.1015 -                    }
 13.1016 -                    continue MapSearch;
 13.1017 -                }
 13.1018 -            }
 13.1019 -        }
 13.1020 -
 13.1021 -        return modules;
 13.1022 -    }
 13.1023 -    
 13.1024 -    public Set<IndexedElement> getImportedElements(String prefix, QuerySupport.Kind kind, PythonParserResult context, List<Import> imports, List<ImportFrom> importsFrom) {
 13.1025 -        // TODO - separate methods from variables?? E.g. if you have method Foo() and class Foo
 13.1026 -        // coming from different places
 13.1027 -        
 13.1028 -        
 13.1029 -//        Set<String> imported = new HashSet<String>();
 13.1030 -//
 13.1031 -        Set<IndexedElement> elements = new HashSet<>();
 13.1032 -
 13.1033 -        // Look up the imports and compute all the symbols we get from the import
 13.1034 -        Set<String> modules = new HashSet<>();
 13.1035 -
 13.1036 -        // ImportsFrom require no index lookup
 13.1037 -        for (ImportFrom from : importsFrom) {
 13.1038 -            if (ImportManager.isFutureImport(from)) {
 13.1039 -                continue;
 13.1040 -            }
 13.1041 -            List<alias> names = from.getInternalNames();
 13.1042 -            if (names != null) {
 13.1043 -                for (alias at : names) {
 13.1044 -                    if ("*".equals(at.getInternalName())) { // NOI18N
 13.1045 -                        modules.add(from.getInternalModule());
 13.1046 -//                    } else {
 13.1047 -//                        String name = at.getInternalAsname() != null ? at.getInternalAsname() : at.getInternalName();
 13.1048 -//                        assert name.length() > 0;
 13.1049 -//                        imported.add(name);
 13.1050 -                    }
 13.1051 -                }
 13.1052 -            }
 13.1053 -        }
 13.1054 -
 13.1055 -//        for (Import imp : imports) {
 13.1056 -//            if (imp.names != null) {
 13.1057 -//                for (alias at : imp.getInternalNames()) {
 13.1058 -//                    if (at.getInternalAsname() != null) {
 13.1059 -//                        String name = at.getInternalAsname();
 13.1060 -//                        assert name.length() > 0;
 13.1061 -//                        imported.add(name);
 13.1062 -//                    } else {
 13.1063 -//                        imported.add(at.getInternalName());
 13.1064 -//                    }
 13.1065 -//                }
 13.1066 -//            }
 13.1067 -//        }
 13.1068 -//
 13.1069 -//
 13.1070 -//        // Create variable items for the locally imported symbols
 13.1071 -//        for (String name : imported) {
 13.1072 -//            if (name.startsWith(prefix)) {
 13.1073 -//                if (kind == QuerySupport.Kind.EXACT) {
 13.1074 -//                    // Ensure that the method is not longer than the prefix
 13.1075 -//                    if ((name.length() > prefix.length()) &&
 13.1076 -//                            (name.charAt(prefix.length()) != '(') &&
 13.1077 -//                            (name.charAt(prefix.length()) != ';')) {
 13.1078 -//                        continue;
 13.1079 -//                    }
 13.1080 -//                } else {
 13.1081 -//                    // REGEXP, CAMELCASE filtering etc. not supported here
 13.1082 -//                    assert (kind == QuerySupport.Kind.PREFIX) ||
 13.1083 -//                    (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
 13.1084 -//                }
 13.1085 -//    String url = null;
 13.1086 -//                ElementKind elementKind = ElementKind.VARIABLE;
 13.1087 -//                if (Character.isUpperCase(name.charAt(0))) {
 13.1088 -//                    // Class?
 13.1089 -//                    elementKind = ElementKind.CLASS;
 13.1090 -//                }
 13.1091 -//                IndexedElement element = new IndexedElement(name, elementKind, url, null);
 13.1092 -//                element.setSmart(true);
 13.1093 -//                elements.add(element);
 13.1094 -//                // TODO - imported class symbls should be shown as classes!
 13.1095 -//            }
 13.1096 -//        }
 13.1097 -
 13.1098 -        // Always include the current file as imported
 13.1099 -        String moduleName = null;
 13.1100 -        if (context != null) {
 13.1101 -            moduleName = PythonUtils.getModuleName(context.getSnapshot().getSource().getFileObject());
 13.1102 -            modules.add(moduleName);
 13.1103 -        }
 13.1104 -
 13.1105 -        modules.addAll(BUILTIN_MODULES);
 13.1106 -
 13.1107 -        addImportedElements(prefix, kind, modules, elements, null);
 13.1108 -
 13.1109 -        return elements;
 13.1110 -    }
 13.1111 -    public Set<String> getImportedFromWildcards(List<ImportFrom> importsFrom) {
 13.1112 -        Set<String> symbols = new HashSet<>(100);
 13.1113 -
 13.1114 -        // Look up the imports and compute all the symbols we get from the import
 13.1115 -        Set<String> modules = new HashSet<>();
 13.1116 -
 13.1117 -        // ImportsFrom require no index lookup
 13.1118 -        for (ImportFrom from : importsFrom) {
 13.1119 -            List<alias> names = from.getInternalNames();
 13.1120 -            if (names != null) {
 13.1121 -                for (alias at : names) {
 13.1122 -                    if ("*".equals(at.getInternalName())) { // NOI18N
 13.1123 -                        modules.add(from.getInternalModule());
 13.1124 -                    }
 13.1125 -                }
 13.1126 -            }
 13.1127 -        }
 13.1128 -
 13.1129 -        String[] terms = { PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MODULE_NAME };
 13.1130 -
 13.1131 -        // Look up all symbols
 13.1132 -        for (String module : modules) {
 13.1133 -            // TODO - cache builtins?
 13.1134 -            Set<String> moduleSymbols = symbols;
 13.1135 -            boolean isSystem = isSystemModule(module);
 13.1136 -            if (isSystem) {
 13.1137 -                Set<String> s = wildcardImports.get(module);
 13.1138 -                if (s != null) {
 13.1139 -                    symbols.addAll(s);
 13.1140 -                    continue;
 13.1141 -                } else {
 13.1142 -                    moduleSymbols = new HashSet<>(100);
 13.1143 -                }
 13.1144 -            }
 13.1145 -
 13.1146 -
 13.1147 -            final Set<IndexResult> result = new HashSet<>();
 13.1148 -            // TODO - handle case sensitivity better...
 13.1149 -
 13.1150 -            search(PythonIndexer.FIELD_MODULE_NAME, module, QuerySupport.Kind.EXACT, result, terms);
 13.1151 -
 13.1152 -            for (IndexResult map : result) {
 13.1153 -                String[] items = map.getValues(PythonIndexer.FIELD_ITEM);
 13.1154 -                if (items != null) {
 13.1155 -                    for (String signature : items) {
 13.1156 -                        int semi = signature.indexOf(';');
 13.1157 -                        assert semi != -1;
 13.1158 -                        int flags = IndexedElement.decode(signature, semi + 3, 0);
 13.1159 -                        if ((flags & IndexedElement.PRIVATE) != 0) {
 13.1160 -                            // Skip private symbols - can't import those
 13.1161 -                            continue;
 13.1162 -                        }
 13.1163 -
 13.1164 -                        String name = signature.substring(0, semi);
 13.1165 -                        moduleSymbols.add(name);
 13.1166 -                    }
 13.1167 -                }
 13.1168 -            }
 13.1169 -
 13.1170 -            if (isSystem) {
 13.1171 -                assert moduleSymbols != symbols;
 13.1172 -                symbols.addAll(moduleSymbols);
 13.1173 -                wildcardImports.put(module, moduleSymbols);
 13.1174 -            }
 13.1175 -        }
 13.1176 -
 13.1177 -        return symbols;
 13.1178 -    }
 13.1179 -    
 13.1180 -    public Set<IndexedElement> getImportedElements(String prefix, QuerySupport.Kind kind, Set<String> modules, Set<String> systemModuleHolder) {
 13.1181 -        Set<IndexedElement> elements = new HashSet<>();
 13.1182 -
 13.1183 -        addImportedElements(prefix, kind, modules, elements, systemModuleHolder);
 13.1184 -
 13.1185 -        return elements;
 13.1186 -    }
 13.1187 -
 13.1188 -    public boolean isSystemModule(String module) {
 13.1189 -        if (systemModules == null) {
 13.1190 -            systemModules = new HashSet<>(800); // measured: 623
 13.1191 -            String[] terms = { PythonIndexer.FIELD_MODULE_ATTR_NAME,
 13.1192 -                               PythonIndexer.FIELD_MODULE_NAME };
 13.1193 -            final Set<IndexResult> result = new HashSet<>();
 13.1194 -
 13.1195 -            // This doesn't work because the attrs field isn't searchable:
 13.1196 -            //search(PythonIndexer.FIELD_MODULE_ATTR_NAME, "S", QuerySupport.Kind.PREFIX, result, ALL_SCOPE, terms);
 13.1197 -            //for (IndexResult map : result) {
 13.1198 -            //    assert map.getValue(PythonIndexer.FIELD_MODULE_ATTR_NAME).indexOf("S") != -1;
 13.1199 -            //    systemModules.add(map.getValue(PythonIndexer.FIELD_MODULE_NAME));
 13.1200 -            //}
 13.1201 -
 13.1202 -            search(PythonIndexer.FIELD_MODULE_NAME, "", QuerySupport.Kind.PREFIX, result, terms);
 13.1203 -
 13.1204 -            for (IndexResult map : result) {
 13.1205 -                String attrs = map.getValue(PythonIndexer.FIELD_MODULE_ATTR_NAME);
 13.1206 -                if (attrs != null && attrs.indexOf('S') != -1) {
 13.1207 -                    String mod = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
 13.1208 -                    systemModules.add(mod);
 13.1209 -                }
 13.1210 -            }
 13.1211 -        }
 13.1212 -
 13.1213 -        return systemModules.contains(module);
 13.1214 -    }
 13.1215 -
 13.1216 -    public boolean isLowercaseClassName(String clz) {
 13.1217 -        if (availableClasses == null) {
 13.1218 -            availableClasses = new HashSet<>(300); // measured: 193
 13.1219 -            final Set<IndexResult> result = new HashSet<>();
 13.1220 -
 13.1221 -            search(PythonIndexer.FIELD_CLASS_NAME, "", QuerySupport.Kind.PREFIX, result, PythonIndexer.FIELD_CLASS_NAME);
 13.1222 -
 13.1223 -            for (IndexResult map : result) {
 13.1224 -                String c = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
 13.1225 -                if (c != null && !Character.isUpperCase(c.charAt(0))) {
 13.1226 -                    availableClasses.add(c);
 13.1227 -                }
 13.1228 -            }
 13.1229 -        }
 13.1230 -
 13.1231 -        return availableClasses.contains(clz);
 13.1232 -    }
 13.1233 -    
 13.1234 -    public void addImportedElements(String prefix, QuerySupport.Kind kind, Set<String> modules, Set<IndexedElement> elements, Set<String> systemModuleHolder) {
 13.1235 -        
 13.1236 -        String[] terms = { PythonIndexer.FIELD_ITEM,
 13.1237 -                           PythonIndexer.FIELD_MODULE_ATTR_NAME,
 13.1238 -                           PythonIndexer.FIELD_MODULE_NAME };
 13.1239 -
 13.1240 -        // Look up all symbols
 13.1241 -        for (String module : modules) {
 13.1242 -            boolean isBuiltin = isBuiltinModule(module);
 13.1243 -            boolean isSystem = isBuiltin;
 13.1244 -
 13.1245 -            final Set<IndexResult> result = new HashSet<>();
 13.1246 -            // TODO - handle case sensitivity better...
 13.1247 -
 13.1248 -            search(PythonIndexer.FIELD_MODULE_NAME, module, QuerySupport.Kind.EXACT, result, terms);
 13.1249 -            int prefixLength = prefix.length();
 13.1250 -
 13.1251 -            for (IndexResult map : result) {
 13.1252 -                String url = map.getUrl().toExternalForm();
 13.1253 -                String[] items = map.getValues(PythonIndexer.FIELD_ITEM);
 13.1254 -                if (items != null) {
 13.1255 -                    String attrs = map.getValue(PythonIndexer.FIELD_MODULE_ATTR_NAME);
 13.1256 -                    if (attrs != null && attrs.indexOf('S') != -1) {
 13.1257 -                        isSystem = true;
 13.1258 -                    }
 13.1259 -                    for (String signature : items) {
 13.1260 -                        if (signature.startsWith(prefix)) {
 13.1261 -                            if (kind == QuerySupport.Kind.EXACT) {
 13.1262 -                                if (signature.charAt(prefixLength) != ';') {
 13.1263 -                                    continue;
 13.1264 -                                }
 13.1265 -                            } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !signature.regionMatches(true, 0, prefix, 0, prefix.length())) {
 13.1266 -                                continue;
 13.1267 -                            } else {
 13.1268 -                                // REGEXP, CAMELCASE filtering etc. not supported here
 13.1269 -                                assert (kind == QuerySupport.Kind.PREFIX) ||
 13.1270 -                                        (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
 13.1271 -                            }
 13.1272 -
 13.1273 -                            IndexedElement element = IndexedElement.create(signature, module, url, null);
 13.1274 -                            if (element.isPrivate()) {
 13.1275 -                                continue;
 13.1276 -                            }
 13.1277 -                            if (isBuiltin) {
 13.1278 -                                element.setRhs("<i>builtin</i>");
 13.1279 -                            } else {
 13.1280 -                                element.setSmart(true);
 13.1281 -                            }
 13.1282 -                            element.setInherited(true);
 13.1283 -                            elements.add(element);
 13.1284 -                        }
 13.1285 -                    }
 13.1286 -                }
 13.1287 -            }
 13.1288 -
 13.1289 -            if (systemModuleHolder != null && isSystem) {
 13.1290 -                systemModuleHolder.add(module);
 13.1291 -            }
 13.1292 -        }
 13.1293 -    }
 13.1294 -
 13.1295 -    public Set<IndexedElement> getExceptions(String prefix, QuerySupport.Kind kind) {
 13.1296 -        final Set<IndexResult> result = new HashSet<>();
 13.1297 -        String[] terms = { PythonIndexer.FIELD_EXTENDS_NAME,
 13.1298 -                              PythonIndexer.FIELD_CLASS_NAME,
 13.1299 -                              PythonIndexer.FIELD_CLASS_ATTR_NAME,
 13.1300 -                              PythonIndexer.FIELD_IN };
 13.1301 -        search(PythonIndexer.FIELD_EXTENDS_NAME, "", QuerySupport.Kind.PREFIX, result, terms); // NOI18N
 13.1302 -        Map<String, String> extendsMap = new HashMap<>(100);
 13.1303 -        // First iteration: Compute inheritance hierarchy
 13.1304 -        for (IndexResult map : result) {
 13.1305 -
 13.1306 -            String superClass = map.getValue(PythonIndexer.FIELD_EXTENDS_NAME);
 13.1307 -            if (superClass != null) {
 13.1308 -                String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
 13.1309 -                if (clz != null) {
 13.1310 -                    extendsMap.put(clz, superClass);
 13.1311 -                }
 13.1312 -            }
 13.1313 -        }
 13.1314 -
 13.1315 -        // Compute set of classes that extend Exception
 13.1316 -
 13.1317 -        Set<String> exceptionClasses = new HashSet<>();
 13.1318 -        Set<String> notExceptionClasses = new HashSet<>();
 13.1319 -        exceptionClasses.add("Exception"); // NOI18N
 13.1320 -        Outer:
 13.1321 -        for (String cls : extendsMap.keySet()) {
 13.1322 -            if (notExceptionClasses.contains(cls)) {
 13.1323 -                continue;
 13.1324 -            } else if (!exceptionClasses.contains(cls)) {
 13.1325 -                // See if this extends exception:
 13.1326 -                String c = cls;
 13.1327 -                int depth = 0;
 13.1328 -                while (c != null) {
 13.1329 -                    c = extendsMap.get(c);
 13.1330 -                    String prev = null;
 13.1331 -                    if (c != null) {
 13.1332 -                        if (exceptionClasses.contains(c)) {
 13.1333 -                            exceptionClasses.add(cls);
 13.1334 -                            continue Outer;
 13.1335 -                        }
 13.1336 -                        depth++;
 13.1337 -                        if (depth == 15) {
 13.1338 -                            // we're probably going in circles, perhaps a extends b extends a.
 13.1339 -                            // This doesn't really happen in Python, but can happen when there
 13.1340 -                            // are unrelated classes with the same name getting treated as one here -
 13.1341 -                            // class a in library X, and class a in library Y,
 13.1342 -                            break;
 13.1343 -                        }
 13.1344 -                    } else if (prev != null) {
 13.1345 -                        notExceptionClasses.add(prev);
 13.1346 -                        break;
 13.1347 -                    }
 13.1348 -                }
 13.1349 -                notExceptionClasses.add(cls);
 13.1350 -            }
 13.1351 -        }
 13.1352 -
 13.1353 -        // Next add elements for all the exceptions
 13.1354 -        final Set<IndexedElement> classes = new HashSet<>();
 13.1355 -        for (IndexResult map : result) {
 13.1356 -            String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
 13.1357 -            if (clz == null || !exceptionClasses.contains(clz)) {
 13.1358 -                continue;
 13.1359 -            }
 13.1360 -
 13.1361 -            if ((kind == QuerySupport.Kind.PREFIX) && !clz.startsWith(prefix)) {
 13.1362 -                continue;
 13.1363 -            } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !clz.regionMatches(true, 0, prefix, 0, prefix.length())) {
 13.1364 -                continue;
 13.1365 -            } else if (kind == QuerySupport.Kind.EXACT && !clz.equals(prefix)) {
 13.1366 -                continue;
 13.1367 -            }
 13.1368 -
 13.1369 -            String url = map.getUrl().toExternalForm();
 13.1370 -            String module = map.getValue(PythonIndexer.FIELD_IN);
 13.1371 -            IndexedElement element = new IndexedElement(clz, ElementKind.CLASS, url, module, null, null);
 13.1372 -            String attrs = map.getValue(PythonIndexer.FIELD_CLASS_ATTR_NAME);
 13.1373 -            if (attrs != null) {
 13.1374 -                int flags = IndexedElement.decode(attrs, 0, 0);
 13.1375 -                element.setFlags(flags);
 13.1376 -            }
 13.1377 -            classes.add(element);
 13.1378 -        }
 13.1379 -
 13.1380 -        return classes;
 13.1381 -    }
 13.1382 -
 13.1383 -    /** Find the subclasses of the given class name, with the POSSIBLE fqn from the
 13.1384 -     * context of the usage. */
 13.1385 -    public Set<IndexedElement> getSubClasses(String fqn, String possibleFqn, String name, boolean directOnly) {
 13.1386 -        //String field = PythonIndexer.FIELD_FQN_NAME;
 13.1387 -        Set<IndexedElement> classes = new HashSet<>();
 13.1388 -        Set<String> scannedClasses = new HashSet<>();
 13.1389 -        Set<String> seenClasses = new HashSet<>();
 13.1390 -
 13.1391 -        if (fqn != null) {
 13.1392 -            addSubclasses(fqn, classes, seenClasses, scannedClasses, directOnly);
 13.1393 -        } else {
 13.1394 -            fqn = possibleFqn;
 13.1395 -            if (name.equals(possibleFqn)) {
 13.1396 -                fqn = null;
 13.1397 -            }
 13.1398 -
 13.1399 -            // Try looking at the libraries too
 13.1400 -            while ((classes.size() == 0) && (fqn != null && fqn.length() > 0)) {
 13.1401 -                // TODO - use the boolvalue from addclasses instead!
 13.1402 -                boolean found = addSubclasses(fqn + "::" + name, classes, seenClasses, scannedClasses, directOnly);
 13.1403 -                if (found) {
 13.1404 -                    return classes;
 13.1405 -                }
 13.1406 -
 13.1407 -                int f = fqn.lastIndexOf("::");
 13.1408 -
 13.1409 -                if (f == -1) {
 13.1410 -                    break;
 13.1411 -                } else {
 13.1412 -                    fqn = fqn.substring(0, f);
 13.1413 -                }
 13.1414 -            }
 13.1415 -
 13.1416 -            if (classes.size() == 0) {
 13.1417 -                addSubclasses(name, classes, seenClasses, scannedClasses, directOnly);
 13.1418 -            }
 13.1419 -        }
 13.1420 -
 13.1421 -        return classes;
 13.1422 -    }
 13.1423 -    
 13.1424 -    private boolean addSubclasses(String classFqn, Set<IndexedElement> classes, Set<String> seenClasses, Set<String> scannedClasses, boolean directOnly) {
 13.1425 -        // Prevent problems with circular includes or redundant includes
 13.1426 -        if (scannedClasses.contains(classFqn)) {
 13.1427 -            return false;
 13.1428 -        }
 13.1429 -
 13.1430 -        scannedClasses.add(classFqn);
 13.1431 -
 13.1432 -        String searchField = PythonIndexer.FIELD_EXTENDS_NAME;
 13.1433 -
 13.1434 -        Set<IndexResult> result = new HashSet<>();
 13.1435 -
 13.1436 -        String[] terms = { PythonIndexer.FIELD_IN,
 13.1437 -                              PythonIndexer.FIELD_EXTENDS_NAME,
 13.1438 -                              PythonIndexer.FIELD_CLASS_ATTR_NAME,
 13.1439 -                              PythonIndexer.FIELD_CLASS_NAME };
 13.1440 -
 13.1441 -        search(searchField, classFqn, QuerySupport.Kind.EXACT, result, terms);
 13.1442 -
 13.1443 -        boolean foundIt = result.size() > 0;
 13.1444 -
 13.1445 -        // If this is a bogus class entry (no search rsults) don't continue
 13.1446 -        if (!foundIt) {
 13.1447 -            return foundIt;
 13.1448 -        }
 13.1449 -
 13.1450 -        for (IndexResult map : result) {
 13.1451 -            String className = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
 13.1452 -            if (className != null && !seenClasses.contains(className)) {
 13.1453 -                String url = map.getUrl().toExternalForm();
 13.1454 -                String module = map.getValue(PythonIndexer.FIELD_IN);
 13.1455 -                IndexedElement clz = new IndexedElement(className, ElementKind.CLASS, url, module, null, null);
 13.1456 -                String attrs = map.getValue(PythonIndexer.FIELD_CLASS_ATTR_NAME);
 13.1457 -                if (attrs != null) {
 13.1458 -                    int flags = IndexedElement.decode(attrs, 0, 0);
 13.1459 -                    clz.setFlags(flags);
 13.1460 -                }
 13.1461 -                classes.add(clz);
 13.1462 -
 13.1463 -                seenClasses.add(className);
 13.1464 -
 13.1465 -                if (!directOnly) {
 13.1466 -                    addSubclasses(className, classes, seenClasses, scannedClasses, directOnly);
 13.1467 -                }
 13.1468 -            }
 13.1469 -        }
 13.1470 -
 13.1471 -        return foundIt;
 13.1472 -    }
 13.1473 -}
    14.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonIndexSearcher.java	Sat Sep 12 23:03:15 2015 -0700
    14.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3 @@ -1,252 +0,0 @@
    14.4 -/*
    14.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    14.6 - *
    14.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    14.8 - *
    14.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   14.10 - * Other names may be trademarks of their respective owners.
   14.11 - *
   14.12 - * The contents of this file are subject to the terms of either the GNU
   14.13 - * General Public License Version 2 only ("GPL") or the Common
   14.14 - * Development and Distribution License("CDDL") (collectively, the
   14.15 - * "License"). You may not use this file except in compliance with the
   14.16 - * License. You can obtain a copy of the License at
   14.17 - * http://www.netbeans.org/cddl-gplv2.html
   14.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   14.19 - * specific language governing permissions and limitations under the
   14.20 - * License.  When distributing the software, include this License Header
   14.21 - * Notice in each file and include the License file at
   14.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   14.23 - * particular file as subject to the "Classpath" exception as provided
   14.24 - * by Oracle in the GPL Version 2 section of the License file that
   14.25 - * accompanied this code. If applicable, add the following below the
   14.26 - * License Header, with the fields enclosed by brackets [] replaced by
   14.27 - * your own identifying information:
   14.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   14.29 - *
   14.30 - * Contributor(s):
   14.31 - *
   14.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   14.33 - */
   14.34 -package org.netbeans.modules.python.editor;
   14.35 -
   14.36 -import java.awt.Toolkit;
   14.37 -import java.util.HashSet;
   14.38 -import java.util.Set;
   14.39 -import java.util.logging.Logger;
   14.40 -import javax.swing.Icon;
   14.41 -import org.netbeans.modules.python.editor.elements.IndexedElement;
   14.42 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   14.43 -import org.netbeans.api.project.FileOwnerQuery;
   14.44 -import org.netbeans.api.project.Project;
   14.45 -import org.netbeans.api.project.ProjectInformation;
   14.46 -import org.netbeans.api.project.ProjectUtils;
   14.47 -import org.netbeans.modules.csl.api.ElementHandle;
   14.48 -import org.netbeans.modules.csl.api.IndexSearcher;
   14.49 -import org.netbeans.modules.csl.api.IndexSearcher.Descriptor;
   14.50 -import org.netbeans.modules.csl.api.IndexSearcher.Helper;
   14.51 -import org.netbeans.modules.csl.spi.GsfUtilities;
   14.52 -import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
   14.53 -import org.openide.filesystems.FileObject;
   14.54 -import org.openide.util.ImageUtilities;
   14.55 -import org.python.antlr.PythonTree;
   14.56 -
   14.57 -/**
   14.58 - *
   14.59 - * @author Tor Norbye
   14.60 - */
   14.61 -public class PythonIndexSearcher implements IndexSearcher {
   14.62 -
   14.63 -    @Override
   14.64 -    public Set<? extends Descriptor> getTypes(Project prjct, String textForQuery, QuerySupport.Kind kind, Helper helper) {
   14.65 -        PythonIndex index = PythonIndex.get(prjct);
   14.66 -        Set<PythonSymbol> result = new HashSet<>();
   14.67 -        Set<? extends IndexedElement> elements;
   14.68 -
   14.69 -        // TODO - do some filtering if you use ./#
   14.70 -        //        int dot = textForQuery.lastIndexOf('.');
   14.71 -        //        if (dot != -1 && (kind == QuerySupport.Kind.PREFIX || kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX)) {
   14.72 -        //            String prefix = textForQuery.substring(dot+1);
   14.73 -        //            String in = textForQuery.substring(0, dot);
   14.74 -
   14.75 -        elements = index.getClasses(textForQuery, kind, null, true);
   14.76 -        for (IndexedElement element : elements) {
   14.77 -            result.add(new PythonSymbol(element, helper));
   14.78 -        }
   14.79 -
   14.80 -        return result;
   14.81 -    }
   14.82 -
   14.83 -    @Override
   14.84 -    public Set<? extends Descriptor> getSymbols(Project prjct, String textForQuery, QuerySupport.Kind kind, Helper helper) {
   14.85 -        PythonIndex index = PythonIndex.get(prjct);
   14.86 -        Set<PythonSymbol> result = new HashSet<>();
   14.87 -        Set<? extends IndexedElement> elements;
   14.88 -
   14.89 -        // TODO - do some filtering if you use ./#
   14.90 -        //        int dot = textForQuery.lastIndexOf('.');
   14.91 -        //        if (dot != -1 && (kind == QuerySupport.Kind.PREFIX || kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX)) {
   14.92 -        //            String prefix = textForQuery.substring(dot+1);
   14.93 -        //            String in = textForQuery.substring(0, dot);
   14.94 -
   14.95 -        elements = index.getAllMembers(textForQuery, kind, null, true);
   14.96 -        for (IndexedElement element : elements) {
   14.97 -            result.add(new PythonSymbol(element, helper));
   14.98 -        }
   14.99 -        elements = index.getClasses(textForQuery, kind, null, true);
  14.100 -        for (IndexedElement element : elements) {
  14.101 -            result.add(new PythonSymbol(element, helper));
  14.102 -        }
  14.103 -        elements = index.getModules(textForQuery, kind);
  14.104 -        for (IndexedElement element : elements) {
  14.105 -            result.add(new PythonSymbol(element, helper));
  14.106 -        }
  14.107 -
  14.108 -        return result;
  14.109 -    }
  14.110 -
  14.111 -    private class PythonSymbol extends Descriptor {
  14.112 -        private final IndexedElement element;
  14.113 -        private String projectName;
  14.114 -        private Icon projectIcon;
  14.115 -        private final Helper helper;
  14.116 -        private boolean isLibrary;
  14.117 -        private static final String ICON_PATH = "org/netbeans/modules/python/editor/resources/pyc_16.png"; //NOI18N
  14.118 -
  14.119 -        public PythonSymbol(IndexedElement element, Helper helper) {
  14.120 -            this.element = element;
  14.121 -            this.helper = helper;
  14.122 -        }
  14.123 -
  14.124 -        @Override
  14.125 -        public Icon getIcon() {
  14.126 -            if (projectName == null) {
  14.127 -                initProjectInfo();
  14.128 -            }
  14.129 -            //if (isLibrary) {
  14.130 -            //    return new ImageIcon(org.openide.util.ImageUtilities.loadImage(PYTHON_KEYWORD));
  14.131 -            //}
  14.132 -            return helper.getIcon(element);
  14.133 -        }
  14.134 -
  14.135 -        @Override
  14.136 -        public String getTypeName() {
  14.137 -            return element.getName();
  14.138 -        }
  14.139 -
  14.140 -        @Override
  14.141 -        public String getProjectName() {
  14.142 -            if (projectName == null) {
  14.143 -                initProjectInfo();
  14.144 -            }
  14.145 -            return projectName;
  14.146 -        }
  14.147 -
  14.148 -        private void initProjectInfo() {
  14.149 -            FileObject fo = element.getFileObject();
  14.150 -            if (fo != null) {
  14.151 -//                File f = FileUtil.toFile(fo);
  14.152 -                Project p = FileOwnerQuery.getOwner(fo);
  14.153 -                if (p != null) {
  14.154 -//                    JsPlatform platform = JsPlatform.platformFor(p);
  14.155 -//                    if (platform != null) {
  14.156 -//                        String lib = platform.getLib();
  14.157 -//                        if (lib != null && f.getPath().startsWith(lib)) {
  14.158 -//                            projectName = "Js Library";
  14.159 -//                            isLibrary = true;
  14.160 -//                        }
  14.161 -//                    } else {
  14.162 -                    ProjectInformation pi = ProjectUtils.getInformation(p);
  14.163 -                    projectName = pi.getDisplayName();
  14.164 -                    projectIcon = pi.getIcon();
  14.165 -//                    }
  14.166 -                }
  14.167 -            } else {
  14.168 -                isLibrary = true;
  14.169 -                Logger.getLogger(PythonIndexSearcher.class.getName()).fine("No fileobject for " + element.toString() + " with fileurl=" + element.getFilenameUrl());
  14.170 -            }
  14.171 -            if (projectName == null) {
  14.172 -                projectName = "";
  14.173 -            }
  14.174 -        }
  14.175 -
  14.176 -        @Override
  14.177 -        public Icon getProjectIcon() {
  14.178 -            if (projectName == null) {
  14.179 -                initProjectInfo();
  14.180 -            }
  14.181 -            if (isLibrary) {
  14.182 -                return ImageUtilities.loadImageIcon(ICON_PATH, false);
  14.183 -            }
  14.184 -            return projectIcon;
  14.185 -        }
  14.186 -
  14.187 -        @Override
  14.188 -        public FileObject getFileObject() {
  14.189 -            return element.getFileObject();
  14.190 -        }
  14.191 -
  14.192 -        @Override
  14.193 -        public void open() {
  14.194 -            PythonParserResult[] parserResultRet = new PythonParserResult[1];
  14.195 -            PythonTree node = PythonAstUtils.getForeignNode(element, parserResultRet);
  14.196 -
  14.197 -            if (node != null) {
  14.198 -                int astOffset = PythonAstUtils.getRange(node).getStart();
  14.199 -                int lexOffset = PythonLexerUtils.getLexerOffset(parserResultRet[0], astOffset);
  14.200 -                if (lexOffset == -1) {
  14.201 -                    lexOffset = 0;
  14.202 -                }
  14.203 -                GsfUtilities.open(element.getFileObject(), lexOffset, element.getName());
  14.204 -                return;
  14.205 -            }
  14.206 -
  14.207 -            FileObject fileObject = element.getFileObject();
  14.208 -            if (fileObject == null) {
  14.209 -                // This should no longer be needed - we perform auto deletion in GSF
  14.210 -                Toolkit.getDefaultToolkit().beep();
  14.211 -                return;
  14.212 -            }
  14.213 -
  14.214 -            helper.open(fileObject, element);
  14.215 -        }
  14.216 -
  14.217 -        @Override
  14.218 -        public String getContextName() {
  14.219 -            // XXX This is lame - move formatting logic to the goto action!
  14.220 -//            StringBuilder sb = new StringBuilder();
  14.221 -//            String require = element.getRequire();
  14.222 -//            String fqn = element.getFqn();
  14.223 -            String fqn = element.getIn() != null ? element.getIn() + "." + element.getName() : element.getName();
  14.224 -            if (element.getName().equals(fqn)) {
  14.225 -                fqn = null;
  14.226 -                String url = element.getFilenameUrl();
  14.227 -                if (url != null) {
  14.228 -                    return url.substring(url.lastIndexOf('/') + 1);
  14.229 -                }
  14.230 -            }
  14.231 -
  14.232 -            return fqn;
  14.233 -        }
  14.234 -
  14.235 -        @Override
  14.236 -        public ElementHandle getElement() {
  14.237 -            return element;
  14.238 -        }
  14.239 -
  14.240 -        @Override
  14.241 -        public int getOffset() {
  14.242 -            throw new UnsupportedOperationException("Not supported yet.");
  14.243 -        }
  14.244 -
  14.245 -        @Override
  14.246 -        public String getSimpleName() {
  14.247 -            return element.getName();
  14.248 -        }
  14.249 -
  14.250 -        @Override
  14.251 -        public String getOuterName() {
  14.252 -            return null;
  14.253 -        }
  14.254 -    }
  14.255 -}
    15.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonIndexer.java	Sat Sep 12 23:03:15 2015 -0700
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,1400 +0,0 @@
    15.4 -/*
    15.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    15.6 - *
    15.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    15.8 - *
    15.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   15.10 - * Other names may be trademarks of their respective owners.
   15.11 - *
   15.12 - * The contents of this file are subject to the terms of either the GNU
   15.13 - * General Public License Version 2 only ("GPL") or the Common
   15.14 - * Development and Distribution License("CDDL") (collectively, the
   15.15 - * "License"). You may not use this file except in compliance with the
   15.16 - * License. You can obtain a copy of the License at
   15.17 - * http://www.netbeans.org/cddl-gplv2.html
   15.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   15.19 - * specific language governing permissions and limitations under the
   15.20 - * License.  When distributing the software, include this License Header
   15.21 - * Notice in each file and include the License file at
   15.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   15.23 - * particular file as subject to the "Classpath" exception as provided
   15.24 - * by Oracle in the GPL Version 2 section of the License file that
   15.25 - * accompanied this code. If applicable, add the following below the
   15.26 - * License Header, with the fields enclosed by brackets [] replaced by
   15.27 - * your own identifying information:
   15.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   15.29 - *
   15.30 - * Contributor(s):
   15.31 - *
   15.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   15.33 - */
   15.34 -package org.netbeans.modules.python.editor;
   15.35 -
   15.36 -import java.io.File;
   15.37 -import java.io.IOException;
   15.38 -import java.net.MalformedURLException;
   15.39 -import java.net.URL;
   15.40 -import java.util.ArrayList;
   15.41 -import java.util.Collections;
   15.42 -import java.util.HashMap;
   15.43 -import java.util.List;
   15.44 -import java.util.Map;
   15.45 -import java.util.logging.Level;
   15.46 -import java.util.logging.Logger;
   15.47 -import java.util.regex.Matcher;
   15.48 -import java.util.regex.Pattern;
   15.49 -import javax.swing.text.BadLocationException;
   15.50 -import org.netbeans.editor.BaseDocument;
   15.51 -import org.netbeans.modules.csl.spi.GsfUtilities;
   15.52 -import org.netbeans.modules.csl.spi.ParserResult;
   15.53 -import org.netbeans.modules.parsing.api.Snapshot;
   15.54 -import org.netbeans.modules.parsing.spi.Parser;
   15.55 -import org.netbeans.modules.parsing.spi.indexing.Context;
   15.56 -import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexer;
   15.57 -import org.netbeans.modules.parsing.spi.indexing.Indexable;
   15.58 -import org.netbeans.modules.parsing.spi.indexing.support.IndexDocument;
   15.59 -import org.netbeans.modules.parsing.spi.indexing.support.IndexingSupport;
   15.60 -import org.netbeans.modules.python.api.PythonPlatform;
   15.61 -import org.netbeans.modules.python.api.PythonPlatformManager;
   15.62 -import org.netbeans.modules.python.editor.elements.IndexedElement;
   15.63 -import org.netbeans.modules.python.editor.hints.Deprecations;
   15.64 -import org.netbeans.modules.python.editor.scopes.ScopeConstants;
   15.65 -import org.netbeans.modules.python.editor.scopes.ScopeInfo;
   15.66 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
   15.67 -import org.netbeans.modules.python.editor.scopes.SymInfo;
   15.68 -import org.openide.filesystems.FileObject;
   15.69 -import org.openide.filesystems.FileStateInvalidException;
   15.70 -import org.openide.filesystems.FileUtil;
   15.71 -import org.openide.filesystems.URLMapper;
   15.72 -import org.openide.util.Exceptions;
   15.73 -import org.python.antlr.PythonTree;
   15.74 -import org.python.antlr.ast.ClassDef;
   15.75 -import org.python.antlr.ast.FunctionDef;
   15.76 -import org.python.antlr.ast.Module;
   15.77 -import org.python.antlr.ast.Name;
   15.78 -import org.python.antlr.base.expr;
   15.79 -
   15.80 -/**
   15.81 - *
   15.82 - * @todo Store information about all symbols exported by a module.
   15.83 - *  I can use that to provide "unused import" help.
   15.84 - * @todo Clean this stuff up: store data, functions, etc.
   15.85 - * @todo Improve detection of builtins. Perhaps run from within Python,
   15.86 - *   something like this:
   15.87 ->>> dir(__builtins__)
   15.88 -['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__', '__name__', 'abs', 'all', 'any', 'apply', 'basestring', 'bool', 'buffer', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter', 'float', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'min', 'object', 'oct', 'open', 'ord', 'pow', 'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
   15.89 - *
   15.90 - * My code for scanning for functions has to be smarter:
   15.91 -.. function:: ljust(s, width)
   15.92 -rjust(s, width)
   15.93 -center(s, width)
   15.94 - * Here I need to pick up all 3 signatures!
   15.95 - * @author Tor Norbye
   15.96 - */
   15.97 -public class PythonIndexer extends EmbeddingIndexer {
   15.98 -    public static final String NAME = "PythonIndexer";
   15.99 -    public static final int VERSION = 1;
  15.100 -    public static boolean PREINDEXING = Boolean.getBoolean("gsf.preindexing"); // NOI18N
  15.101 -    public static final String FIELD_MEMBER = "member"; //NOI18N
  15.102 -    public static final String FIELD_MODULE_NAME = "module"; //NOI18N
  15.103 -    public static final String FIELD_MODULE_ATTR_NAME = "modattrs"; //NOI18N
  15.104 -    public static final String FIELD_CLASS_ATTR_NAME = "clzattrs"; //NOI18N
  15.105 -    public static final String FIELD_EXTENDS_NAME = "extends"; //NOI18N
  15.106 -    public static final String FIELD_ITEM = "item"; //NOI18N
  15.107 -    public static final String FIELD_IN = "in"; //NOI18N
  15.108 -    public static final String FIELD_CLASS_NAME = "class"; //NOI18N
  15.109 -    public static final String FIELD_CASE_INSENSITIVE_CLASS_NAME = "class-ig"; //NOI18N
  15.110 -    private FileObject prevParent;
  15.111 -    private boolean prevResult;
  15.112 -
  15.113 -    public static boolean isIndexable(Indexable indexable, Snapshot snapshot) {
  15.114 -        FileObject fo = snapshot.getSource().getFileObject();
  15.115 -        String extension = fo.getExt();
  15.116 -        if ("py".equals(extension)) { // NOI18N
  15.117 -            return true;
  15.118 -        }
  15.119 -
  15.120 -        if ("rst".equals(extension)) { // NOI18N
  15.121 -            // Index restructured text if it looks like it contains Python library
  15.122 -            // definitions
  15.123 -            return true;
  15.124 -        }
  15.125 -
  15.126 -        if ("egg".equals(extension)) { // NOI18N
  15.127 -            return true;
  15.128 -        }
  15.129 -
  15.130 -        return false;
  15.131 -    }
  15.132 -
  15.133 -    
  15.134 -    public boolean isIndexable(Snapshot file) {
  15.135 -        FileObject fo = file.getSource().getFileObject();
  15.136 -        String extension = fo.getExt();
  15.137 -        if ("py".equals(extension)) { // NOI18N
  15.138 -
  15.139 -            // Skip "test" folders under lib... Lots of weird files there
  15.140 -            // and we don't want to pollute the index with them
  15.141 -            FileObject parent = fo.getParent();
  15.142 -
  15.143 -            if (parent != null && parent.getName().equals("test")) { // NOI18N
  15.144 -                // Make sure it's really a lib folder, we want to include the
  15.145 -                // user's files
  15.146 -
  15.147 -                // Avoid double-indexing files that have multiple versions - e.g. foo.js and foo-min.js
  15.148 -                // or foo.uncompressed
  15.149 -                FileObject parentFo = fo.getParent();
  15.150 -                if (prevParent == parentFo) {
  15.151 -                    return prevResult;
  15.152 -                }
  15.153 -                prevResult = true;
  15.154 -                prevParent = parentFo;
  15.155 -                PythonPlatformManager manager = PythonPlatformManager.getInstance();
  15.156 -                Platforms:
  15.157 -                for (String name : manager.getPlatformList()) {
  15.158 -                    PythonPlatform platform = manager.getPlatform(name);
  15.159 -                    if (platform != null) {
  15.160 -                        for (FileObject root : platform.getLibraryRoots()) {
  15.161 -                            if (FileUtil.isParentOf(root, parentFo)) {
  15.162 -                                prevResult = false;
  15.163 -                                break Platforms;
  15.164 -                            }
  15.165 -                        }
  15.166 -                    }
  15.167 -                }
  15.168 -            }
  15.169 -
  15.170 -            return true;
  15.171 -        }
  15.172 -
  15.173 -        if ("rst".equals(extension)) { // NOI18N
  15.174 -            // Index restructured text if it looks like it contains Python library
  15.175 -            // definitions
  15.176 -            return true;
  15.177 -        }
  15.178 -
  15.179 -        if ("egg".equals(extension)) { // NOI18N
  15.180 -            return true;
  15.181 -        }
  15.182 -
  15.183 -        return false;
  15.184 -    }
  15.185 -
  15.186 -    @Override
  15.187 -    protected void index(Indexable indexable, Parser.Result result, Context context) {
  15.188 -        PythonParserResult parseResult = (PythonParserResult)result;
  15.189 -        if (parseResult == null) {
  15.190 -            return;
  15.191 -        }
  15.192 -        
  15.193 -        IndexingSupport support;
  15.194 -        try {
  15.195 -            support = IndexingSupport.getInstance(context);
  15.196 -        } catch (IOException ioe) {
  15.197 -            LOG.log(Level.WARNING, null, ioe);
  15.198 -            return;
  15.199 -        }
  15.200 -        
  15.201 -        support.removeDocuments(indexable);
  15.202 -        
  15.203 -        FileObject fileObject = result.getSnapshot().getSource().getFileObject();
  15.204 -        String extension = fileObject.getNameExt();
  15.205 -
  15.206 -        if (extension.endsWith(".rst")) { // NOI18N
  15.207 -            scanRst(fileObject, indexable, support, null);
  15.208 -        } else if (extension.endsWith(".egg")) { // NOI18N
  15.209 -            scanEgg(fileObject, indexable, parseResult, support);
  15.210 -        } else {
  15.211 -            // Normal python file
  15.212 -            new IndexTask(parseResult, support).scan();
  15.213 -        }
  15.214 -    }
  15.215 -    private static final Logger LOG = Logger.getLogger(PythonIndexer.class.getName());
  15.216 -
  15.217 -    public boolean acceptQueryPath(String url) {
  15.218 -        return !url.contains("jsstubs"); // NOI18N
  15.219 -    }
  15.220 -
  15.221 -    public String getPersistentUrl(File file) {
  15.222 -        String url;
  15.223 -        try {
  15.224 -            url = file.toURI().toURL().toExternalForm();
  15.225 -
  15.226 -            // Make relative URLs for urls in the libraries
  15.227 -            return PythonIndex.getPreindexUrl(url);
  15.228 -        } catch (MalformedURLException ex) {
  15.229 -            Exceptions.printStackTrace(ex);
  15.230 -            return file.getPath();
  15.231 -        }
  15.232 -    }
  15.233 -
  15.234 -    public String getIndexVersion() {
  15.235 -        return "0.123"; // NOI18N
  15.236 -    }
  15.237 -
  15.238 -    public String getIndexerName() {
  15.239 -        return "python"; // NOI18N
  15.240 -    }
  15.241 -
  15.242 -    public FileObject getPreindexedDb() {
  15.243 -        return null;
  15.244 -    }
  15.245 -
  15.246 -    private static void appendFlags(StringBuilder sb, char c, SymInfo sym, int flags) {
  15.247 -        sb.append(';');
  15.248 -        sb.append(c);
  15.249 -        sb.append(';');
  15.250 -
  15.251 -        if (sym.isPrivate()) {
  15.252 -            flags |= IndexedElement.PRIVATE;
  15.253 -        }
  15.254 -        if (c == 'c') {
  15.255 -            flags |= IndexedElement.CONSTRUCTOR;
  15.256 -        }
  15.257 -
  15.258 -        sb.append(IndexedElement.encode(flags));
  15.259 -        sb.append(';');
  15.260 -    }
  15.261 -    private static final int DEFAULT_DOC_SIZE = 40; // TODO Measure
  15.262 -
  15.263 -    private static class IndexTask {
  15.264 -        private PythonParserResult result;
  15.265 -        private FileObject file;
  15.266 -        private IndexingSupport support;
  15.267 -        private List<IndexDocument> documents = new ArrayList<>();
  15.268 -        private String url;
  15.269 -        private String module;
  15.270 -        private SymbolTable symbolTable;
  15.271 -        private String overrideUrl;
  15.272 -
  15.273 -        private IndexTask(PythonParserResult result, IndexingSupport support) {
  15.274 -            this.result = result;
  15.275 -            this.file = result.getSnapshot().getSource().getFileObject();
  15.276 -            this.support = support;
  15.277 -
  15.278 -            module = PythonUtils.getModuleName(file);
  15.279 -            //PythonTree root = PythonAstUtils.getRoot(result);
  15.280 -            //if (root instanceof Module) {
  15.281 -            //    Str moduleDoc = PythonAstUtils.getDocumentationNode(root);
  15.282 -            //    if (moduleDoc != null) {
  15.283 -            //        moduleAttributes = "d(" + moduleDoc.getCharStartIndex() + ")";
  15.284 -            //    }
  15.285 -            //}
  15.286 -        }
  15.287 -
  15.288 -        private IndexTask(PythonParserResult result, IndexingSupport support, String overrideUrl) {
  15.289 -            this(result, support);
  15.290 -            this.overrideUrl = overrideUrl;
  15.291 -        }
  15.292 -
  15.293 -        public List<IndexDocument> scan() {
  15.294 -            url = file.toURL().toExternalForm();
  15.295 -            // Make relative URLs for urls in the libraries
  15.296 -            url = PythonIndex.getPreindexUrl(url);
  15.297 -
  15.298 -            IndexDocument doc = createDocument();
  15.299 -            doc.addPair(FIELD_MODULE_NAME, module, true, true);
  15.300 -
  15.301 -            String moduleAttrs = null;
  15.302 -            if (url.startsWith(PythonIndex.CLUSTER_URL) || url.startsWith(PythonIndex.PYTHONHOME_URL)) {
  15.303 -                moduleAttrs = "S"; // NOI18N
  15.304 -            } else if (PREINDEXING) {
  15.305 -                String prj = System.getProperty("gsf.preindexing.projectpath");
  15.306 -                if (prj != null && !url.contains(prj)) {
  15.307 -                    System.err.println("WARNING -- not marking url " + url + " from " + file + " as a system library!");
  15.308 -                }
  15.309 -            }
  15.310 -            if (Deprecations.isDeprecatedModule(module)) {
  15.311 -                if (moduleAttrs == null) {
  15.312 -                    moduleAttrs = "D"; // NOI18N
  15.313 -                } else {
  15.314 -                    moduleAttrs += "D"; // NOI18N
  15.315 -                }
  15.316 -            }
  15.317 -            if (moduleAttrs != null) {
  15.318 -                doc.addPair(FIELD_MODULE_ATTR_NAME, moduleAttrs, false, true);
  15.319 -            }
  15.320 -
  15.321 -            PythonTree root = PythonAstUtils.getRoot(result);
  15.322 -            if (root == null) {
  15.323 -                return documents;
  15.324 -            }
  15.325 -            if (!(root instanceof Module)) {
  15.326 -                // Unexpected... http://netbeans.org/bugzilla/show_bug.cgi?id=165756
  15.327 -                // Maybe some kind of top level error node?
  15.328 -                System.err.println("WARNING - top level AST node type was " + root + " of type " + root.getClass().getName());
  15.329 -                return documents;
  15.330 -            }
  15.331 -            symbolTable = result.getSymbolTable();
  15.332 -            ScopeInfo scopeInfo = symbolTable.getScopeInfo(root);
  15.333 -            for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
  15.334 -                String name = entry.getKey();
  15.335 -                SymInfo sym = entry.getValue();
  15.336 -
  15.337 -                if (sym.isClass()) {
  15.338 -                    StringBuilder sig = new StringBuilder();
  15.339 -                    sig.append(name);
  15.340 -                    appendFlags(sig, 'C', sym, 0);
  15.341 -                    doc.addPair(FIELD_ITEM, sig.toString(), true, true);
  15.342 -
  15.343 -                    if (sym.node instanceof ClassDef) {
  15.344 -                        assert sym.node instanceof ClassDef : sym.node;
  15.345 -                        indexClass(name, sym, (ClassDef)sym.node);
  15.346 -                    } else {
  15.347 -                        // Could be a symbol defined both as a class and a function
  15.348 -                        // (conditionally) such as _Environ in minicompat.py,
  15.349 -                        // and another trigger in socket.py.
  15.350 -                    }
  15.351 -                } else if (sym.isFunction()) {
  15.352 -                    if (sym.node instanceof Name) {
  15.353 -                        assert false : "Unexpected non-function node, " + ((Name)sym.node).getInternalId() + " - from symbol " + name + " in " + file + " with sym=" + sym;
  15.354 -                    }
  15.355 -                    assert sym.node instanceof FunctionDef : sym.node;
  15.356 -                    FunctionDef def = (FunctionDef)sym.node;
  15.357 -                    String sig = computeFunctionSig(name, def, sym);
  15.358 -                    doc.addPair(FIELD_ITEM, sig, true, true);
  15.359 -                } else if (sym.isImported()) {
  15.360 -                    if (!"*".equals(name)) { // NOI18N
  15.361 -                        StringBuilder sig = new StringBuilder();
  15.362 -                        sig.append(name);
  15.363 -                        appendFlags(sig, 'I', sym, 0);
  15.364 -                        doc.addPair(FIELD_ITEM, sig.toString(), true, true);
  15.365 -                    }
  15.366 -                } else if (sym.isGeneratorExp()) {
  15.367 -                    StringBuilder sig = new StringBuilder();
  15.368 -                    sig.append(name);
  15.369 -                    appendFlags(sig, 'G', sym, 0);
  15.370 -                    doc.addPair(FIELD_ITEM, sig.toString(), true, true);
  15.371 -                } else if (sym.isData()) {
  15.372 -                    StringBuilder sig = new StringBuilder();
  15.373 -                    sig.append(name);
  15.374 -                    appendFlags(sig, 'D', sym, 0);
  15.375 -                    doc.addPair(FIELD_ITEM, sig.toString(), true, true);
  15.376 -                } else {
  15.377 -                    // XXX what the heck is this??
  15.378 -                }
  15.379 -            }
  15.380 -
  15.381 -            return documents;
  15.382 -        }
  15.383 -
  15.384 -        private void indexClass(String className, SymInfo classSym, ClassDef clz) {
  15.385 -            IndexDocument classDocument = createDocument();
  15.386 -            classDocument.addPair(FIELD_IN, module, true, true);
  15.387 -
  15.388 -            // Superclass
  15.389 -            List<expr> bases = clz.getInternalBases();
  15.390 -            if (bases != null) {
  15.391 -                for (expr base : bases) {
  15.392 -                    String extendsName = PythonAstUtils.getExprName(base);
  15.393 -                    if (extendsName != null) {
  15.394 -                        classDocument.addPair(FIELD_EXTENDS_NAME, extendsName, true, true);
  15.395 -                    }
  15.396 -                }
  15.397 -            }
  15.398 -
  15.399 -            classDocument.addPair(FIELD_CLASS_NAME, className, true, true);
  15.400 -
  15.401 -            if (classSym.isPrivate()) {
  15.402 -                // TODO - store Documented, Deprecated, DocOnly, etc.
  15.403 -                classDocument.addPair(FIELD_CLASS_ATTR_NAME, IndexedElement.encode(IndexedElement.PRIVATE), false, true);
  15.404 -            }
  15.405 -            classDocument.addPair(FIELD_CASE_INSENSITIVE_CLASS_NAME, className.toLowerCase(), true, true);
  15.406 -
  15.407 -            //Str doc = PythonAstUtils.getDocumentationNode(clz);
  15.408 -            //if (doc != null) {
  15.409 -            //    StringBuilder sb = new StringBuilder();
  15.410 -            //    sb.append("d("); // NOI18N
  15.411 -            //    sb.append(doc.getCharStartIndex());
  15.412 -            //    sb.append(")"); // NOI18N
  15.413 -            //    classDocument.addPair(FIELD_CLASS_ATTRS, sb.toString(), false);
  15.414 -            //}
  15.415 -
  15.416 -            ScopeInfo scopeInfo = symbolTable.getScopeInfo(clz);
  15.417 -            for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
  15.418 -                String name = entry.getKey();
  15.419 -                SymInfo sym = entry.getValue();
  15.420 -
  15.421 -//                int flags = sym.flags;
  15.422 -//                assert !sym.isClass() : "found a class " + name + " of type " + sym.dumpFlags(scopeInfo) + " within class " + className + " in module " + module;
  15.423 -//                if (!(sym.isFunction() || sym.isMember() || sym.isData())) {
  15.424 -//                }
  15.425 -//                assert sym.isFunction() || sym.isMember() || sym.isData() : name + ";" + sym.toString();
  15.426 -
  15.427 -                if (sym.isClass()) {
  15.428 -                    // Triggers in httplib _socket_close inside FakeSocket
  15.429 -                    StringBuilder sig = new StringBuilder();
  15.430 -                    sig.append(name);
  15.431 -                    appendFlags(sig, 'C', sym, 0);
  15.432 -                    classDocument.addPair(FIELD_ITEM, sig.toString(), true, true);
  15.433 -
  15.434 -                } else if (sym.isFunction() && sym.node instanceof FunctionDef) {
  15.435 -                    if (sym.node instanceof Name) {
  15.436 -                        assert false : "Unexpected non-function node, " + ((Name)sym.node).getInternalId() + " - from symbol " + name + " in " + file + " with sym=" + sym;
  15.437 -                    }
  15.438 -                    FunctionDef def = (FunctionDef)sym.node;
  15.439 -                    String sig = computeFunctionSig(name, def, sym);
  15.440 -                    classDocument.addPair(FIELD_MEMBER, sig, true, true);
  15.441 -                } else if (sym.isData()) {
  15.442 -                    StringBuilder sig = new StringBuilder();
  15.443 -                    sig.append(name);
  15.444 -                    appendFlags(sig, 'D', sym, 0);
  15.445 -                    classDocument.addPair(FIELD_MEMBER, sig.toString(), true, true);
  15.446 -                } else if (sym.isMember()) {
  15.447 -                    StringBuilder sig = new StringBuilder();
  15.448 -                    sig.append(name);
  15.449 -                    appendFlags(sig, 'A', sym, 0);
  15.450 -                    classDocument.addPair(FIELD_MEMBER, sig.toString(), true, true);
  15.451 -                } else if (!sym.isBound()) {
  15.452 -                    continue;
  15.453 -                } else {
  15.454 -                    // XXX what the heck is this??
  15.455 -                    assert false : className + "::" + name + " : " + sym.dumpFlags(scopeInfo);
  15.456 -                }
  15.457 -            }
  15.458 -
  15.459 -            if (scopeInfo.attributes.size() > 0) {
  15.460 -                for (Map.Entry<String, SymInfo> entry : scopeInfo.attributes.entrySet()) {
  15.461 -                    String name = entry.getKey();
  15.462 -                    SymInfo sym = entry.getValue();
  15.463 -
  15.464 -                    if (sym.isClass()) {
  15.465 -                        // Triggers in httplib _socket_close inside FakeSocket
  15.466 -                        StringBuilder sig = new StringBuilder();
  15.467 -                        sig.append(name);
  15.468 -                        appendFlags(sig, 'C', sym, 0);
  15.469 -                        classDocument.addPair(FIELD_ITEM, sig.toString(), true, true);
  15.470 -
  15.471 -                    } else if (sym.isFunction() && sym.node instanceof FunctionDef) {
  15.472 -                        if (sym.node instanceof Name) {
  15.473 -                            assert false : "Unexpected non-function node, " + ((Name)sym.node).getInternalId() + " - from symbol " + name + " in " + file + " with sym=" + sym;
  15.474 -                        }
  15.475 -                        FunctionDef def = (FunctionDef)sym.node;
  15.476 -                        String sig = computeFunctionSig(name, def, sym);
  15.477 -                        classDocument.addPair(FIELD_MEMBER, sig, true, true);
  15.478 -                    } else if (sym.isData()) {
  15.479 -                        StringBuilder sig = new StringBuilder();
  15.480 -                        sig.append(name);
  15.481 -                        appendFlags(sig, 'D', sym, 0);
  15.482 -                        classDocument.addPair(FIELD_MEMBER, sig.toString(), true, true);
  15.483 -                    } else if (sym.isMember()) {
  15.484 -                        StringBuilder sig = new StringBuilder();
  15.485 -                        sig.append(name);
  15.486 -                        appendFlags(sig, 'A', sym, 0);
  15.487 -                        classDocument.addPair(FIELD_MEMBER, sig.toString(), true, true);
  15.488 -                    } else if (!sym.isBound()) {
  15.489 -                        continue;
  15.490 -                    } else {
  15.491 -                        // XXX what the heck is this??
  15.492 -                        assert false : className + "::" + name + " : " + sym.dumpFlags(scopeInfo);
  15.493 -                    }
  15.494 -                }
  15.495 -            }
  15.496 -        }
  15.497 -
  15.498 -
  15.499 -// TODO - what about nested functions?
  15.500 -        private IndexDocument createDocument() {
  15.501 -            IndexDocument doc = support.createDocument(file);
  15.502 -            documents.add(doc);
  15.503 -
  15.504 -            return doc;
  15.505 -        }
  15.506 -    }
  15.507 -
  15.508 -    public static String computeClassSig(ClassDef def, SymInfo sym) {
  15.509 -        StringBuilder sig = new StringBuilder();
  15.510 -        sig.append(def.getInternalName());
  15.511 -        appendFlags(sig, 'C', sym, 0);
  15.512 -
  15.513 -        return sig.toString();
  15.514 -    }
  15.515 -
  15.516 -    public static String computeFunctionSig(String name, FunctionDef def, SymInfo sym) {
  15.517 -        StringBuilder sb = new StringBuilder();
  15.518 -        sb.append(name);
  15.519 -        char type;
  15.520 -        int flags = 0;
  15.521 -        if ("__init__".equals(name)) { // NOI18N
  15.522 -            type = 'c';
  15.523 -        } else {
  15.524 -            type = 'F';
  15.525 -
  15.526 -            List<expr> decorators = def.getInternalDecorator_list();
  15.527 -            if (decorators != null && decorators.size() > 0) {
  15.528 -                for (expr decorator : decorators) {
  15.529 -                    String decoratorName = PythonAstUtils.getExprName(decorator);
  15.530 -                    if ("property".equals(decoratorName)) { // NOI18N
  15.531 -                        type = 'A';
  15.532 -                    } else if ("classmethod".equals(decoratorName)) { // NOI18N
  15.533 -                        // Classmethods seem to be used mostly for constructors/inherited factories
  15.534 -                        type = 'c';
  15.535 -                        flags |= IndexedElement.CONSTRUCTOR | IndexedElement.STATIC;
  15.536 -                    } else if ("staticmethod".equals(decoratorName)) { // NOI18N
  15.537 -                        flags |= IndexedElement.STATIC;
  15.538 -                    }
  15.539 -                }
  15.540 -            }
  15.541 -        }
  15.542 -        appendFlags(sb, type, sym, flags);
  15.543 -
  15.544 -        List<String> params = PythonAstUtils.getParameters(def);
  15.545 -        boolean first = true;
  15.546 -        for (String param : params) {
  15.547 -            if (first) {
  15.548 -                first = false;
  15.549 -            } else {
  15.550 -                sb.append(',');
  15.551 -            }
  15.552 -            sb.append(param);
  15.553 -        }
  15.554 -        sb.append(';');
  15.555 -        String sig = sb.toString();
  15.556 -        return sig;
  15.557 -    }
  15.558 -
  15.559 -    private String cleanupSignature(String signature) {
  15.560 -        // Clean up signatures - remove [optional] areas, deal
  15.561 -        //   with arg=Default.Value parameters,
  15.562 -        //   or "literal" or (lit,er,al) default values.
  15.563 -        // See unit tests for details.
  15.564 -        boolean lastWasComma = false;
  15.565 -        StringBuilder sb = new StringBuilder();
  15.566 -        Loop:
  15.567 -        for (int i = 0, n = signature.length(); i < n; i++) {
  15.568 -            char c = signature.charAt(i);
  15.569 -            switch (c) {
  15.570 -            case ' ':
  15.571 -            case '[':
  15.572 -            case ']':
  15.573 -            case '\'':
  15.574 -            case '"':
  15.575 -            case '.':
  15.576 -                continue Loop;
  15.577 -            case '=': {
  15.578 -                int level = 0;
  15.579 -                for (i++; i < n; i++) {
  15.580 -                    c = signature.charAt(i);
  15.581 -                    if (c == '(') {
  15.582 -                        level++;
  15.583 -                    } else if (c == ')') {
  15.584 -                        if (level == 0) {
  15.585 -                            break;
  15.586 -                        }
  15.587 -                        level--;
  15.588 -                    }
  15.589 -                    if (c == ',' && level == 0) {
  15.590 -                        break;
  15.591 -                    }
  15.592 -                }
  15.593 -                i--; // compensate for loop-increment
  15.594 -                continue Loop;
  15.595 -            }
  15.596 -            case ')':
  15.597 -                if (lastWasComma) {
  15.598 -                    sb.setLength(sb.length() - 1);
  15.599 -                    lastWasComma = false;
  15.600 -                }
  15.601 -                break;
  15.602 -            case ',':
  15.603 -                if (lastWasComma) {
  15.604 -                    continue Loop;
  15.605 -                }
  15.606 -                lastWasComma = true;
  15.607 -                break;
  15.608 -            default:
  15.609 -                lastWasComma = false;
  15.610 -            }
  15.611 -            sb.append(c);
  15.612 -        }
  15.613 -
  15.614 -        return sb.toString();
  15.615 -    }
  15.616 -
  15.617 -    /**
  15.618 -     * Determine if the definition beginning on lines[lineno] is deprecated.
  15.619 -     */
  15.620 -    private boolean isDeprecated(String[] lines, int lineno) {
  15.621 -        int firstIndent = RstFormatter.getIndentation(lines[lineno], 0);
  15.622 -        for (int i = lineno + 1; i < lines.length; i++) {
  15.623 -            String line = lines[i];
  15.624 -            int indent = RstFormatter.getIndentation(line, 0);
  15.625 -            if (indent == -1) { // empty line
  15.626 -                continue;
  15.627 -            }
  15.628 -            if (line.contains(":deprecated:") || line.contains(".. deprecated::")) { // NOI18N
  15.629 -                return true;
  15.630 -            }
  15.631 -            // Note - we checked for ::deprecated BEFORE bailing on the next
  15.632 -            // same-indent line, because in some cases, these appear on the same
  15.633 -            // level as the deprecated element (for exampe, modules)
  15.634 -            if (indent <= firstIndent) {
  15.635 -                return false;
  15.636 -            }
  15.637 -
  15.638 -            // For classes we can have embedded definitions of functions/data/methods --
  15.639 -            // a deprecated note for these should not be considered a deprecation of
  15.640 -            // the whole class! See the unit test for bz2.zip for example.
  15.641 -            if (line.startsWith(".. attribute::", indent) || // NOI18N
  15.642 -                    line.startsWith(".. data::", indent) || // NOI18N
  15.643 -                    line.startsWith(".. function::", indent) || // NOI18N
  15.644 -                    line.startsWith(".. method::", indent)) { // NOI18N
  15.645 -                return false;
  15.646 -            }
  15.647 -        }
  15.648 -
  15.649 -        return false;
  15.650 -    }
  15.651 -
  15.652 -    private static class CachedIndexDocument {
  15.653 -        private List<CachedIndexDocumentEntry> entries = new ArrayList<>(DEFAULT_DOC_SIZE);
  15.654 -
  15.655 -        private void addPair(String key, String value, boolean index) {
  15.656 -            entries.add(new CachedIndexDocumentEntry(key, value, index));
  15.657 -        }
  15.658 -    }
  15.659 -
  15.660 -    private static class CachedIndexDocumentEntry {
  15.661 -        private String key;
  15.662 -        private String value;
  15.663 -        private boolean index;
  15.664 -
  15.665 -        public CachedIndexDocumentEntry(String key, String value, boolean index) {
  15.666 -            this.key = key;
  15.667 -            this.value = value;
  15.668 -            this.index = index;
  15.669 -        }
  15.670 -    }
  15.671 -
  15.672 -    private List<IndexDocument> scanRst(FileObject fo, Indexable indexable, IndexingSupport support, String overrideUrl) {
  15.673 -        List<CachedIndexDocument> documents = new ArrayList<>();
  15.674 -
  15.675 -        List<IndexDocument> docs = new ArrayList<>();
  15.676 -        
  15.677 -        if (fo != null) {
  15.678 -            String module = fo.getNameExt();
  15.679 -            assert module.endsWith(".rst"); // NOI18N
  15.680 -            module = module.substring(0, module.length() - 4);
  15.681 -
  15.682 -            // Skip files that are already in the standard Python libraries (as .py files).
  15.683 -            // For these, normal scanning applies
  15.684 -            // (I should consider checking that they are consistent with the official
  15.685 -            // documentation, at least during preindexing)
  15.686 -            if (PREINDEXING) {
  15.687 -                // XXX This doesn't work right for anything but the builtin Jython interpreter....
  15.688 -                // OTOH that's the only thing we're preindexing at this point
  15.689 -                FileObject lib = getLibDir();
  15.690 -                if (lib != null) {
  15.691 -                    String path = module.replace('.', '/');
  15.692 -                    FileObject py = lib.getFileObject(path); // Look for package dir
  15.693 -                    if (py == null) {
  15.694 -                        py = lib.getFileObject(path + ".py"); // NOI18N
  15.695 -                    }
  15.696 -                    if (py != null) {
  15.697 -                        System.err.println("DELETE " + FileUtil.getFileDisplayName(fo) + " because there is a corresponding " + FileUtil.getFileDisplayName(py)); // NOI18N
  15.698 -                        // No - it's in a zip archive now
  15.699 -                        //try {
  15.700 -                        //    // Delete it!
  15.701 -                        //    fo.delete();
  15.702 -                        //} catch (IOException ex) {
  15.703 -                        //    Exceptions.printStackTrace(ex);
  15.704 -                        //}
  15.705 -                        return Collections.emptyList();
  15.706 -                    }
  15.707 -                }
  15.708 -            }
  15.709 -
  15.710 -            String name = fo.getName();
  15.711 -
  15.712 -            // Skip some really obsolete libraries -- IRIX only etc
  15.713 -            if (name.equals("gl") || name.equals("cd") || // NOI18N
  15.714 -                    name.equals("al") || name.equals("fm") ||
  15.715 -                    name.equals("fl") || name.equals("imgfile") || // NOI18N
  15.716 -                    name.equals("jpeg") || // NOI18N
  15.717 -                    name.equals("sunau") || name.equals("sunaudio")) { // NOI!8N
  15.718 -                return Collections.emptyList();
  15.719 -            }
  15.720 -
  15.721 -            Pattern PATTERN = Pattern.compile("\\s*\\.\\.\\s+(.*)::\\s*(.+)\\s*"); // NOI18N
  15.722 -
  15.723 -            BaseDocument doc = GsfUtilities.getDocument(fo, true);
  15.724 -            if (doc != null) {
  15.725 -                Map<String, CachedIndexDocument> classDocs = new HashMap<>();
  15.726 -                CachedIndexDocument document = null;
  15.727 -                try {
  15.728 -                    String text = doc.getText(0, doc.getLength());
  15.729 -                    String[] lines = text.split("\n");
  15.730 -                    String currentClass = null;
  15.731 -
  15.732 -                    for (int lineno = 0, maxLines = lines.length; lineno < maxLines; lineno++) {
  15.733 -                        String line = lines[lineno];
  15.734 -                        if (!line.startsWith(".. ") && !line.contains(" .. ")) { // NOI18N
  15.735 -                            continue;
  15.736 -                        }
  15.737 -
  15.738 -                        Matcher m = PATTERN.matcher(line);
  15.739 -                        if (m.matches()) {
  15.740 -                            String key = m.group(1);
  15.741 -
  15.742 -                            if (key.equals("attribute") || // NOI18N
  15.743 -                                    key.equals("currentmodule") || // NOI18N
  15.744 -                                    key.equals("class") || // NOI18N
  15.745 -                                    key.equals("exception") || // NOI18N
  15.746 -                                    key.equals("function") || // NOI18N
  15.747 -                                    key.equals("method") || // NOI18N
  15.748 -                                    key.equals("data") || // NOI18N
  15.749 -                                    key.equals("module")) {  // NOI18N
  15.750 -
  15.751 -
  15.752 -                                if (key.equals("module") || key.equals("currentmodule")) {  // NOI18N
  15.753 -                                    // TODO - determine package name
  15.754 -                                    module = m.group(2);
  15.755 -                                    document = new CachedIndexDocument();
  15.756 -                                    documents.add(document);
  15.757 -                                    document.addPair(FIELD_MODULE_NAME, module, true);
  15.758 -                                    String moduleAttrs = "S";
  15.759 -                                    if (isDeprecated(lines, lineno)) {
  15.760 -                                        moduleAttrs = "SD";
  15.761 -                                    }
  15.762 -                                    document.addPair(FIELD_MODULE_ATTR_NAME, moduleAttrs, false); // NOI18N
  15.763 -                                } else {
  15.764 -                                    // Methods described in an rst without an actual module definition...
  15.765 -                                    if (document == null) {
  15.766 -                                        document = new CachedIndexDocument();
  15.767 -                                        documents.add(document);
  15.768 -                                        document.addPair(FIELD_MODULE_NAME, module, true);
  15.769 -                                        document.addPair(FIELD_MODULE_ATTR_NAME, "S", false); // NOI18N
  15.770 -                                    }
  15.771 -                                    if (key.equals("method") || key.equals("attribute")) { // NOI18N) { // NOI18N
  15.772 -                                        String signature = m.group(2);
  15.773 -
  15.774 -                                        if ("string.template".equals(signature)) { // NOI18N
  15.775 -                                            // Wrong - ignore this one (ends up on the String class)
  15.776 -                                            continue;
  15.777 -                                        }
  15.778 -                                        if (signature.startsWith("somenamedtuple.")) {
  15.779 -                                            // Ditto
  15.780 -                                            continue;
  15.781 -                                        }
  15.782 -                                        // Error in mailbox.rst - Python 2.6
  15.783 -                                        if (".et_folder(folder)".equals(signature)) {
  15.784 -                                            signature = "get_folder(folder)";
  15.785 -                                        }
  15.786 -
  15.787 -                                        int dot = signature.indexOf('.');
  15.788 -                                        if (dot != -1) {
  15.789 -                                            int paren = signature.indexOf('(');
  15.790 -                                            if (paren == -1 || paren > dot) {
  15.791 -                                                assert signature.matches("\\w+\\.\\w+.*") : signature;
  15.792 -                                                String dottedName = signature.substring(0, dot);
  15.793 -                                                CachedIndexDocument dottedDoc = classDocs.get(dottedName);
  15.794 -                                                if (dottedDoc != null) {
  15.795 -                                                    currentClass = dottedName;
  15.796 -                                                } else /*if (currentClass == null)*/ {
  15.797 -                                                    currentClass = dottedName;
  15.798 -                                                    // New class without class:: declaration first.
  15.799 -                                                    CachedIndexDocument classDocument = new CachedIndexDocument();
  15.800 -                                                    documents.add(classDocument);
  15.801 -                                                    classDocs.put(currentClass, classDocument);
  15.802 -                                                    classDocument.addPair(FIELD_IN, module, true);
  15.803 -
  15.804 -                                                    classDocument.addPair(FIELD_CLASS_NAME, currentClass, true);
  15.805 -                                                    classDocument.addPair(FIELD_CASE_INSENSITIVE_CLASS_NAME, currentClass.toLowerCase(), true);
  15.806 -                                                }
  15.807 -                                                signature = signature.substring(dot + 1);
  15.808 -                                            }
  15.809 -                                        }
  15.810 -
  15.811 -
  15.812 -                                        CachedIndexDocument classDocument = classDocs.get(currentClass);
  15.813 -                                        assert classDocs != null;
  15.814 -
  15.815 -                                        if (key.equals("method")) {
  15.816 -                                            signature = cleanupSignature(signature);
  15.817 -                                            if (signature.indexOf('(') == -1) {
  15.818 -                                                signature = signature + "()";
  15.819 -                                            }
  15.820 -
  15.821 -                                            assert signature.indexOf('(') != -1 && signature.indexOf(')') != -1 &&
  15.822 -                                                    signature.indexOf(')') > signature.indexOf('(') : signature;
  15.823 -                                            int lparen = signature.indexOf('(');
  15.824 -                                            int rparen = signature.indexOf(')', lparen + 1);
  15.825 -                                            if (lparen != -1 && rparen != -1) {
  15.826 -                                                String methodName = signature.substring(0, lparen);
  15.827 -                                                String args = signature.substring(lparen + 1, rparen);
  15.828 -                                                char type;
  15.829 -                                                if (methodName.equals("__init__")) { // NOI18N
  15.830 -                                                    type = 'c';
  15.831 -                                                } else {
  15.832 -                                                    type = 'F';
  15.833 -                                                }
  15.834 -                                                StringBuilder sig = new StringBuilder();
  15.835 -                                                sig.append(methodName);
  15.836 -
  15.837 -                                                int symFlags = 0;
  15.838 -                                                if (SymInfo.isPrivateName(methodName)) {
  15.839 -                                                    symFlags |= ScopeConstants.PRIVATE;
  15.840 -                                                }
  15.841 -                                                // TODO - look up deprecated etc.
  15.842 -                                                SymInfo fakeSym = new SymInfo(symFlags);
  15.843 -
  15.844 -                                                int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
  15.845 -                                                if (isDeprecated(lines, lineno)) {
  15.846 -                                                    flags |= IndexedElement.DEPRECATED;
  15.847 -                                                }
  15.848 -
  15.849 -                                                appendFlags(sig, type, fakeSym, flags);
  15.850 -                                                sig.append(args);
  15.851 -                                                sig.append(';');
  15.852 -
  15.853 -                                                classDocument.addPair(FIELD_MEMBER, sig.toString(), true);
  15.854 -                                            }
  15.855 -                                        } else {
  15.856 -                                            assert key.equals("attribute");
  15.857 -
  15.858 -                                            StringBuilder sig = new StringBuilder();
  15.859 -                                            sig.append(signature);
  15.860 -                                            int symFlags = 0;
  15.861 -                                            if (SymInfo.isPrivateName(signature)) {
  15.862 -                                                symFlags |= ScopeConstants.PRIVATE;
  15.863 -                                            }
  15.864 -                                            // TODO - look up deprecated etc.
  15.865 -                                            SymInfo fakeSym = new SymInfo(symFlags);
  15.866 -
  15.867 -                                            int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
  15.868 -                                            if (isDeprecated(lines, lineno)) {
  15.869 -                                                flags |= IndexedElement.DEPRECATED;
  15.870 -                                            }
  15.871 -
  15.872 -
  15.873 -                                            appendFlags(sig, 'A', fakeSym, flags);
  15.874 -                                            classDocument.addPair(FIELD_MEMBER, sig.toString(), true);
  15.875 -                                        }
  15.876 -                                    } else if (key.equals("class") || key.equals("exception")) { // NOI18N
  15.877 -                                        assert module != null;
  15.878 -                                        String cls = m.group(2);
  15.879 -
  15.880 -                                        int paren = cls.indexOf('(');
  15.881 -                                        String constructor = null;
  15.882 -                                        if (paren != -1) {
  15.883 -                                            // Some documents specify a constructor here
  15.884 -                                            constructor = cleanupSignature(cls);
  15.885 -                                            cls = cls.substring(0, paren);
  15.886 -                                        }
  15.887 -                                        currentClass = cls;
  15.888 -
  15.889 -                                        CachedIndexDocument classDocument = new CachedIndexDocument();
  15.890 -                                        classDocs.put(currentClass, classDocument);
  15.891 -                                        documents.add(classDocument);
  15.892 -                                        classDocument.addPair(FIELD_IN, module, true);
  15.893 -
  15.894 -                                        if (key.equals("exception") && !"Exception".equals(cls)) { // NOI18N
  15.895 -                                            classDocument.addPair(FIELD_EXTENDS_NAME, "Exception", true); // NOI18N
  15.896 -                                        }
  15.897 -
  15.898 -                                        classDocument.addPair(FIELD_CLASS_NAME, cls, true);
  15.899 -                                        int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY | IndexedElement.CONSTRUCTOR;
  15.900 -                                        if (isDeprecated(lines, lineno)) {
  15.901 -                                            flags |= IndexedElement.DEPRECATED;
  15.902 -                                        }
  15.903 -                                        if (flags != 0) {
  15.904 -                                            // TODO - store Documented, Deprecated, DocOnly, etc.
  15.905 -                                            classDocument.addPair(FIELD_CLASS_ATTR_NAME, IndexedElement.encode(flags), false);
  15.906 -                                        }
  15.907 -                                        classDocument.addPair(FIELD_CASE_INSENSITIVE_CLASS_NAME, cls.toLowerCase(), true);
  15.908 -
  15.909 -                                        // TODO - determine extends
  15.910 -                                        //document.addPair(FIELD_EXTENDS_NAME, superClass, true);
  15.911 -
  15.912 -                                        if (constructor != null) {
  15.913 -                                            assert constructor.indexOf('(') != -1 && constructor.indexOf(')') != -1 &&
  15.914 -                                                    constructor.indexOf(')') > constructor.indexOf('(') : constructor;
  15.915 -
  15.916 -                                            String signature = constructor;
  15.917 -                                            int lparen = signature.indexOf('(');
  15.918 -                                            int rparen = signature.indexOf(')', lparen + 1);
  15.919 -                                            if (lparen != -1 && rparen != -1) {
  15.920 -                                                //String methodName = signature.substring(0, lparen);
  15.921 -                                                String methodName = "__init__"; // The constructor is always __init__ !
  15.922 -                                                String args = signature.substring(lparen + 1, rparen);
  15.923 -                                                StringBuilder sig = new StringBuilder();
  15.924 -                                                sig.append(methodName);
  15.925 -                                                int symFlags = 0;
  15.926 -                                                if (SymInfo.isPrivateName(methodName)) {
  15.927 -                                                    symFlags |= ScopeConstants.PRIVATE;
  15.928 -                                                }
  15.929 -                                                // TODO - look up deprecated etc.
  15.930 -                                                SymInfo fakeSym = new SymInfo(symFlags);
  15.931 -
  15.932 -                                                flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY | IndexedElement.CONSTRUCTOR;
  15.933 -                                                if (isDeprecated(lines, lineno)) {
  15.934 -                                                    flags |= IndexedElement.DEPRECATED;
  15.935 -                                                }
  15.936 -
  15.937 -                                                appendFlags(sig, 'c', fakeSym, flags);
  15.938 -                                                sig.append(args);
  15.939 -                                                sig.append(';');
  15.940 -
  15.941 -                                                classDocument.addPair(FIELD_MEMBER, sig.toString(), true);
  15.942 -                                            }
  15.943 -
  15.944 -                                        }
  15.945 -                                    } else if (key.equals("function") || (key.equals("data") && m.group(2).contains("("))) { // NOI18N
  15.946 -                                        // constants.rst for example registers a data item for "quit" which is really a function
  15.947 -
  15.948 -                                        String signature = m.group(2);
  15.949 -                                        indexRstFunction(signature, lines, lineno, document);
  15.950 -
  15.951 -                                        // See if we have any additional lines with signatures
  15.952 -                                        for (int lookahead = lineno + 1; lookahead < maxLines; lookahead++) {
  15.953 -                                            String l = lines[lookahead];
  15.954 -                                            String trimmed = l.trim();
  15.955 -                                            if (trimmed.length() == 0 || trimmed.startsWith(":")) { // NOI18N
  15.956 -                                                break;
  15.957 -                                            }
  15.958 -                                            lineno++;
  15.959 -
  15.960 -                                            indexRstFunction(trimmed, lines, lookahead, document);
  15.961 -                                        }
  15.962 -
  15.963 -                                    } else if (key.equals("data")) { // NOI18N
  15.964 -                                        String data = m.group(2);
  15.965 -
  15.966 -                                        StringBuilder sig = new StringBuilder();
  15.967 -                                        sig.append(data);
  15.968 -                                        int symFlags = 0;
  15.969 -                                        if (SymInfo.isPrivateName(data)) {
  15.970 -                                            symFlags |= ScopeConstants.PRIVATE;
  15.971 -                                        }
  15.972 -                                        // TODO - look up deprecated etc.
  15.973 -                                        SymInfo fakeSym = new SymInfo(symFlags);
  15.974 -
  15.975 -                                        int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
  15.976 -                                        if (isDeprecated(lines, lineno)) {
  15.977 -                                            flags |= IndexedElement.DEPRECATED;
  15.978 -                                        }
  15.979 -
  15.980 -                                        appendFlags(sig, 'D', fakeSym, flags);
  15.981 -
  15.982 -                                        document.addPair(FIELD_ITEM, sig.toString(), true);
  15.983 -                                    } else {
  15.984 -                                        // TODO Handle deprecated attribute!
  15.985 -
  15.986 -                                        //    currentmodule::
  15.987 -                                        //    deprecated::
  15.988 -                                        //    doctest::
  15.989 -                                        //    envvar::
  15.990 -                                        //    epigraph::
  15.991 -                                        //    highlight::
  15.992 -                                        //    highlightlang::
  15.993 -                                        //    index::
  15.994 -                                        //    literalinclude::
  15.995 -                                        //    moduleauthor::
  15.996 -                                        //    note::
  15.997 -                                        //    opcode::
  15.998 -                                        //    productionlist::
  15.999 -                                        //    rubric::
 15.1000 -                                        //    sectionauthor::
 15.1001 -                                        //    seealso::
 15.1002 -                                        //    testcode::
 15.1003 -                                        //    testsetup::
 15.1004 -                                        //    toctree::
 15.1005 -                                        //    versionadded::
 15.1006 -                                        //    versionchanged::
 15.1007 -                                        //    warning::
 15.1008 -                                    }
 15.1009 -                                }
 15.1010 -                            }
 15.1011 -                        } else if (line.startsWith(".. _bltin-file-objects:") || line.startsWith(".. _string-methods:")) { // NOI18N
 15.1012 -                            if (currentClass != null) {
 15.1013 -                                currentClass = null;
 15.1014 -                            }
 15.1015 -                        }
 15.1016 -                    }
 15.1017 -
 15.1018 -                    for (String clz : classDocs.keySet()) {
 15.1019 -                        StringBuilder sig = new StringBuilder();
 15.1020 -                        sig.append(clz);
 15.1021 -                        int symFlags = 0;
 15.1022 -                        if (SymInfo.isPrivateName(clz)) {
 15.1023 -                            symFlags |= ScopeConstants.PRIVATE;
 15.1024 -                        }
 15.1025 -                        // TODO - look up deprecated etc.
 15.1026 -                        SymInfo fakeSym = new SymInfo(symFlags);
 15.1027 -                        appendFlags(sig, 'C', fakeSym, IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY);
 15.1028 -
 15.1029 -                        document.addPair(FIELD_ITEM, sig.toString(), true);
 15.1030 -                    }
 15.1031 -
 15.1032 -                } catch (BadLocationException ex) {
 15.1033 -                    Exceptions.printStackTrace(ex);
 15.1034 -                }
 15.1035 -
 15.1036 -                // Post processing: Add missing attributes not found in the .rst files
 15.1037 -                // but introspected using dir() in a python console
 15.1038 -                if (document != null) {
 15.1039 -                    if ("operator".equals(module)) { // Fill in missing operators!
 15.1040 -                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1041 -                                new String[] { "__abs__", "__add__", "__and__", "__div__", "__floordiv__", "__index__", "__invert__", "__lshift__", "__mod__", "__mul__", "__neg__", "__or__", "__pos__", "__pow__", "__rshift__", "__sub__", "__truediv__", "__xor__" },
 15.1042 -                                document, classDocs, "int", documents, module, false, true);
 15.1043 -                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1044 -                                new String[] { "__abs__", "__add__", "__and__", "__div__", "__floordiv__", "__index__", "__invert__", "__lshift__", "__mod__", "__mul__", "__neg__", "__or__", "__pos__", "__pow__", "__rshift__", "__sub__", "__truediv__", "__xor__" },
 15.1045 -                                document, classDocs, "long", documents, module, false, true);
 15.1046 -                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1047 -                                new String[] { "__abs__", "__add__", "__div__", "__eq__", "__floordiv__", "__ge__", "__gt__", "__le__", "__lt__", "__mod__", "__mul__", "__ne__", "__neg__", "__pos__", "__pow__", "__sub__", "__truediv__" },
 15.1048 -                                document, classDocs, "float", documents, module, false, true);
 15.1049 -                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1050 -                                new String[] { "__abs__", "__add__", "__div__", "__eq__", "__floordiv__", "__ge__", "__gt__", "__le__", "__lt__", "__mod__", "__mul__", "__ne__", "__neg__", "__pos__", "__pow__", "__sub__", "__truediv__" },
 15.1051 -                                document, classDocs, "complex", documents, module, false, true);
 15.1052 -                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1053 -                                new String[] { "__abs__", "__add__", "__and__", "__div__", "__floordiv__", "__index__", "__invert__", "__lshift__", "__mod__", "__mul__", "__neg__", "__or__", "__pos__", "__pow__", "__rshift__", "__sub__", "__truediv__", "__xor__" },
 15.1054 -                                document, classDocs, "bool", documents, module, false, true);
 15.1055 -
 15.1056 -                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1057 -                                new String[] { "__add__", "__contains__", "__eq__", "__ge__", "__getitem__", "__getslice__", "__gt__", "__le__", "__lt__", "__mod__", "__mul__", "__ne__", "index" },
 15.1058 -                                document, classDocs, "str", documents, module, false, true);
 15.1059 -                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1060 -                                new String[] { "__add__", "__contains__", "__delitem__", "__delslice__", "__eq__", "__ge__", "__getitem__", "__getslice__", "__gt__", "__iadd__", "__imul__", "__le__", "__lt__", "__mul__", "__ne__", "__setitem__", "__setslice__", "index" },
 15.1061 -                                document, classDocs, "list", documents, module, false, true);
 15.1062 -                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1063 -                                new String[] { "__contains__", "__delitem__", "__eq__", "__ge__", "__getitem__", "__gt__", "__le__", "__lt__", "__ne__", "__setitem__" },
 15.1064 -                                document, classDocs, "dict", documents, module, false, true);
 15.1065 -                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1066 -                                new String[] { "__add__", "__contains__", "__eq__", "__ge__", "__getitem__", "__getslice__", "__gt__", "__le__", "__lt__", "__mul__", "__ne__", "index" },
 15.1067 -                                document, classDocs, "tuple", documents, module, false, true);
 15.1068 -                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1069 -                                new String[] { "__add__", "__contains__", "__eq__", "__ge__", "__getitem__", "__getslice__", "__gt__", "__le__", "__lt__", "__mod__", "__mul__", "__ne__", "index" },
 15.1070 -                                document, classDocs, "unicode", documents, module, false, true);
 15.1071 -//                    } else if ("stdtypes".equals(module)) {
 15.1072 -//                        // Found no definitions for these puppies
 15.1073 -//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1074 -//                              new String[] { "__class__", "__cmp__", "__coerce__", "__delattr__", "__divmod__", "__doc__", "__float__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__hex__", "__init__", "__int__", "__long__", "__new__", "__nonzero__", "__oct__", "__radd__", "__rand__", "__rdiv__", "__rdivmod__", "__reduce__", "__reduce_ex__", "__repr__", "__rfloordiv__", "__rlshift__", "__rmod__", "__rmul__", "__ror__", "__rpow__", "__rrshift__", "__rsub__", "__rtruediv__", "__rxor__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "__trunc__", "conjugate", "denominator", "imag", "numerator", "real" },
 15.1075 -//                                document, classDocs, "int", documents, module, true, false);
 15.1076 -//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1077 -//                              new String[] { "__class__", "__cmp__", "__coerce__", "__delattr__", "__divmod__", "__doc__", "__float__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__hex__", "__init__", "__int__", "__long__", "__new__", "__nonzero__", "__oct__", "__radd__", "__rand__", "__rdiv__", "__rdivmod__", "__reduce__", "__reduce_ex__", "__repr__", "__rfloordiv__", "__rlshift__", "__rmod__", "__rmul__", "__ror__", "__rpow__", "__rrshift__", "__rsub__", "__rtruediv__", "__rxor__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "__trunc__", "conjugate", "denominator", "imag", "numerator", "real" },
 15.1078 -//                                document, classDocs, "long", documents, module, true, false);
 15.1079 -//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1080 -//                              new String[] { "__class__", "__coerce__", "__delattr__", "__divmod__", "__doc__", "__float__", "__format__", "__getattribute__", "__getformat__", "__getnewargs__", "__hash__", "__init__", "__int__", "__long__", "__new__", "__nonzero__", "__radd__", "__rdiv__", "__rdivmod__", "__reduce__", "__reduce_ex__", "__repr__", "__rfloordiv__", "__rmod__", "__rmul__", "__rpow__", "__rsub__", "__rtruediv__", "__setattr__", "__setformat__", "__sizeof__", "__str__", "__subclasshook__", "__trunc__", "conjugate", "imag", "is_integer", "real" },
 15.1081 -//                                document, classDocs, "float", documents, module, true, false);
 15.1082 -//
 15.1083 -//
 15.1084 -//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1085 -//                              new String[] { "__class__", "__coerce__", "__delattr__", "__divmod__", "__doc__", "__float__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__init__", "__int__", "__long__", "__new__", "__nonzero__", "__radd__", "__rdiv__", "__rdivmod__", "__reduce__", "__reduce_ex__", "__repr__", "__rfloordiv__", "__rmod__", "__rmul__", "__rpow__", "__rsub__", "__rtruediv__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "conjugate", "imag", "real" },
 15.1086 -//                                document, classDocs, "complex", documents, module, true, false);
 15.1087 -//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1088 -//                              new String[] { "__class__", "__cmp__", "__coerce__", "__delattr__", "__divmod__", "__doc__", "__float__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__hex__", "__init__", "__int__", "__long__", "__new__", "__nonzero__", "__oct__", "__radd__", "__rand__", "__rdiv__", "__rdivmod__", "__reduce__", "__reduce_ex__", "__repr__", "__rfloordiv__", "__rlshift__", "__rmod__", "__rmul__", "__ror__", "__rpow__", "__rrshift__", "__rsub__", "__rtruediv__", "__rxor__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "__trunc__", "conjugate", "denominator", "imag", "numerator", "real" },
 15.1089 -//                                document, classDocs, "bool", documents, module, true, false);
 15.1090 -//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1091 -//                              new String[] { "__class__", "__delattr__", "__doc__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__init__", "__len__", "__new__", "__repr__", "__rmod__", "__rmul__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "_formatter_field_name_split", "_formatter_parser" },
 15.1092 -//                                document, classDocs, "str", documents, module, true, false);
 15.1093 -//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1094 -//                              new String[] { "__class__", "__delattr__", "__doc__", "__format__", "__getattribute__", "__hash__", "__init__", "__iter__", "__len__", "__new__", "__repr__", "__reversed__", "__rmul__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "append", "count", "extend", "insert", "pop", "remove", "reverse", "sort" },
 15.1095 -//                                document, classDocs, "list", documents, module, true, false);
 15.1096 -//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1097 -//                              new String[] { "__class__", "__cmp__", "__delattr__", "__doc__", "__format__", "__getattribute__", "__hash__", "__iter__", "__len__", "__new__", "__repr__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__" },
 15.1098 -//                                document, classDocs, "dict", documents, module, true, false);
 15.1099 -//
 15.1100 -//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1101 -//                              new String[] { "__class__", "__delattr__", "__doc__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__init__", "__iter__", "__len__", "__new__", "__reduce__", "__reduce_ex__", "__repr__", "__rmul__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "count" },
 15.1102 -//                                document, classDocs, "tuple", documents, module, true, false);
 15.1103 -//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
 15.1104 -//                              new String[] { "__class__", "__delattr__", "__doc__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__init__", "__len__", "__new__", "__reduce__", "__reduce_ex__", "__repr__", "__rmod__", "__rmul__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "_formatter_field_name_split", "_formatter_parser", "capitalize", "center", "count", "decode", "encode", "endswith", "expandtabs", "find", "format", "isalnum", "isalpha", "isdecimal", "isdigit", "islower", "isnumeric", "isspace", "istitle", "isupper", "join", "ljust", "lower", "lstrip", "partition", "replace", "rfind", "rindex", "rjust", "rpartition", "rsplit", "rstrip", "split", "splitlines", "startswith", "strip", "swapcase", "title", "translate", "upper", "zfill" },
 15.1105 -//                                document, classDocs, "unicode", documents, module, true, false);
 15.1106 -//
 15.1107 -                    }
 15.1108 -                }
 15.1109 -
 15.1110 -                // And convert to a proper GSF search document. I didn't do this directly
 15.1111 -                // because I want to modify the documents after adding documents and pairs.
 15.1112 -                for (CachedIndexDocument cid : documents) {
 15.1113 -                    List<CachedIndexDocumentEntry> entries = cid.entries;
 15.1114 -                    IndexDocument indexedDoc = support.createDocument(indexable);
 15.1115 -//                    IndexDocument indexedDoc = support.createDocument(entries.size(), overrideUrl);
 15.1116 -                    docs.add(indexedDoc);
 15.1117 -                    for (CachedIndexDocumentEntry entry : entries) {
 15.1118 -                        indexedDoc.addPair(entry.key, entry.value, true, true); // XXX indexable and stored ???
 15.1119 -                    }
 15.1120 -                }
 15.1121 -            }
 15.1122 -        }
 15.1123 -
 15.1124 -        return docs;
 15.1125 -    }
 15.1126 -
 15.1127 -    /** Add the given list of names, found in the given document with a given key, and add it
 15.1128 -     * to the specified class (possibly found in the classDocs list - if not, add one to the
 15.1129 -     * documents list)
 15.1130 -     */
 15.1131 -    private void addMissing(String key, String newKey, String[] names, CachedIndexDocument doc,
 15.1132 -            Map<String, CachedIndexDocument> classDocs, String clz, List<CachedIndexDocument> documents, String module,
 15.1133 -            boolean addUnknown, boolean search) {
 15.1134 -
 15.1135 -        CachedIndexDocument classDocument = classDocs.get(clz);
 15.1136 -        if (classDocument == null) {
 15.1137 -            // New class without class:: declaration first.
 15.1138 -            classDocument = new CachedIndexDocument();
 15.1139 -            documents.add(classDocument);
 15.1140 -            classDocs.put(clz, classDocument);
 15.1141 -            classDocument.addPair(FIELD_IN, module, true);
 15.1142 -
 15.1143 -            classDocument.addPair(FIELD_CLASS_NAME, clz, true);
 15.1144 -            classDocument.addPair(FIELD_CASE_INSENSITIVE_CLASS_NAME, clz.toLowerCase(), true);
 15.1145 -        }
 15.1146 -
 15.1147 -        assert classDocument != doc;
 15.1148 -
 15.1149 -        List<String> namesFound = new ArrayList<>();
 15.1150 -        List<String> namesMissing = new ArrayList<>();
 15.1151 -        boolean noneFound = true;
 15.1152 -
 15.1153 -        // Look for each of the given functions
 15.1154 -        Search:
 15.1155 -        for (String name : names) {
 15.1156 -            boolean found = false;
 15.1157 -            if (search) {
 15.1158 -                int nameLength = name.length();
 15.1159 -
 15.1160 -                // DEBUGGING: Look to make sure I don't already have it in the class doc!
 15.1161 -                for (CachedIndexDocumentEntry entry : classDocument.entries) {
 15.1162 -                    if (newKey.equals(entry.key)) {
 15.1163 -                        if (entry.value.startsWith(name) &&
 15.1164 -                                (entry.value.length() <= nameLength || entry.value.charAt(nameLength) == ';')) {
 15.1165 -                             // Uh oh - what do I do here?
 15.1166 -                            System.err.println("WARNING: I already have a definition for name " + name + " in class " + clz);
 15.1167 -                            continue Search;
 15.1168 -                        }
 15.1169 -                    }
 15.1170 -                }
 15.1171 -
 15.1172 -                for (CachedIndexDocumentEntry entry : doc.entries) {
 15.1173 -                    if (key.equals(entry.key)) {
 15.1174 -                        if (entry.value.startsWith(name) &&
 15.1175 -                                (entry.value.length() <= nameLength || entry.value.charAt(nameLength) == ';')) {
 15.1176 -                            // Found it!
 15.1177 -                            classDocument.addPair(newKey, entry.value, entry.index);
 15.1178 -                            found = true;
 15.1179 -                            namesFound.add(name);
 15.1180 -                            break;
 15.1181 -                        }
 15.1182 -                    }
 15.1183 -                }
 15.1184 -            }
 15.1185 -
 15.1186 -            if (!found) {
 15.1187 -                if (addUnknown) {
 15.1188 -                    // TODO - see if I can find a way to extract the signature too!
 15.1189 -                    String args = "";
 15.1190 -                    String signature = name + "()"; //
 15.1191 -
 15.1192 -                    assert signature.indexOf('(') != -1 && signature.indexOf(')') != -1 &&
 15.1193 -                            signature.indexOf(')') > signature.indexOf('(') : signature;
 15.1194 -                    char type;
 15.1195 -                    if (name.equals("__init__")) { // NOI18N
 15.1196 -                        type = 'c';
 15.1197 -                    } else {
 15.1198 -                        type = 'F';
 15.1199 -                    }
 15.1200 -                    StringBuilder sig = new StringBuilder();
 15.1201 -                    sig.append(name);
 15.1202 -
 15.1203 -                    int symFlags = 0;
 15.1204 -                    if (SymInfo.isPrivateName(name)) {
 15.1205 -                        symFlags |= ScopeConstants.PRIVATE;
 15.1206 -                    }
 15.1207 -                    // TODO - look up deprecated etc.
 15.1208 -                    SymInfo fakeSym = new SymInfo(symFlags);
 15.1209 -
 15.1210 -                    int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
 15.1211 -                    appendFlags(sig, type, fakeSym, flags);
 15.1212 -                    sig.append(args);
 15.1213 -                    sig.append(';');
 15.1214 -
 15.1215 -                    classDocument.addPair(newKey, sig.toString(), true);
 15.1216 -                } else {
 15.1217 -                    namesMissing.add(name);
 15.1218 -                }
 15.1219 -            } else {
 15.1220 -                noneFound = false;
 15.1221 -            }
 15.1222 -        }
 15.1223 -
 15.1224 -        if (PREINDEXING) {
 15.1225 -            if (namesFound.size() > 0) {
 15.1226 -                StringBuilder sb = new StringBuilder();
 15.1227 -                sb.append("FOUND for ");
 15.1228 -                sb.append(clz);
 15.1229 -                sb.append(" in ");
 15.1230 -                sb.append(module);
 15.1231 -                sb.append(": ");
 15.1232 -                appendList(sb, namesFound);
 15.1233 -                System.err.println(sb.toString());
 15.1234 -            }
 15.1235 -
 15.1236 -            if (noneFound && search) {
 15.1237 -                System.err.println("ERROR: NONE of the passed in names for " + clz + " were found!");
 15.1238 -            }
 15.1239 -
 15.1240 -            if (namesMissing.size() > 0) {
 15.1241 -                StringBuilder sb = new StringBuilder();
 15.1242 -                sb.append("WARNING: Missing these names from ");
 15.1243 -                sb.append(module);
 15.1244 -                sb.append(" for use by class ");
 15.1245 -                sb.append(clz);
 15.1246 -                sb.append(" : ");
 15.1247 -                appendList(sb, namesMissing);
 15.1248 -                System.err.println(sb.toString());
 15.1249 -            }
 15.1250 -        }
 15.1251 -    }
 15.1252 -
 15.1253 -    private static void appendList(StringBuilder sb, List<String> list) {
 15.1254 -        sb.append("{ ");
 15.1255 -        boolean first = true;
 15.1256 -        for (String m : list) {
 15.1257 -            if (first) {
 15.1258 -                first = false;
 15.1259 -            } else {
 15.1260 -                sb.append(", ");
 15.1261 -            }
 15.1262 -            sb.append('"');
 15.1263 -            sb.append(m);
 15.1264 -            sb.append('"');
 15.1265 -        }
 15.1266 -        sb.append(" }");
 15.1267 -    }
 15.1268 -
 15.1269 -    private void indexRstFunction(String signature, String[] lines, int lineno, CachedIndexDocument document) {
 15.1270 -        int dot = signature.indexOf('.');
 15.1271 -        if (dot != -1) {
 15.1272 -            int paren = signature.indexOf('(');
 15.1273 -            if (paren == -1 || paren > dot) {
 15.1274 -                assert signature.matches("\\w+\\.\\w+.*") : signature; // NOI18N
 15.1275 -                signature = signature.substring(dot + 1);
 15.1276 -            }
 15.1277 -        }
 15.1278 -        signature = cleanupSignature(signature);
 15.1279 -        if (signature.indexOf('(') == -1) {
 15.1280 -            signature = signature + "()"; // NOI18N
 15.1281 -        } else if (signature.indexOf(')') == -1) {
 15.1282 -            //signature = signature + ")";
 15.1283 -            assert signature.indexOf(')') != -1;
 15.1284 -        }
 15.1285 -        int lparen = signature.indexOf('(');
 15.1286 -        int rparen = signature.indexOf(')', lparen + 1);
 15.1287 -        if (lparen != -1 && rparen != -1) {
 15.1288 -            String methodName = signature.substring(0, lparen);
 15.1289 -            String args = signature.substring(lparen + 1, rparen);
 15.1290 -            StringBuilder sig = new StringBuilder();
 15.1291 -            sig.append(methodName);
 15.1292 -            int symFlags = 0;
 15.1293 -            if (SymInfo.isPrivateName(methodName)) {
 15.1294 -                symFlags |= ScopeConstants.PRIVATE;
 15.1295 -            }
 15.1296 -            // TODO - look up deprecated etc.
 15.1297 -            SymInfo fakeSym = new SymInfo(symFlags);
 15.1298 -            int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
 15.1299 -            if (isDeprecated(lines, lineno)) {
 15.1300 -                flags |= IndexedElement.DEPRECATED;
 15.1301 -            }
 15.1302 -            appendFlags(sig, 'F', fakeSym, flags);
 15.1303 -            sig.append(args);
 15.1304 -            sig.append(';');
 15.1305 -
 15.1306 -            document.addPair(FIELD_ITEM, sig.toString(), true);
 15.1307 -        }
 15.1308 -    }
 15.1309 -
 15.1310 -    private List<IndexDocument> scanEgg(FileObject fo, Indexable indexable, ParserResult result, IndexingSupport support) {
 15.1311 -        List<IndexDocument> documents = new ArrayList<>();
 15.1312 -
 15.1313 -        if (fo == null) {
 15.1314 -            return documents;
 15.1315 -        }
 15.1316 -
 15.1317 -        try {
 15.1318 -            String s = fo.toURL().toExternalForm() + "!"; // NOI18N
 15.1319 -            URL u = new URL("jar:" + s); // NOI18N
 15.1320 -            FileObject root = URLMapper.findFileObject(u);
 15.1321 -            String rootUrl = PythonIndex.getPreindexUrl(u.toExternalForm());
 15.1322 -            indexScriptDocRecursively(support, documents, root, rootUrl);
 15.1323 -        } catch (MalformedURLException ex) {
 15.1324 -            Exceptions.printStackTrace(ex);
 15.1325 -        }
 15.1326 -
 15.1327 -        return documents;
 15.1328 -    }
 15.1329 -
 15.1330 -    /**
 15.1331 -     * Method which recursively indexes directory trees, such as the yui/ folder
 15.1332 -     * for example
 15.1333 -     */
 15.1334 -    private void indexScriptDocRecursively(IndexingSupport support, List<IndexDocument> documents, final FileObject fo, String url) {
 15.1335 -        if (fo.isFolder()) {
 15.1336 -            for (FileObject c : fo.getChildren()) {
 15.1337 -                indexScriptDocRecursively(support, documents, c, url + "/" + c.getNameExt()); // NOI18N
 15.1338 -            }
 15.1339 -            return;
 15.1340 -        }
 15.1341 -
 15.1342 -        String ext = fo.getExt();
 15.1343 -
 15.1344 -//        if ("py".equals(ext)) { // NOI18N
 15.1345 -//            DefaultParseListener listener = new DefaultParseListener();
 15.1346 -//            List<ParserFile> files = Collections.<ParserFile>singletonList(new DefaultParserFile(fo, null, false));
 15.1347 -//            SourceFileReader reader = new SourceFileReader() {
 15.1348 -//                public CharSequence read(ParserFile file) throws IOException {
 15.1349 -//                    BaseDocument doc = GsfUtilities.getDocument(fo, true);
 15.1350 -//                    if (doc != null) {
 15.1351 -//                        try {
 15.1352 -//                            return doc.getText(0, doc.getLength());
 15.1353 -//                        } catch (BadLocationException ex) {
 15.1354 -//                            Exceptions.printStackTrace(ex);
 15.1355 -//                        }
 15.1356 -//                    }
 15.1357 -//
 15.1358 -//                    return "";
 15.1359 -//                }
 15.1360 -//
 15.1361 -//                public int getCaretOffset(ParserFile file) {
 15.1362 -//                    return -1;
 15.1363 -//                }
 15.1364 -//            };
 15.1365 -//            Job job = new Job(files, listener, reader, null);
 15.1366 -//            new PythonParser().parseFiles(job);
 15.1367 -//            ParserResult parserResult = listener.getParserResult();
 15.1368 -//            if (parserResult != null && parserResult.isValid()) {
 15.1369 -//                documents.addAll(new IndexTask((PythonParserResult)parserResult, support, url).scan());
 15.1370 -//            }
 15.1371 -//        } else if ("rst".equals(ext)) { // NOI18N
 15.1372 -//            documents.addAll(scanRst(fo, support, url));
 15.1373 -//        }
 15.1374 -    }
 15.1375 -
 15.1376 -    private FileObject getLibDir() {
 15.1377 -        // TODO - fetch from projects!!!!
 15.1378 -        PythonPlatformManager manager = PythonPlatformManager.getInstance();
 15.1379 -        PythonPlatform platform = manager.getPlatform(manager.getDefaultPlatform());
 15.1380 -        if (platform != null) {
 15.1381 -            String cmd = platform.getInterpreterCommand();
 15.1382 -            File file = new File(cmd);
 15.1383 -            if (file.exists()) {
 15.1384 -                file = file.getAbsoluteFile();
 15.1385 -                File home = file.getParentFile().getParentFile();
 15.1386 -                if (home != null) {
 15.1387 -                    // Look for Lib - Jython style
 15.1388 -                    File lib = new File(home, "Lib"); // NOI18N
 15.1389 -                    boolean exists = lib.exists();
 15.1390 -                    if (!exists) { // Unix style
 15.1391 -                        lib = new File(home, "lib" + File.separator + "python"); // NOI18N
 15.1392 -                        exists = lib.exists();
 15.1393 -                    }
 15.1394 -                    if (exists) {
 15.1395 -                        return FileUtil.toFileObject(lib);
 15.1396 -                    }
 15.1397 -                }
 15.1398 -            }
 15.1399 -        }
 15.1400 -
 15.1401 -        return null;
 15.1402 -    }
 15.1403 -}
    16.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonIndexerFactory.java	Sat Sep 12 23:03:15 2015 -0700
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,47 +0,0 @@
    16.4 -/*
    16.5 - * To change this license header, choose License Headers in Project Properties.
    16.6 - * To change this template file, choose Tools | Templates
    16.7 - * and open the template in the editor.
    16.8 - */
    16.9 -package org.netbeans.modules.python.editor;
   16.10 -
   16.11 -import org.netbeans.modules.parsing.api.Snapshot;
   16.12 -import org.netbeans.modules.parsing.spi.indexing.Context;
   16.13 -import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexer;
   16.14 -import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory;
   16.15 -import org.netbeans.modules.parsing.spi.indexing.Indexable;
   16.16 -
   16.17 -/**
   16.18 - *
   16.19 - * @author Ralph Benjamin Ruijs
   16.20 - */
   16.21 -public class PythonIndexerFactory extends EmbeddingIndexerFactory {    
   16.22 -
   16.23 -    @Override
   16.24 -    public EmbeddingIndexer createIndexer(Indexable indexable, Snapshot snapshot) {
   16.25 -        if(PythonIndexer.isIndexable(indexable, snapshot)) {
   16.26 -            return new PythonIndexer();
   16.27 -        }
   16.28 -        return null;
   16.29 -    }
   16.30 -
   16.31 -    @Override
   16.32 -    public void filesDeleted(Iterable<? extends Indexable> indexables, Context context) {
   16.33 -//        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   16.34 -    }
   16.35 -
   16.36 -    @Override
   16.37 -    public void filesDirty(Iterable<? extends Indexable> arg0, Context arg1) {
   16.38 -//        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   16.39 -    }
   16.40 -
   16.41 -    @Override
   16.42 -    public String getIndexerName() {
   16.43 -        return PythonIndexer.NAME;
   16.44 -    }
   16.45 -
   16.46 -    @Override
   16.47 -    public int getIndexVersion() {
   16.48 -        return PythonIndexer.VERSION;
   16.49 -    }
   16.50 -}
    17.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonInstantRename.java	Sat Sep 12 23:03:15 2015 -0700
    17.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonInstantRename.java	Sun Sep 13 11:47:42 2015 +0200
    17.3 @@ -30,6 +30,9 @@
    17.4   */
    17.5  package org.netbeans.modules.python.editor;
    17.6  
    17.7 +import org.netbeans.modules.python.source.AstPath;
    17.8 +import org.netbeans.modules.python.source.PythonParserResult;
    17.9 +import org.netbeans.modules.python.source.PythonAstUtils;
   17.10  import java.util.Collections;
   17.11  import java.util.Set;
   17.12  import javax.swing.text.Document;
   17.13 @@ -39,9 +42,9 @@
   17.14  import org.netbeans.modules.csl.api.InstantRenamer;
   17.15  import org.netbeans.modules.csl.api.OffsetRange;
   17.16  import org.netbeans.modules.csl.spi.ParserResult;
   17.17 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   17.18 -import org.netbeans.modules.python.editor.lexer.PythonCommentTokenId;
   17.19 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   17.20 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
   17.21 +import org.netbeans.modules.python.source.lexer.PythonCommentTokenId;
   17.22 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
   17.23  import org.python.antlr.PythonTree;
   17.24  import org.python.antlr.ast.Attribute;
   17.25  import org.python.antlr.ast.Call;
    18.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonKeystrokeHandler.java	Sat Sep 12 23:03:15 2015 -0700
    18.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonKeystrokeHandler.java	Sun Sep 13 11:47:42 2015 +0200
    18.3 @@ -30,14 +30,17 @@
    18.4   */
    18.5  package org.netbeans.modules.python.editor;
    18.6  
    18.7 +import org.netbeans.modules.python.source.AstPath;
    18.8 +import org.netbeans.modules.python.source.PythonParserResult;
    18.9 +import org.netbeans.modules.python.source.PythonAstUtils;
   18.10  import java.util.ArrayList;
   18.11  import java.util.List;
   18.12  import javax.swing.text.BadLocationException;
   18.13  import javax.swing.text.Caret;
   18.14  import javax.swing.text.Document;
   18.15  import javax.swing.text.JTextComponent;
   18.16 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   18.17 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   18.18 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
   18.19 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
   18.20  import org.netbeans.api.lexer.Token;
   18.21  import org.netbeans.api.lexer.TokenHierarchy;
   18.22  import org.netbeans.api.lexer.TokenId;
    19.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonLanguage.java	Sat Sep 12 23:03:15 2015 -0700
    19.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonLanguage.java	Sun Sep 13 11:47:42 2015 +0200
    19.3 @@ -30,9 +30,13 @@
    19.4   */
    19.5  package org.netbeans.modules.python.editor;
    19.6  
    19.7 +import org.netbeans.modules.python.source.PythonStructureScanner;
    19.8 +import org.netbeans.modules.python.source.PythonIndexerFactory;
    19.9 +import org.netbeans.modules.python.source.PythonIndexSearcher;
   19.10 +import org.netbeans.modules.python.source.PythonParser;
   19.11 +import org.netbeans.modules.python.source.PythonFormatter;
   19.12  import java.io.File;
   19.13  import org.netbeans.api.java.classpath.ClassPath;
   19.14 -import org.netbeans.modules.python.editor.hints.PythonHintsProvider;
   19.15  import org.netbeans.api.lexer.Language;
   19.16  import org.netbeans.modules.csl.api.CodeCompletionHandler;
   19.17  import org.netbeans.modules.csl.api.DeclarationFinder;
   19.18 @@ -50,7 +54,7 @@
   19.19  import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory;
   19.20  import org.netbeans.modules.parsing.spi.indexing.PathRecognizerRegistration;
   19.21  import org.netbeans.modules.python.api.PythonMIMEResolver;
   19.22 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   19.23 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
   19.24  import org.openide.filesystems.FileObject;
   19.25  import org.openide.filesystems.FileUtil;
   19.26  import org.openide.modules.InstalledFileLocator;
   19.27 @@ -144,15 +148,15 @@
   19.28          return new PythonIndexerFactory();
   19.29      }
   19.30  
   19.31 -    @Override
   19.32 -    public boolean hasHintsProvider() {
   19.33 -        return true;
   19.34 -    }
   19.35 -
   19.36 -    @Override
   19.37 -    public HintsProvider getHintsProvider() {
   19.38 -        return new PythonHintsProvider();
   19.39 -    }
   19.40 +//    @Override
   19.41 +//    public boolean hasHintsProvider() {
   19.42 +//        return true;
   19.43 +//    }
   19.44 +//
   19.45 +//    @Override
   19.46 +//    public HintsProvider getHintsProvider() {
   19.47 +//        return new PythonHintsProvider();
   19.48 +//    }
   19.49  
   19.50      @Override
   19.51      public DeclarationFinder getDeclarationFinder() {
    20.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonOccurrencesMarker.java	Sat Sep 12 23:03:15 2015 -0700
    20.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonOccurrencesMarker.java	Sun Sep 13 11:47:42 2015 +0200
    20.3 @@ -30,6 +30,9 @@
    20.4   */
    20.5  package org.netbeans.modules.python.editor;
    20.6  
    20.7 +import org.netbeans.modules.python.source.AstPath;
    20.8 +import org.netbeans.modules.python.source.PythonAstUtils;
    20.9 +import org.netbeans.modules.python.source.PythonParserResult;
   20.10  import java.util.ArrayList;
   20.11  import java.util.HashMap;
   20.12  import java.util.HashSet;
   20.13 @@ -50,9 +53,9 @@
   20.14  import org.netbeans.modules.parsing.spi.Parser.Result;
   20.15  import org.netbeans.modules.parsing.spi.Scheduler;
   20.16  import org.netbeans.modules.parsing.spi.SchedulerEvent;
   20.17 -import org.netbeans.modules.python.editor.lexer.PythonCommentTokenId;
   20.18 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   20.19 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   20.20 +import org.netbeans.modules.python.source.lexer.PythonCommentTokenId;
   20.21 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
   20.22 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
   20.23  import org.openide.util.Exceptions;
   20.24  import org.python.antlr.PythonTree;
   20.25  import org.python.antlr.Visitor;
    21.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonParser.java	Sat Sep 12 23:03:15 2015 -0700
    21.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.3 @@ -1,760 +0,0 @@
    21.4 -/*
    21.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    21.6 - *
    21.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    21.8 - *
    21.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   21.10 - * Other names may be trademarks of their respective owners.
   21.11 - *
   21.12 - * The contents of this file are subject to the terms of either the GNU
   21.13 - * General Public License Version 2 only ("GPL") or the Common
   21.14 - * Development and Distribution License("CDDL") (collectively, the
   21.15 - * "License"). You may not use this file except in compliance with the
   21.16 - * License. You can obtain a copy of the License at
   21.17 - * http://www.netbeans.org/cddl-gplv2.html
   21.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   21.19 - * specific language governing permissions and limitations under the
   21.20 - * License.  When distributing the software, include this License Header
   21.21 - * Notice in each file and include the License file at
   21.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   21.23 - * particular file as subject to the "Classpath" exception as provided
   21.24 - * by Oracle in the GPL Version 2 section of the License file that
   21.25 - * accompanied this code. If applicable, add the following below the
   21.26 - * License Header, with the fields enclosed by brackets [] replaced by
   21.27 - * your own identifying information:
   21.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   21.29 - *
   21.30 - * Contributor(s):
   21.31 - *
   21.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   21.33 - */
   21.34 -package org.netbeans.modules.python.editor;
   21.35 -
   21.36 -import java.io.InputStream;
   21.37 -import java.io.InputStreamReader;
   21.38 -import java.util.ArrayList;
   21.39 -import java.util.List;
   21.40 -import java.util.logging.Level;
   21.41 -import java.util.logging.Logger;
   21.42 -import javax.swing.event.ChangeListener;
   21.43 -import javax.swing.text.BadLocationException;
   21.44 -import org.netbeans.modules.csl.api.Severity;
   21.45 -import org.netbeans.modules.csl.spi.DefaultError;
   21.46 -import org.netbeans.modules.csl.api.Error;
   21.47 -import org.netbeans.modules.csl.api.OffsetRange;
   21.48 -import org.netbeans.modules.csl.spi.GsfUtilities;
   21.49 -import org.netbeans.modules.parsing.api.Snapshot;
   21.50 -import org.netbeans.modules.parsing.api.Task;
   21.51 -import org.netbeans.modules.parsing.spi.Parser;
   21.52 -import org.netbeans.modules.parsing.spi.SourceModificationEvent;
   21.53 -import org.netbeans.modules.python.api.PythonFileEncodingQuery;
   21.54 -import org.openide.filesystems.FileObject;
   21.55 -import org.python.antlr.runtime.ANTLRStringStream;
   21.56 -import org.python.antlr.runtime.BaseRecognizer;
   21.57 -import org.python.antlr.runtime.BitSet;
   21.58 -import org.python.antlr.runtime.CommonToken;
   21.59 -import org.python.antlr.runtime.CommonTokenStream;
   21.60 -import org.python.antlr.runtime.IntStream;
   21.61 -import org.python.antlr.runtime.Lexer;
   21.62 -import org.python.antlr.runtime.MismatchedTokenException;
   21.63 -import org.python.antlr.runtime.RecognitionException;
   21.64 -
   21.65 -import org.openide.filesystems.FileUtil;
   21.66 -import org.openide.util.Exceptions;
   21.67 -import org.python.antlr.ListErrorHandler;
   21.68 -import org.python.antlr.ParseException;
   21.69 -import org.python.antlr.PythonLexer;
   21.70 -import org.python.antlr.PythonTokenSource;
   21.71 -import org.python.antlr.PythonTree;
   21.72 -import org.python.antlr.PythonTreeAdaptor;
   21.73 -import org.python.antlr.base.expr;
   21.74 -import org.python.antlr.base.mod;
   21.75 -import org.python.antlr.base.slice;
   21.76 -import org.python.antlr.base.stmt;
   21.77 -import org.python.antlr.runtime.ANTLRReaderStream;
   21.78 -import org.python.antlr.runtime.CharStream;
   21.79 -
   21.80 -/**
   21.81 - * Parser for Python. Wraps Jython.
   21.82 - * 
   21.83 - * @author Frank Wierzbicki
   21.84 - * @author Tor Norbye
   21.85 - */
   21.86 -public class PythonParser extends Parser {
   21.87 -    /** For unit tests such that they can make sure we didn't have a parser abort */
   21.88 -    static Throwable runtimeException;
   21.89 -
   21.90 -    static {
   21.91 -        org.python.core.PySystemState.initialize();
   21.92 -    }
   21.93 -    
   21.94 -    private Result lastResult;
   21.95 -    private final PythonFileEncodingQuery fileEncodingQuery = new PythonFileEncodingQuery();
   21.96 -    private String headerCached = null;
   21.97 -    private String encodingCache = null;
   21.98 -
   21.99 -    public mod file_input(CharStream charStream, String fileName) throws RecognitionException {
  21.100 -        ListErrorHandler eh = new ListErrorHandler();
  21.101 -        mod tree = null;
  21.102 -        PythonLexer lexer = new PythonLexer(charStream);
  21.103 -        lexer.setErrorHandler(eh);
  21.104 -        CommonTokenStream tokens = new CommonTokenStream(lexer);
  21.105 -        tokens.discardOffChannelTokens(true);
  21.106 -        PythonTokenSource indentedSource = new PythonTokenSource(tokens, fileName);
  21.107 -        tokens = new CommonTokenStream(indentedSource);
  21.108 -        org.python.antlr.PythonParser parser = new org.python.antlr.PythonParser(tokens);
  21.109 -        parser.setTreeAdaptor(new PythonTreeAdaptor());
  21.110 -        parser.setErrorHandler(eh);
  21.111 -        org.python.antlr.PythonParser.file_input_return r = parser.file_input();
  21.112 -        tree = (mod)r.getTree();
  21.113 -        return tree;
  21.114 -    }
  21.115 -
  21.116 -    @Override
  21.117 -    public void addChangeListener(ChangeListener changeListener) {}
  21.118 -
  21.119 -    @Override
  21.120 -    public void removeChangeListener(ChangeListener changeListener) {}
  21.121 -    
  21.122 -    public PythonTree parse(InputStream istream, String fileName) throws Exception {
  21.123 -        InputStreamReader reader = new InputStreamReader(istream, "ISO-8859-1");
  21.124 -        return file_input(new ANTLRReaderStream(reader), fileName);
  21.125 -    }
  21.126 -    
  21.127 -    @Override
  21.128 -    public final Result getResult(Task task) throws org.netbeans.modules.parsing.spi.ParseException {
  21.129 -        return lastResult;
  21.130 -    }
  21.131 -    
  21.132 -    private static final Logger LOG = Logger.getLogger(PythonParser.class.getName());
  21.133 -
  21.134 -    @Override
  21.135 -    public void parse(Snapshot snapshot, Task task, SourceModificationEvent event) throws org.netbeans.modules.parsing.spi.ParseException {
  21.136 -        Context context = new Context();
  21.137 -        context.snapshot = snapshot;
  21.138 -        context.event = event;
  21.139 -        context.task = task;
  21.140 -        context.caretOffset = GsfUtilities.getLastKnownCaretOffset(snapshot, event);
  21.141 -        context.source = snapshot.getText().toString();
  21.142 -        context.file = snapshot.getSource().getFileObject();
  21.143 -        if(context.file == null) {
  21.144 -            return; // TODO: parse the source, not the file
  21.145 -        }
  21.146 -        /* Let's not sanitize ;-) Would be great if we could have a more robust parser
  21.147 -        if (context.caretOffset != -1) {
  21.148 -            context.sanitized = Sanitize.EDITED_DOT;
  21.149 -        }
  21.150 -        */
  21.151 -        lastResult = parse(context, context.sanitized);
  21.152 -    }
  21.153 -    public PythonParserResult parse(final Context context, Sanitize sanitizing) {
  21.154 -        boolean sanitizedSource = false;
  21.155 -        String sourceCode = context.source;
  21.156 -        if (!((sanitizing == Sanitize.NONE) || (sanitizing == Sanitize.NEVER))) {
  21.157 -            boolean ok = sanitizeSource(context, sanitizing);
  21.158 -
  21.159 -            if (ok) {
  21.160 -                assert context.sanitizedSource != null;
  21.161 -                sanitizedSource = true;
  21.162 -                sourceCode = context.sanitizedSource;
  21.163 -            } else {
  21.164 -                // Try next trick
  21.165 -                return sanitize(context, sanitizing);
  21.166 -            }
  21.167 -        }
  21.168 -        final String source = sourceCode;
  21.169 -
  21.170 -        if (sanitizing == Sanitize.NONE) {
  21.171 -            context.errorOffset = -1;
  21.172 -        }
  21.173 -
  21.174 -        final List<Error> errors = new ArrayList<>();
  21.175 -        final FileObject file = context.file;
  21.176 -        try {
  21.177 -            String fileName = file.getNameExt();
  21.178 -            // TODO - sniff file headers etc. Frank's comment:
  21.179 -            // Longer term for Python compatibility, having NetBeans sniff the top two lines
  21.180 -            // for an encoding would be the right thing to do from a pure Python
  21.181 -            // compatibility standard (see http://www.python.org/dev/peps/pep-0263/) I
  21.182 -            // have pep-0263 code in Jython that I could probably extract for this
  21.183 -            // purpose down the road.
  21.184 -            //String charset = "ISO8859_1"; // NOI18N
  21.185 -            //String charset = "UTF-8"; // NOI18N
  21.186 -            //String charset = "iso8859_1"; // NOI18N
  21.187 -            // TODO: improve this check.
  21.188 -            int cache_len = sourceCode.length() >= 64 ? 64 : sourceCode.length();
  21.189 -            if (headerCached == null || cache_len != headerCached.length() || !headerCached.equals(sourceCode.substring(0, cache_len))) {
  21.190 -                headerCached = sourceCode.substring(0, cache_len);
  21.191 -                encodingCache = fileEncodingQuery.getPythonFileEncoding(sourceCode.split("\n", 2));                
  21.192 -            }
  21.193 -            String charset = encodingCache;            
  21.194 -                
  21.195 -            final boolean ignoreErrors = sanitizedSource;
  21.196 -            ListErrorHandler errorHandler = new ListErrorHandler() {
  21.197 -                @Override
  21.198 -                public void error(String message, PythonTree t) {
  21.199 -                    errors.add(new DefaultError(null, message, null, file, t.getCharStartIndex(), t.getCharStopIndex(), Severity.ERROR));
  21.200 -                    super.error(message, t);
  21.201 -                }
  21.202 -
  21.203 -                @Override
  21.204 -                public expr errorExpr(PythonTree t) {
  21.205 -                    return super.errorExpr(t);
  21.206 -                }
  21.207 -
  21.208 -                @Override
  21.209 -                public mod errorMod(PythonTree t) {
  21.210 -                    return super.errorMod(t);
  21.211 -                }
  21.212 -
  21.213 -                @Override
  21.214 -                public slice errorSlice(PythonTree t) {
  21.215 -                    return super.errorSlice(t);
  21.216 -                }
  21.217 -
  21.218 -                @Override
  21.219 -                public stmt errorStmt(PythonTree t) {
  21.220 -                    return super.errorStmt(t);
  21.221 -                }
  21.222 -
  21.223 -                @Override
  21.224 -                public boolean mismatch(BaseRecognizer br, IntStream input, int ttype, BitSet follow) {
  21.225 -                    return super.mismatch(br, input, ttype, follow);
  21.226 -                }
  21.227 -
  21.228 -                @Override
  21.229 -                public Object recoverFromMismatchedToken(BaseRecognizer br, IntStream input, int ttype, BitSet follow) {
  21.230 -                    MismatchedTokenException mt = new MismatchedTokenException(ttype, input);
  21.231 -                    String message = br.getErrorMessage(mt, br.getTokenNames());
  21.232 -                    if (mt.line >= 1) {
  21.233 -                        int lineOffset = findLineOffset(context.source, mt.line-1);
  21.234 -                        if (mt.charPositionInLine > 0) {
  21.235 -                            lineOffset += mt.charPositionInLine;
  21.236 -                        }
  21.237 -                        int start = lineOffset;//t.getCharStartIndex();
  21.238 -                        int stop = lineOffset;//t.getCharStopIndex();
  21.239 -                        errors.add(new DefaultError(null, message, null, file, start, stop, Severity.ERROR));
  21.240 -                    }
  21.241 -                    return super.recoverFromMismatchedToken(br, input, ttype, follow);
  21.242 -                }
  21.243 -
  21.244 -                @Override
  21.245 -                public void recover(Lexer lex, RecognitionException re) {
  21.246 -                    super.recover(lex, re);
  21.247 -                }
  21.248 -
  21.249 -                @Override
  21.250 -                public void recover(BaseRecognizer br, IntStream input, RecognitionException re) {
  21.251 -                    super.recover(br, input, re);
  21.252 -                }
  21.253 -
  21.254 -                @Override
  21.255 -                public void reportError(BaseRecognizer br, RecognitionException re) {
  21.256 -                    if (!ignoreErrors) {
  21.257 -                        String message = br.getErrorMessage(re, br.getTokenNames());
  21.258 -                        if (message == null || message.length() == 0) {
  21.259 -                            message = re.getMessage();
  21.260 -                        }
  21.261 -                        if (message == null) {
  21.262 -                            //message = re.getUnexpectedType();
  21.263 -                            message = re.toString();
  21.264 -                        }
  21.265 -                        int start = re.index;
  21.266 -
  21.267 -                        // Try to find the line offset. re.index doesn't do the trick.
  21.268 -                        start = PythonUtils.getOffsetByLineCol(source, re.line - 1, 0); // -1: 0-based
  21.269 -                        int end = start;
  21.270 -                        if (re.charPositionInLine > 0) {
  21.271 -                            try {
  21.272 -                                end = GsfUtilities.getRowLastNonWhite(source, start) + 1;
  21.273 -                                start += re.charPositionInLine;
  21.274 -                                if (end < start) {
  21.275 -                                    end = start;
  21.276 -                                }
  21.277 -                            } catch (BadLocationException ex) {
  21.278 -                                Exceptions.printStackTrace(ex);
  21.279 -                                end = start;
  21.280 -                            }
  21.281 -                            if (end == 0) {
  21.282 -                                end = start;
  21.283 -                            }
  21.284 -                        }
  21.285 -
  21.286 -                        // Some errors have better offsets if we look at the token stream
  21.287 -                        if (re instanceof MismatchedTokenException) {
  21.288 -                            MismatchedTokenException m = (MismatchedTokenException)re;
  21.289 -                            if (m.token != null) {
  21.290 -                                if (m.token instanceof org.python.antlr.runtime.CommonToken) {
  21.291 -                                    CommonToken token = (org.python.antlr.runtime.CommonToken)m.token;
  21.292 -                                    start = token.getStartIndex();
  21.293 -                                    end = token.getStopIndex();
  21.294 -                                }
  21.295 -                            }
  21.296 -                        }
  21.297 -
  21.298 -                        if (start > source.length()) {
  21.299 -                            start = source.length();
  21.300 -                            end = start;
  21.301 -                        }
  21.302 -
  21.303 -                        errors.add(new DefaultError(null, message, null, file, start, end, Severity.ERROR));
  21.304 -
  21.305 -                        // In order to avoid a StackOverflowError, the BaseRecognizer must be recreated.
  21.306 -                        // We must keep the names of the tokens to avoid a NullPointerException.
  21.307 -                        // See bz252630
  21.308 -                        final String[] tokenNames = br.getTokenNames();
  21.309 -                        br = new BaseRecognizer() {
  21.310 -
  21.311 -                            @Override
  21.312 -                            public String getSourceName() {
  21.313 -                                return file.getName();
  21.314 -                            }
  21.315 -
  21.316 -                            @Override
  21.317 -                            public String[] getTokenNames() {
  21.318 -                                return tokenNames;
  21.319 -                            }
  21.320 -                        };
  21.321 -
  21.322 -                        super.reportError(br, re);
  21.323 -                    }
  21.324 -                }
  21.325 -            };
  21.326 -
  21.327 -            PythonLexer lexer = new PythonLexer(new ANTLRStringStream(sourceCode));
  21.328 -            lexer.setErrorHandler(errorHandler);
  21.329 -            CommonTokenStream tokens = new CommonTokenStream(lexer);
  21.330 -            tokens.discardOffChannelTokens(true);
  21.331 -            PythonTokenSource indentedSource = new PythonTokenSource(tokens, fileName);
  21.332 -            CommonTokenStream indentedTokens = new CommonTokenStream(indentedSource);
  21.333 -            // Import line ending with a dot raise a NullPointerException in
  21.334 -            // org.python.antlr.GrammarActions.makeDottedText called from parser.file_input
  21.335 -            // sanitizeImportTokens will remove the dot token from the list of tokens in
  21.336 -            // indentedTokens to avoid the bug and add an error at this file.
  21.337 -            // See https://netbeans.org/bugzilla/show_bug.cgi?id=252356
  21.338 -            sanitizeImportTokens(indentedTokens, errors, file);
  21.339 -            org.python.antlr.PythonParser parser;
  21.340 -            if (charset != null) {
  21.341 -                parser = new org.python.antlr.PythonParser(indentedTokens, charset);
  21.342 -            } else {
  21.343 -                parser = new org.python.antlr.PythonParser(indentedTokens);
  21.344 -            }
  21.345 -            parser.setTreeAdaptor(new PythonTreeAdaptor());
  21.346 -            parser.setErrorHandler(errorHandler);
  21.347 -            org.python.antlr.PythonParser.file_input_return r = parser.file_input();
  21.348 -            PythonTree t = (PythonTree)r.getTree();
  21.349 -            PythonParserResult result = new PythonParserResult(t, context.snapshot);
  21.350 -            result.setErrors(errors);
  21.351 -
  21.352 -            result.setSanitized(context.sanitized, context.sanitizedRange, context.sanitizedContents);
  21.353 -            result.setSource(sourceCode);
  21.354 -
  21.355 -            return result;
  21.356 -        } catch (ParseException pe) {
  21.357 -            if (sanitizing == Sanitize.NONE) {
  21.358 -                PythonParserResult sanitizedResult = sanitize(context, sanitizing);
  21.359 -                if (sanitizedResult.isValid()) {
  21.360 -                    return sanitizedResult;
  21.361 -                } else {
  21.362 -                    int offset = pe.index;
  21.363 -                    assert offset >= 0;
  21.364 -                    String desc = pe.getLocalizedMessage();
  21.365 -                    if (desc == null) {
  21.366 -                        desc = pe.getMessage();
  21.367 -                    }
  21.368 -                    DefaultError error = new DefaultError(null /*key*/, desc, null, file, offset, offset, Severity.ERROR);
  21.369 -                    PythonParserResult parserResult = new PythonParserResult(null, context.snapshot);
  21.370 -                    parserResult.addError(error);
  21.371 -                    for (Error e : errors) {
  21.372 -                        parserResult.addError(e);
  21.373 -                    }
  21.374 -
  21.375 -                    return parserResult;
  21.376 -                }
  21.377 -            } else {
  21.378 -                return sanitize(context, sanitizing);
  21.379 -            }
  21.380 -        } catch (NullPointerException e) {
  21.381 -            String fileName = "";
  21.382 -            if (file != null) {
  21.383 -                fileName = FileUtil.getFileDisplayName(file);
  21.384 -            }
  21.385 -            e = Exceptions.attachMessage(e, "Was parsing " + fileName);
  21.386 -            Exceptions.printStackTrace(e);
  21.387 -            return new PythonParserResult(null, context.snapshot);
  21.388 -        } catch (Throwable t) {
  21.389 -            runtimeException = t;
  21.390 -            StackTraceElement[] stackTrace = t.getStackTrace();
  21.391 -            if (stackTrace != null && stackTrace.length > 0 && stackTrace[0].getClassName().startsWith("org.python.antlr")) {//.runtime.tree.RewriteRuleElementStream")) {
  21.392 -                // This is issue 150921
  21.393 -                // Don't bug user about it -- we already know
  21.394 -                Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Encountered issue #150921", t);
  21.395 -            } else {
  21.396 -                t = Exceptions.attachMessage(t, "Was parsing " + FileUtil.getFileDisplayName(file));
  21.397 -                Exceptions.printStackTrace(t);
  21.398 -            }
  21.399 -            return new PythonParserResult(null, context.snapshot);
  21.400 -        }
  21.401 -    }
  21.402 -
  21.403 -    private void sanitizeImportTokens(CommonTokenStream indentedTokens, List errors, FileObject file) {
  21.404 -        List tokens = indentedTokens.getTokens();
  21.405 -        List<CommonToken> tokensToRemove = new ArrayList<>();
  21.406 -        int i = 0;
  21.407 -        while (i < tokens.size()) {
  21.408 -            CommonToken importToken = (CommonToken)tokens.get(i);
  21.409 -            if ("import".equals(importToken.getText()) || "from".equals(importToken.getText())) {
  21.410 -                // sanitizeDotTokens return the index of the token that starts the next line
  21.411 -                i = sanitizeDotTokens(tokens, tokensToRemove, importToken, i + 1, errors, file);
  21.412 -            } else {
  21.413 -                i++;
  21.414 -            }
  21.415 -        }
  21.416 -
  21.417 -        for (CommonToken token : tokensToRemove) {
  21.418 -            tokens.remove(token);
  21.419 -        }
  21.420 -    }
  21.421 -
  21.422 -    private int sanitizeDotTokens(List tokens, List tokensToRemove, CommonToken importToken,
  21.423 -            int startIndex, List errors, FileObject file) {
  21.424 -        for (int j = startIndex; j < tokens.size() - 1; j++) {
  21.425 -            CommonToken dotToken = (CommonToken)tokens.get(j);
  21.426 -            CommonToken nextToken = (CommonToken)tokens.get(j + 1);
  21.427 -            if (".".equals(dotToken.getText())) {
  21.428 -                if (nextToken.getText().startsWith("\n")) {
  21.429 -                    tokensToRemove.add(dotToken);
  21.430 -                    String rawTokenText;
  21.431 -                    if (nextToken.getText().startsWith("\n")) {
  21.432 -                        rawTokenText = "\\n";
  21.433 -                    } else {
  21.434 -                        rawTokenText = " ";
  21.435 -                    }
  21.436 -                    errors.add(
  21.437 -                        new DefaultError(null, "Mismatch input '.' expecting NAME\nMissing NAME at '" + rawTokenText + "'",
  21.438 -                            null, file, importToken.getStartIndex(), dotToken.getStopIndex(), Severity.ERROR));
  21.439 -                }
  21.440 -            } else if ("\n".equals(nextToken.getText())) { // End of line, must continue looping from external loop
  21.441 -                return j + 1;
  21.442 -            }
  21.443 -        }
  21.444 -
  21.445 -        return startIndex;
  21.446 -    }
  21.447 -
  21.448 -    private static String asString(CharSequence sequence) {
  21.449 -        if (sequence instanceof String) {
  21.450 -            return (String)sequence;
  21.451 -        } else {
  21.452 -            return sequence.toString();
  21.453 -        }
  21.454 -    }
  21.455 -
  21.456 -
  21.457 -    @SuppressWarnings("fallthrough")
  21.458 -    private PythonParserResult sanitize(final Context context, final Sanitize sanitizing) {
  21.459 -
  21.460 -        switch (sanitizing) {
  21.461 -        case NEVER:
  21.462 -            return new PythonParserResult(null, context.snapshot);
  21.463 -
  21.464 -        case NONE:
  21.465 -            if (context.caretOffset != -1) {
  21.466 -                return parse(context, Sanitize.EDITED_DOT);
  21.467 -            }
  21.468 -
  21.469 -        case EDITED_DOT:
  21.470 -            // We've tried removing whitespace around the edit location
  21.471 -            // Fall through to try parsing with removing stuff around error location
  21.472 -            // (Don't bother doing this if errorOffset==caretOffset since that would try the same
  21.473 -            // source as EDITED_DOT which has no better chance of succeeding...)
  21.474 -            if (context.errorOffset != -1 && context.errorOffset != context.caretOffset) {
  21.475 -                return parse(context, Sanitize.ERROR_DOT);
  21.476 -            }
  21.477 -
  21.478 -        // Fall through to try the next trick
  21.479 -        case ERROR_DOT:
  21.480 -
  21.481 -            // We've tried removing dots - now try removing the whole line at the error position
  21.482 -            if (context.errorOffset != -1) {
  21.483 -                return parse(context, Sanitize.ERROR_LINE);
  21.484 -            }
  21.485 -
  21.486 -        // Fall through to try the next trick
  21.487 -        case ERROR_LINE:
  21.488 -
  21.489 -            // Messing with the error line didn't work - we could try "around" the error line
  21.490 -            // but I'm not attempting that now.
  21.491 -            // Finally try removing the whole line around the user editing position
  21.492 -            // (which could be far from where the error is showing up - but if you're typing
  21.493 -            // say a new "def" statement in a class, this will show up as an error on a mismatched
  21.494 -            // "end" statement rather than here
  21.495 -            if (context.caretOffset != -1) {
  21.496 -                return parse(context, Sanitize.EDITED_LINE);
  21.497 -            }
  21.498 -
  21.499 -        // Fall through for default handling
  21.500 -        case EDITED_LINE:
  21.501 -        default:
  21.502 -            // We're out of tricks - just return the failed parse result
  21.503 -            return new PythonParserResult(null, context.snapshot);
  21.504 -        }
  21.505 -    }
  21.506 -
  21.507 -    /**
  21.508 -     * Try cleaning up the source buffer around the current offset to increase
  21.509 -     * likelihood of parse success. Initially this method had a lot of
  21.510 -     * logic to determine whether a parse was likely to fail (e.g. invoking
  21.511 -     * the isEndMissing method from bracket completion etc.).
  21.512 -     * However, I am now trying a parse with the real source first, and then
  21.513 -     * only if that fails do I try parsing with sanitized source. Therefore,
  21.514 -     * this method has to be less conservative in ripping out code since it
  21.515 -     * will only be used when the regular source is failing.
  21.516 -     *
  21.517 -     * @todo Automatically close current statement by inserting ";"
  21.518 -     * @todo Handle sanitizing "new ^" from parse errors
  21.519 -     * @todo Replace "end" insertion fix with "}" insertion
  21.520 -     */
  21.521 -    private boolean sanitizeSource(Context context, Sanitize sanitizing) {
  21.522 -        int offset = context.caretOffset;
  21.523 -
  21.524 -        // Let caretOffset represent the offset of the portion of the buffer we'll be operating on
  21.525 -        if ((sanitizing == Sanitize.ERROR_DOT) || (sanitizing == Sanitize.ERROR_LINE)) {
  21.526 -            offset = context.errorOffset;
  21.527 -        }
  21.528 -
  21.529 -        // Don't attempt cleaning up the source if we don't have the buffer position we need
  21.530 -        if (offset == -1) {
  21.531 -            return false;
  21.532 -        }
  21.533 -
  21.534 -        // The user might be editing around the given caretOffset.
  21.535 -        // See if it looks modified
  21.536 -        // Insert an end statement? Insert a } marker?
  21.537 -        String doc = context.source;
  21.538 -        if (offset > doc.length()) {
  21.539 -            return false;
  21.540 -        }
  21.541 -
  21.542 -        try {
  21.543 -            // Sometimes the offset shows up on the next line
  21.544 -            if (GsfUtilities.isRowEmpty(doc, offset) || GsfUtilities.isRowWhite(doc, offset)) {
  21.545 -                offset = GsfUtilities.getRowStart(doc, offset) - 1;
  21.546 -                if (offset < 0) {
  21.547 -                    offset = 0;
  21.548 -                }
  21.549 -            }
  21.550 -
  21.551 -            if (!(GsfUtilities.isRowEmpty(doc, offset) || GsfUtilities.isRowWhite(doc, offset))) {
  21.552 -                if ((sanitizing == Sanitize.EDITED_LINE) || (sanitizing == Sanitize.ERROR_LINE)) {
  21.553 -                    // See if I should try to remove the current line, since it has text on it.
  21.554 -                    int lineEnd = GsfUtilities.getRowLastNonWhite(doc, offset);
  21.555 -
  21.556 -                    if (lineEnd != -1) {
  21.557 -                        lineEnd++; // lineEnd is exclusive, not inclusive
  21.558 -                        StringBuilder sb = new StringBuilder(doc.length());
  21.559 -                        int lineStart = GsfUtilities.getRowStart(doc, offset);
  21.560 -                        if (lineEnd >= lineStart + 2) {
  21.561 -                            sb.append(doc.substring(0, lineStart));
  21.562 -                            sb.append("//");
  21.563 -                            int rest = lineStart + 2;
  21.564 -                            if (rest < doc.length()) {
  21.565 -                                sb.append(doc.substring(rest, doc.length()));
  21.566 -                            }
  21.567 -                        } else {
  21.568 -                            // A line with just one character - can't replace with a comment
  21.569 -                            // Just replace the char with a space
  21.570 -                            sb.append(doc.substring(0, lineStart));
  21.571 -                            sb.append(" ");
  21.572 -                            int rest = lineStart + 1;
  21.573 -                            if (rest < doc.length()) {
  21.574 -                                sb.append(doc.substring(rest, doc.length()));
  21.575 -                            }
  21.576 -
  21.577 -                        }
  21.578 -
  21.579 -                        assert sb.length() == doc.length();
  21.580 -
  21.581 -                        context.sanitizedRange = new OffsetRange(lineStart, lineEnd);
  21.582 -                        context.sanitizedSource = sb.toString();
  21.583 -                        context.sanitizedContents = doc.substring(lineStart, lineEnd);
  21.584 -                        return true;
  21.585 -                    }
  21.586 -                } else {
  21.587 -                    assert sanitizing == Sanitize.ERROR_DOT || sanitizing == Sanitize.EDITED_DOT;
  21.588 -                    // Try nuking dots/colons from this line
  21.589 -                    // See if I should try to remove the current line, since it has text on it.
  21.590 -                    int lineStart = GsfUtilities.getRowStart(doc, offset);
  21.591 -                    int lineEnd = offset - 1;
  21.592 -                    while (lineEnd >= lineStart && lineEnd < doc.length()) {
  21.593 -                        if (!Character.isWhitespace(doc.charAt(lineEnd))) {
  21.594 -                            break;
  21.595 -                        }
  21.596 -                        lineEnd--;
  21.597 -                    }
  21.598 -                    if (lineEnd > lineStart) {
  21.599 -                        StringBuilder sb = new StringBuilder(doc.length());
  21.600 -                        String line = doc.substring(lineStart, lineEnd + 1);
  21.601 -                        int removeChars = 0;
  21.602 -                        int removeEnd = lineEnd + 1;
  21.603 -                        boolean isLineEnd = GsfUtilities.getRowLastNonWhite(context.source, lineEnd) <= lineEnd;
  21.604 -
  21.605 -                        if (line.endsWith(".")) { // NOI18N
  21.606 -                            removeChars = 1;
  21.607 -                        } else if (line.endsWith("(")) { // NOI18N
  21.608 -                            if (isLineEnd) {
  21.609 -                                removeChars = 1;
  21.610 -                            }
  21.611 -                        } else if (line.endsWith(",")) { // NOI18N                            removeChars = 1;
  21.612 -                            if (!isLineEnd) {
  21.613 -                                removeChars = 1;
  21.614 -                            }
  21.615 -                        } else if (line.endsWith(", ")) { // NOI18N
  21.616 -                            if (!isLineEnd) {
  21.617 -                                removeChars = 2;
  21.618 -                            }
  21.619 -                        } else if (line.endsWith(",)")) { // NOI18N
  21.620 -                            // Handle lone comma in parameter list - e.g.
  21.621 -                            // type "foo(a," -> you end up with "foo(a,|)" which doesn't parse - but
  21.622 -                            // the line ends with ")", not "," !
  21.623 -                            // Just remove the comma
  21.624 -                            removeChars = 1;
  21.625 -                            removeEnd--;
  21.626 -                        } else if (line.endsWith(", )")) { // NOI18N
  21.627 -                            // Just remove the comma
  21.628 -                            removeChars = 1;
  21.629 -                            removeEnd -= 2;
  21.630 -                        } else if (line.endsWith(" def") && isLineEnd) { // NOI18N
  21.631 -                            removeChars = 3;
  21.632 -                        } else {
  21.633 -//                            // Make sure the line doesn't end with one of the JavaScript keywords
  21.634 -//                            // (new, do, etc) - we can't handle that!
  21.635 -//                            for (String keyword : PythonUtils.PYTHON_KEYWORDS) { // reserved words are okay
  21.636 -//                                if (line.endsWith(keyword)) {
  21.637 -//                                    if ("print".equals(keyword)) { // NOI18N
  21.638 -//                                        // Only remove the keyword if it's the end of the line. Otherwise,
  21.639 -//                                        // it could have just been typed in front of something (e.g. inserted a print) and we don't
  21.640 -//                                        // want to confuse the parser with "va foo" instead of "var foo"
  21.641 -//                                        if (!isLineEnd) {
  21.642 -//                                            continue;
  21.643 -//                                        }
  21.644 -//                                    }
  21.645 -//                                    removeChars = 1;
  21.646 -//                                    break;
  21.647 -//                                }
  21.648 -//                            }
  21.649 -                        }
  21.650 -
  21.651 -                        if (removeChars == 0) {
  21.652 -                            return false;
  21.653 -                        }
  21.654 -
  21.655 -                        int removeStart = removeEnd - removeChars;
  21.656 -
  21.657 -                        sb.append(doc.substring(0, removeStart));
  21.658 -
  21.659 -                        for (int i = 0; i < removeChars; i++) {
  21.660 -                            sb.append(' ');
  21.661 -                        }
  21.662 -
  21.663 -                        if (removeEnd < doc.length()) {
  21.664 -                            sb.append(doc.substring(removeEnd, doc.length()));
  21.665 -                        }
  21.666 -                        assert sb.length() == doc.length();
  21.667 -
  21.668 -                        context.sanitizedRange = new OffsetRange(removeStart, removeEnd);
  21.669 -                        context.sanitizedSource = sb.toString();
  21.670 -                        context.sanitizedContents = doc.substring(removeStart, removeEnd);
  21.671 -                        return true;
  21.672 -                    }
  21.673 -                }
  21.674 -            }
  21.675 -        } catch (BadLocationException ble) {
  21.676 -            Exceptions.printStackTrace(ble);
  21.677 -        }
  21.678 -
  21.679 -        return false;
  21.680 -    }
  21.681 -
  21.682 -    private static int findLineOffset(String source, int line) {
  21.683 -        int offset = -1;
  21.684 -        for (int i = 0; i < line; i++) {
  21.685 -            offset = source.indexOf("\n", offset+1);
  21.686 -            if (offset == -1) {
  21.687 -                return source.length();
  21.688 -            }
  21.689 -        }
  21.690 -
  21.691 -        return Math.min(source.length(), offset+1);
  21.692 -    }
  21.693 -
  21.694 -    /** Attempts to sanitize the input buffer */
  21.695 -    public static enum Sanitize {
  21.696 -        /** Only parse the current file accurately, don't try heuristics */
  21.697 -        NEVER,
  21.698 -        /** Perform no sanitization */
  21.699 -        NONE,
  21.700 -        /** Try to remove the trailing . or :: at the caret line */
  21.701 -        EDITED_DOT,
  21.702 -        /** Try to remove the trailing . or :: at the error position, or the prior
  21.703 -         * line, or the caret line */
  21.704 -        ERROR_DOT,
  21.705 -        /** Try to cut out the error line */
  21.706 -        ERROR_LINE,
  21.707 -        /** Try to cut out the current edited line, if known */
  21.708 -        EDITED_LINE,
  21.709 -    }
  21.710 -
  21.711 -    /** Sanitize context */
  21.712 -    public static class Context {
  21.713 -        private FileObject file;
  21.714 -//        private ParseListener listener;
  21.715 -        private int errorOffset;
  21.716 -        private String source;
  21.717 -        private String sanitizedSource;
  21.718 -        private OffsetRange sanitizedRange = OffsetRange.NONE;
  21.719 -        private String sanitizedContents;
  21.720 -        private int caretOffset;
  21.721 -        private Sanitize sanitized = Sanitize.NONE;
  21.722 -//        private TranslatedSource translatedSource;
  21.723 -//        private Parser.Job job;
  21.724 -        private Snapshot snapshot;
  21.725 -        private Task task;
  21.726 -        private SourceModificationEvent event;
  21.727 -//
  21.728 -//        public Context(ParserFile parserFile, ParseListener listener, String source, int caretOffset, TranslatedSource translatedSource, Parser.Job job) {
  21.729 -//            this.file = parserFile;
  21.730 -//            this.listener = listener;
  21.731 -//            this.source = source;
  21.732 -//            this.caretOffset = caretOffset;
  21.733 -//            this.translatedSource = translatedSource;
  21.734 -//            this.job = job;
  21.735 -//
  21.736 -//
  21.737 -//            if (caretOffset != -1) {
  21.738 -//                sanitized = Sanitize.EDITED_DOT;
  21.739 -//            }
  21.740 -//        }
  21.741 -//
  21.742 -//        @Override
  21.743 -//        public String toString() {
  21.744 -//            return "PythonParser.Context(" + file.toString() + ")"; // NOI18N
  21.745 -//        }
  21.746 -//
  21.747 -//        public OffsetRange getSanitizedRange() {
  21.748 -//            return sanitizedRange;
  21.749 -//        }
  21.750 -//
  21.751 -//        public Sanitize getSanitized() {
  21.752 -//            return sanitized;
  21.753 -//        }
  21.754 -//
  21.755 -//        public String getSanitizedSource() {
  21.756 -//            return sanitizedSource;
  21.757 -//        }
  21.758 -//
  21.759 -//        public int getErrorOffset() {
  21.760 -//            return errorOffset;
  21.761 -//        }
  21.762 -    }
  21.763 -}
    22.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonParserResult.java	Sat Sep 12 23:03:15 2015 -0700
    22.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3 @@ -1,153 +0,0 @@
    22.4 -/*
    22.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    22.6 - *
    22.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    22.8 - *
    22.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   22.10 - * Other names may be trademarks of their respective owners.
   22.11 - *
   22.12 - * The contents of this file are subject to the terms of either the GNU
   22.13 - * General Public License Version 2 only ("GPL") or the Common
   22.14 - * Development and Distribution License("CDDL") (collectively, the
   22.15 - * "License"). You may not use this file except in compliance with the
   22.16 - * License. You can obtain a copy of the License at
   22.17 - * http://www.netbeans.org/cddl-gplv2.html
   22.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   22.19 - * specific language governing permissions and limitations under the
   22.20 - * License.  When distributing the software, include this License Header
   22.21 - * Notice in each file and include the License file at
   22.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   22.23 - * particular file as subject to the "Classpath" exception as provided
   22.24 - * by Oracle in the GPL Version 2 section of the License file that
   22.25 - * accompanied this code. If applicable, add the following below the
   22.26 - * License Header, with the fields enclosed by brackets [] replaced by
   22.27 - * your own identifying information:
   22.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   22.29 - *
   22.30 - * Contributor(s):
   22.31 - *
   22.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   22.33 - */
   22.34 -package org.netbeans.modules.python.editor;
   22.35 -
   22.36 -import java.util.Collections;
   22.37 -import java.util.LinkedList;
   22.38 -import java.util.List;
   22.39 -import org.netbeans.api.annotations.common.NonNull;
   22.40 -import org.netbeans.modules.csl.api.Error;
   22.41 -import org.netbeans.modules.csl.api.OffsetRange;
   22.42 -import org.netbeans.modules.csl.spi.ParserResult;
   22.43 -import org.netbeans.modules.parsing.api.Snapshot;
   22.44 -import org.netbeans.modules.python.editor.PythonParser.Sanitize;
   22.45 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
   22.46 -import org.python.antlr.PythonTree;
   22.47 -
   22.48 -/**
   22.49 - * A ParserResult for Python. The AST Jython's AST.
   22.50 - *
   22.51 - * @todo Cache AstPath for caret position here!
   22.52 - * @author Tor Norbye
   22.53 - */
   22.54 -public class PythonParserResult extends ParserResult {
   22.55 -    private PythonTree root;
   22.56 -    private List<Error> errors;
   22.57 -    private OffsetRange sanitizedRange = OffsetRange.NONE;
   22.58 -    private String source;
   22.59 -    private String sanitizedContents;
   22.60 -    private PythonParser.Sanitize sanitized;
   22.61 -    private PythonStructureScanner.AnalysisResult analysisResult;
   22.62 -    private SymbolTable symbolTable;
   22.63 -    private int codeTemplateOffset = -1;
   22.64 -
   22.65 -    public PythonParserResult(PythonTree tree, @NonNull Snapshot snapshot) {
   22.66 -        super(snapshot);
   22.67 -        this.root = tree;
   22.68 -        this.errors = new LinkedList<>();
   22.69 -    }
   22.70 -
   22.71 -    public PythonTree getRoot() {
   22.72 -        return root;
   22.73 -    }
   22.74 -
   22.75 -    @Override
   22.76 -    public List<? extends Error> getDiagnostics() {
   22.77 -        return errors;
   22.78 -    }
   22.79 -
   22.80 -    @Override
   22.81 -    protected void invalidate() {
   22.82 -    }
   22.83 -
   22.84 -    public void setErrors(List<? extends Error> errors) {
   22.85 -        this.errors.clear();
   22.86 -        this.errors.addAll(errors);
   22.87 -    }
   22.88 -    
   22.89 -    /**
   22.90 -     * Set the range of source that was sanitized, if any.
   22.91 -     */
   22.92 -    void setSanitized(PythonParser.Sanitize sanitized, OffsetRange sanitizedRange, String sanitizedContents) {
   22.93 -        this.sanitized = sanitized;
   22.94 -        this.sanitizedRange = sanitizedRange;
   22.95 -        this.sanitizedContents = sanitizedContents;
   22.96 -        if (sanitizedContents == null || sanitizedRange == OffsetRange.NONE) {
   22.97 -            this.sanitized = Sanitize.NONE;
   22.98 -        }
   22.99 -    }
  22.100 -
  22.101 -    public PythonParser.Sanitize getSanitized() {
  22.102 -        return sanitized;
  22.103 -    }
  22.104 -
  22.105 -    /**
  22.106 -     * Return whether the source code for the parse result was "cleaned"
  22.107 -     * or "sanitized" (modified to reduce chance of parser errors) or not.
  22.108 -     * This method returns OffsetRange.NONE if the source was not sanitized,
  22.109 -     * otherwise returns the actual sanitized range.
  22.110 -     */
  22.111 -    public OffsetRange getSanitizedRange() {
  22.112 -        return sanitizedRange;
  22.113 -    }
  22.114 -
  22.115 -    public SymbolTable getSymbolTable() {
  22.116 -        if (symbolTable == null) {
  22.117 -            symbolTable = new SymbolTable(root, getSnapshot().getSource().getFileObject());
  22.118 -        }
  22.119 -
  22.120 -        return symbolTable;
  22.121 -    }
  22.122 -
  22.123 -    public String getSanitizedContents() {
  22.124 -        return sanitizedContents;
  22.125 -    }
  22.126 -
  22.127 -    public String getSource() {
  22.128 -        return source;
  22.129 -    }
  22.130 -
  22.131 -    public void setSource(String source) {
  22.132 -        this.source = source;
  22.133 -    }
  22.134 -
  22.135 -    /**
  22.136 -     * @return the codeTemplateOffset
  22.137 -     */
  22.138 -    public int getCodeTemplateOffset() {
  22.139 -        return codeTemplateOffset;
  22.140 -    }
  22.141 -
  22.142 -    /**
  22.143 -     * @param codeTemplateOffset the codeTemplateOffset to set
  22.144 -     */
  22.145 -    public void setCodeTemplateOffset(int codeTemplateOffset) {
  22.146 -        this.codeTemplateOffset = codeTemplateOffset;
  22.147 -    }
  22.148 -
  22.149 -    public void addError(Error e) {
  22.150 -        errors.add(e);
  22.151 -    }
  22.152 -
  22.153 -    public boolean isValid() {
  22.154 -        return errors.isEmpty();
  22.155 -    }
  22.156 -}
    23.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonSemanticHighlighter.java	Sat Sep 12 23:03:15 2015 -0700
    23.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonSemanticHighlighter.java	Sun Sep 13 11:47:42 2015 +0200
    23.3 @@ -30,6 +30,8 @@
    23.4   */
    23.5  package org.netbeans.modules.python.editor;
    23.6  
    23.7 +import org.netbeans.modules.python.source.PythonParserResult;
    23.8 +import org.netbeans.modules.python.source.PythonAstUtils;
    23.9  import java.util.EnumSet;
   23.10  import java.util.HashMap;
   23.11  import java.util.Map;
   23.12 @@ -37,12 +39,10 @@
   23.13  import org.netbeans.modules.csl.api.ColoringAttributes;
   23.14  import org.netbeans.modules.csl.api.OffsetRange;
   23.15  import org.netbeans.modules.csl.api.SemanticAnalyzer;
   23.16 -import org.netbeans.modules.csl.spi.ParserResult;
   23.17 -import org.netbeans.modules.parsing.spi.Parser.Result;
   23.18  import org.netbeans.modules.parsing.spi.Scheduler;
   23.19  import org.netbeans.modules.parsing.spi.SchedulerEvent;
   23.20 -import org.netbeans.modules.python.editor.scopes.ScopeInfo;
   23.21 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
   23.22 +import org.netbeans.modules.python.source.scopes.ScopeInfo;
   23.23 +import org.netbeans.modules.python.source.scopes.SymbolTable;
   23.24  import org.openide.util.Exceptions;
   23.25  import org.python.antlr.PythonTree;
   23.26  import org.python.antlr.Visitor;
    24.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonStructureItem.java	Sat Sep 12 23:03:15 2015 -0700
    24.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.3 @@ -1,195 +0,0 @@
    24.4 -/*
    24.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    24.6 - *
    24.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    24.8 - *
    24.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   24.10 - * Other names may be trademarks of their respective owners.
   24.11 - *
   24.12 - * The contents of this file are subject to the terms of either the GNU
   24.13 - * General Public License Version 2 only ("GPL") or the Common
   24.14 - * Development and Distribution License("CDDL") (collectively, the
   24.15 - * "License"). You may not use this file except in compliance with the
   24.16 - * License. You can obtain a copy of the License at
   24.17 - * http://www.netbeans.org/cddl-gplv2.html
   24.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   24.19 - * specific language governing permissions and limitations under the
   24.20 - * License.  When distributing the software, include this License Header
   24.21 - * Notice in each file and include the License file at
   24.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   24.23 - * particular file as subject to the "Classpath" exception as provided
   24.24 - * by Oracle in the GPL Version 2 section of the License file that
   24.25 - * accompanied this code. If applicable, add the following below the
   24.26 - * License Header, with the fields enclosed by brackets [] replaced by
   24.27 - * your own identifying information:
   24.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   24.29 - *
   24.30 - * Contributor(s):
   24.31 - *
   24.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   24.33 - */
   24.34 -package org.netbeans.modules.python.editor;
   24.35 -
   24.36 -import java.util.ArrayList;
   24.37 -import java.util.Collections;
   24.38 -import java.util.List;
   24.39 -import javax.swing.ImageIcon;
   24.40 -import org.netbeans.modules.csl.api.ElementHandle;
   24.41 -import org.netbeans.modules.csl.api.ElementKind;
   24.42 -import org.netbeans.modules.csl.api.HtmlFormatter;
   24.43 -import org.netbeans.modules.csl.api.Modifier;
   24.44 -import org.netbeans.modules.csl.api.StructureItem;
   24.45 -import org.netbeans.modules.python.editor.elements.AstElement;
   24.46 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
   24.47 -import org.openide.util.ImageUtilities;
   24.48 -import org.python.antlr.PythonTree;
   24.49 -import org.python.antlr.ast.ClassDef;
   24.50 -import org.python.antlr.ast.FunctionDef;
   24.51 -
   24.52 -public final class PythonStructureItem extends AstElement implements StructureItem {
   24.53 -    private List<PythonStructureItem> children;
   24.54 -    private PythonStructureItem parent;
   24.55 -
   24.56 -    public PythonStructureItem(SymbolTable scopes, ClassDef def) {
   24.57 -        this(scopes, def, def.getInternalName(), ElementKind.CLASS);
   24.58 -    }
   24.59 -
   24.60 -    public PythonStructureItem(SymbolTable scopes, FunctionDef def) {
   24.61 -        this(scopes, def, def.getInternalName(), ElementKind.METHOD);
   24.62 -        if ("__init__".equals(name)) { // NOI18N
   24.63 -            kind = ElementKind.CONSTRUCTOR;
   24.64 -        }
   24.65 -    }
   24.66 -    
   24.67 -    public PythonStructureItem(SymbolTable scopes, PythonTree node, String name, ElementKind kind) {
   24.68 -        super(scopes, node, name, kind);
   24.69 -        this.node = node;
   24.70 -        this.name = name;
   24.71 -        this.kind = kind;
   24.72 -    }
   24.73 -
   24.74 -    void add(PythonStructureItem child) {
   24.75 -        if (children == null) {
   24.76 -            children = new ArrayList<>();
   24.77 -        }
   24.78 -        children.add(child);
   24.79 -        child.parent = this;
   24.80 -    }
   24.81 -
   24.82 -    @Override
   24.83 -    public String getSortText() {
   24.84 -        return name;
   24.85 -    }
   24.86 -
   24.87 -    @Override
   24.88 -    public String getHtml(HtmlFormatter formatter) {
   24.89 -        formatter.appendText(name);
   24.90 -        if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
   24.91 -            FunctionDef def = (FunctionDef)node;
   24.92 -            List<String> params = PythonAstUtils.getParameters(def);
   24.93 -            if (params.size() > 0) {
   24.94 -                boolean isFirst = true;
   24.95 -                formatter.appendHtml("(");
   24.96 -                formatter.parameters(true);
   24.97 -                for (String param : params) {
   24.98 -                    if (isFirst) {
   24.99 -                        isFirst = false;
  24.100 -                    } else {
  24.101 -                        formatter.appendText(",");
  24.102 -                    }
  24.103 -                    formatter.appendText(param);
  24.104 -                }
  24.105 -                formatter.parameters(false);
  24.106 -                formatter.appendHtml(")");
  24.107 -            }
  24.108 -        }
  24.109 -        return formatter.getText();
  24.110 -    }
  24.111 -
  24.112 -    @Override
  24.113 -    public ElementHandle getElementHandle() {
  24.114 -        return null;
  24.115 -    }
  24.116 -
  24.117 -    @Override
  24.118 -    public boolean isLeaf() {
  24.119 -        return children == null;
  24.120 -    }
  24.121 -
  24.122 -    @Override
  24.123 -    public List<? extends StructureItem> getNestedItems() {
  24.124 -        return children == null ? Collections.<StructureItem>emptyList() : children;
  24.125 -    }
  24.126 -
  24.127 -    @Override
  24.128 -    public long getPosition() {
  24.129 -        return node.getCharStartIndex();
  24.130 -    }
  24.131 -
  24.132 -    @Override
  24.133 -    public long getEndPosition() {
  24.134 -        return node.getCharStopIndex();
  24.135 -    }
  24.136 -
  24.137 -    @Override
  24.138 -    public ImageIcon getCustomIcon() {
  24.139 -        if (kind == ElementKind.CLASS && getModifiers().contains(Modifier.PRIVATE)) {
  24.140 -            // GSF doesn't automatically handle icons on private classes, so I have to
  24.141 -            // work around that here
  24.142 -            return ImageUtilities.loadImageIcon("org/netbeans/modules/python/editor/resources/private-class.png", false); //NOI18N
  24.143 -        }
  24.144 -
  24.145 -        return null;
  24.146 -    }
  24.147 -
  24.148 -    @Override
  24.149 -    public Object getSignature() {
  24.150 -        if ((kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) && parent != null &&
  24.151 -                parent.kind == ElementKind.CLASS) {
  24.152 -            return parent.name + "." + name;
  24.153 -        }
  24.154 -        return super.getSignature();
  24.155 -    }
  24.156 -
  24.157 -    @Override
  24.158 -    public boolean equals(Object obj) {
  24.159 -        if (obj == null) {
  24.160 -            return false;
  24.161 -        }
  24.162 -        if (getClass() != obj.getClass()) {
  24.163 -            return false;
  24.164 -        }
  24.165 -        final PythonStructureItem other = (PythonStructureItem)obj;
  24.166 -        if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
  24.167 -            return false;
  24.168 -        }
  24.169 -        if (this.kind != other.kind) {
  24.170 -            return false;
  24.171 -        }
  24.172 -        if (this.getModifiers() != other.getModifiers() && (this.modifiers == null || !this.modifiers.equals(other.modifiers))) {
  24.173 -            return false;
  24.174 -        }
  24.175 -
  24.176 -        if ((kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) && node != null && other.node != null) {
  24.177 -            FunctionDef def = (FunctionDef)node;
  24.178 -            List<String> params = PythonAstUtils.getParameters(def);
  24.179 -            List<String> otherParams = PythonAstUtils.getParameters((FunctionDef)other.node);
  24.180 -            if (!params.equals((otherParams))) {
  24.181 -                return false;
  24.182 -            }
  24.183 -        }
  24.184 -
  24.185 -//        if (this.getNestedItems().size() != other.getNestedItems().size()) {
  24.186 -//            return false;
  24.187 -//        }
  24.188 -//
  24.189 -        return true;
  24.190 -    }
  24.191 -
  24.192 -    @Override
  24.193 -    public int hashCode() {
  24.194 -        int hash = 7;
  24.195 -        hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0);
  24.196 -        return hash;
  24.197 -    }
  24.198 -}
    25.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonStructureScanner.java	Sat Sep 12 23:03:15 2015 -0700
    25.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.3 @@ -1,274 +0,0 @@
    25.4 -/*
    25.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    25.6 - *
    25.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    25.8 - *
    25.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   25.10 - * Other names may be trademarks of their respective owners.
   25.11 - *
   25.12 - * The contents of this file are subject to the terms of either the GNU
   25.13 - * General Public License Version 2 only ("GPL") or the Common
   25.14 - * Development and Distribution License("CDDL") (collectively, the
   25.15 - * "License"). You may not use this file except in compliance with the
   25.16 - * License. You can obtain a copy of the License at
   25.17 - * http://www.netbeans.org/cddl-gplv2.html
   25.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   25.19 - * specific language governing permissions and limitations under the
   25.20 - * License.  When distributing the software, include this License Header
   25.21 - * Notice in each file and include the License file at
   25.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   25.23 - * particular file as subject to the "Classpath" exception as provided
   25.24 - * by Oracle in the GPL Version 2 section of the License file that
   25.25 - * accompanied this code. If applicable, add the following below the
   25.26 - * License Header, with the fields enclosed by brackets [] replaced by
   25.27 - * your own identifying information:
   25.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   25.29 - *
   25.30 - * Contributor(s):
   25.31 - *
   25.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   25.33 - */
   25.34 -package org.netbeans.modules.python.editor;
   25.35 -
   25.36 -import java.util.ArrayList;
   25.37 -import java.util.Collections;
   25.38 -import java.util.HashMap;
   25.39 -import java.util.List;
   25.40 -import java.util.Map;
   25.41 -import javax.swing.text.BadLocationException;
   25.42 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   25.43 -import org.netbeans.editor.BaseDocument;
   25.44 -import org.netbeans.editor.Utilities;
   25.45 -import org.netbeans.modules.csl.api.ElementKind;
   25.46 -import org.netbeans.modules.csl.api.OffsetRange;
   25.47 -import org.netbeans.modules.csl.api.StructureItem;
   25.48 -import org.netbeans.modules.csl.api.StructureScanner;
   25.49 -import org.netbeans.modules.csl.api.StructureScanner.Configuration;
   25.50 -import org.netbeans.modules.csl.spi.GsfUtilities;
   25.51 -import org.netbeans.modules.csl.spi.ParserResult;
   25.52 -import org.netbeans.modules.python.editor.scopes.ScopeInfo;
   25.53 -import org.netbeans.modules.python.editor.scopes.SymInfo;
   25.54 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
   25.55 -import org.openide.util.Exceptions;
   25.56 -import org.python.antlr.PythonTree;
   25.57 -import org.python.antlr.Visitor;
   25.58 -import org.python.antlr.ast.ClassDef;
   25.59 -import org.python.antlr.ast.FunctionDef;
   25.60 -import org.python.antlr.ast.Str;
   25.61 -
   25.62 -/**
   25.63 - * This class analyzes the structure of a Python parse tree
   25.64 - * and infers structure (navigation items, folds, etc.)
   25.65 - *
   25.66 - * @author Tor Norbye
   25.67 - */
   25.68 -public class PythonStructureScanner implements StructureScanner {
   25.69 -    
   25.70 -    public static AnalysisResult analyze(PythonParserResult info) {
   25.71 -        AnalysisResult analysisResult = new AnalysisResult();
   25.72 -
   25.73 -        PythonTree root = PythonAstUtils.getRoot(info);
   25.74 -        if (root != null) {
   25.75 -            SymbolTable scopes = PythonAstUtils.getParseResult(info).getSymbolTable();
   25.76 -            StructureVisitor visitor = new StructureVisitor(scopes);
   25.77 -            try {
   25.78 -                visitor.visit(root);
   25.79 -                analysisResult.setElements(visitor.getRoots());
   25.80 -            } catch (Exception ex) {
   25.81 -                Exceptions.printStackTrace(ex);
   25.82 -            }
   25.83 -        }
   25.84 -
   25.85 -        return analysisResult;
   25.86 -    }
   25.87 -
   25.88 -    @Override
   25.89 -    public List<? extends StructureItem> scan(ParserResult info) {
   25.90 -        PythonParserResult parseResult = PythonAstUtils.getParseResult(info);
   25.91 -        if (parseResult == null) {
   25.92 -            return Collections.emptyList();
   25.93 -        }
   25.94 -
   25.95 -        return getStructure(parseResult).getElements();
   25.96 -    }
   25.97 -    
   25.98 -    public PythonStructureScanner.AnalysisResult getStructure(PythonParserResult result) {
   25.99 -        // TODO Cache ! (Used to be in PythonParserResult
  25.100 -        AnalysisResult analysisResult = PythonStructureScanner.analyze(result);
  25.101 -        return analysisResult;
  25.102 -    }
  25.103 -
  25.104 -    @Override
  25.105 -    public Map<String, List<OffsetRange>> folds(ParserResult info) {
  25.106 -        PythonParserResult result = PythonAstUtils.getParseResult(info);
  25.107 -        PythonTree root = PythonAstUtils.getRoot(result);
  25.108 -        if (root == null) {
  25.109 -            return Collections.emptyMap();
  25.110 -        }
  25.111 -
  25.112 -        //TranslatedSource source = result.getTranslatedSource();
  25.113 -        //
  25.114 -        //AnalysisResult ar = result.getStructure();
  25.115 -        //
  25.116 -        //List<?extends AstElement> elements = ar.getElements();
  25.117 -        //List<StructureItem> itemList = new ArrayList<StructureItem>(elements.size());
  25.118 -
  25.119 -        BaseDocument doc = GsfUtilities.getDocument(result.getSnapshot().getSource().getFileObject(), false);
  25.120 -        if (doc != null) {
  25.121 -            try {
  25.122 -                doc.readLock(); // For Utilities.getRowEnd() access
  25.123 -                FoldVisitor visitor = new FoldVisitor((PythonParserResult) info, doc);
  25.124 -                visitor.visit(root);
  25.125 -                List<OffsetRange> codeBlocks = visitor.getCodeBlocks();
  25.126 -
  25.127 -                Map<String, List<OffsetRange>> folds = new HashMap<>();
  25.128 -                folds.put("codeblocks", codeBlocks); // NOI18N
  25.129 -
  25.130 -                return folds;
  25.131 -            } catch (Exception ex) {
  25.132 -                Exceptions.printStackTrace(ex);
  25.133 -            } finally {
  25.134 -                doc.readUnlock();
  25.135 -            }
  25.136 -        }
  25.137 -        return Collections.emptyMap();
  25.138 -    }
  25.139 -
  25.140 -    @Override
  25.141 -    public Configuration getConfiguration() {
  25.142 -        return new Configuration(true, true, -1);
  25.143 -    }
  25.144 -
  25.145 -    private static class FoldVisitor extends Visitor {
  25.146 -        private List<OffsetRange> codeBlocks = new ArrayList<>();
  25.147 -        private PythonParserResult info;
  25.148 -        private BaseDocument doc;
  25.149 -
  25.150 -        private FoldVisitor(PythonParserResult info, BaseDocument doc) {
  25.151 -            this.info = info;
  25.152 -            this.doc = doc;
  25.153 -        }
  25.154 -
  25.155 -        private void addFoldRange(PythonTree node) {
  25.156 -            OffsetRange astRange = PythonAstUtils.getRange(node);
  25.157 -
  25.158 -            OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
  25.159 -            if (lexRange != OffsetRange.NONE) {
  25.160 -                try {
  25.161 -                    int startRowEnd = Utilities.getRowEnd(doc, lexRange.getStart());
  25.162 -                    if (startRowEnd < lexRange.getEnd()) {
  25.163 -                        codeBlocks.add(new OffsetRange(startRowEnd, lexRange.getEnd()));
  25.164 -                    }
  25.165 -                } catch (BadLocationException ex) {
  25.166 -                    Exceptions.printStackTrace(ex);
  25.167 -                }
  25.168 -            }
  25.169 -        }
  25.170 -
  25.171 -        @Override
  25.172 -        public Object visitClassDef(ClassDef node) throws Exception {
  25.173 -            addFoldRange(node);
  25.174 -
  25.175 -            return super.visitClassDef(node);
  25.176 -        }
  25.177 -
  25.178 -        @Override
  25.179 -        public Object visitFunctionDef(FunctionDef node) throws Exception {
  25.180 -            addFoldRange(node);
  25.181 -
  25.182 -            return super.visitFunctionDef(node);
  25.183 -        }
  25.184 -
  25.185 -        @Override
  25.186 -        public Object visitStr(Str node) throws Exception {
  25.187 -            addFoldRange(node);
  25.188 -            return super.visitStr(node);
  25.189 -        }
  25.190 -
  25.191 -        public List<OffsetRange> getCodeBlocks() {
  25.192 -            return codeBlocks;
  25.193 -        }
  25.194 -    }
  25.195 -
  25.196 -    private static class StructureVisitor extends Visitor {
  25.197 -        List<PythonStructureItem> roots = new ArrayList<>();
  25.198 -        List<PythonStructureItem> stack = new ArrayList<>();
  25.199 -        SymbolTable scopes;
  25.200 -
  25.201 -        StructureVisitor(SymbolTable scopes) {
  25.202 -            this.scopes = scopes;
  25.203 -        }
  25.204 -
  25.205 -        private List<PythonStructureItem> getRoots() {
  25.206 -            return roots;
  25.207 -        }
  25.208 -
  25.209 -        @Override
  25.210 -        public Object visitClassDef(ClassDef def) throws Exception {
  25.211 -            PythonStructureItem item = new PythonStructureItem(scopes, def);
  25.212 -            add(item);
  25.213 -
  25.214 -            ScopeInfo scope = scopes.getScopeInfo(def);
  25.215 -            if (scope != null && scope.attributes.size() > 0) {
  25.216 -                for (Map.Entry<String, SymInfo> entry : scope.attributes.entrySet()) {
  25.217 -                    // TODO - sort these puppies? Right now their natural order will be
  25.218 -                    // random (hashkey dependent) instead of by source position or by name
  25.219 -                    SymInfo sym = entry.getValue();
  25.220 -                    if (sym.node != null) {
  25.221 -                        String name = entry.getKey();
  25.222 -                        PythonStructureItem attribute = new PythonStructureItem(scopes, sym.node, name, ElementKind.ATTRIBUTE);
  25.223 -                        item.add(attribute);
  25.224 -                    }
  25.225 -                }
  25.226 -            }
  25.227 -
  25.228 -            stack.add(item);
  25.229 -            Object result = super.visitClassDef(def);
  25.230 -            stack.remove(stack.size() - 1);
  25.231 -
  25.232 -            return result;
  25.233 -        }
  25.234 -
  25.235 -        @Override
  25.236 -        public Object visitFunctionDef(FunctionDef def) throws Exception {
  25.237 -            PythonStructureItem item = new PythonStructureItem(scopes, def);
  25.238 -
  25.239 -            add(item);
  25.240 -            stack.add(item);
  25.241 -            Object result = super.visitFunctionDef(def);
  25.242 -            stack.remove(stack.size() - 1);
  25.243 -
  25.244 -            return result;
  25.245 -        }
  25.246 -
  25.247 -        private void add(PythonStructureItem child) {
  25.248 -            PythonStructureItem parent = stack.size() > 0 ? stack.get(stack.size() - 1) : null;
  25.249 -            if (parent == null) {
  25.250 -                roots.add(child);
  25.251 -            } else {
  25.252 -                parent.add(child);
  25.253 -            }
  25.254 -        }
  25.255 -    }
  25.256 -
  25.257 -    public static class AnalysisResult {
  25.258 -        //private List<?extends AstElement> elements;
  25.259 -        private List<PythonStructureItem> elements;
  25.260 -
  25.261 -        private AnalysisResult() {
  25.262 -        }
  25.263 -
  25.264 -        //private void setElements(List<?extends AstElement> elements) {
  25.265 -        private void setElements(List<PythonStructureItem> elements) {
  25.266 -            this.elements = elements;
  25.267 -        }
  25.268 -
  25.269 -        //public List<?extends AstElement> getElements() {
  25.270 -        public List<PythonStructureItem> getElements() {
  25.271 -            if (elements == null) {
  25.272 -                return Collections.emptyList();
  25.273 -            }
  25.274 -            return elements;
  25.275 -        }
  25.276 -    }
  25.277 -}
    26.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonTypeAnalyzer.java	Sat Sep 12 23:03:15 2015 -0700
    26.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonTypeAnalyzer.java	Sun Sep 13 11:47:42 2015 +0200
    26.3 @@ -30,6 +30,9 @@
    26.4   */
    26.5  package org.netbeans.modules.python.editor;
    26.6  
    26.7 +import org.netbeans.modules.python.source.PythonIndex;
    26.8 +import org.netbeans.modules.python.source.PythonAstUtils;
    26.9 +import org.netbeans.modules.python.source.PythonParserResult;
   26.10  import java.util.Collections;
   26.11  import java.util.HashMap;
   26.12  import java.util.LinkedList;
   26.13 @@ -39,9 +42,9 @@
   26.14  import org.netbeans.api.lexer.TokenSequence;
   26.15  import org.netbeans.editor.BaseDocument;
   26.16  import org.netbeans.modules.csl.api.OffsetRange;
   26.17 -import org.netbeans.modules.python.editor.lexer.PythonCommentTokenId;
   26.18 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   26.19 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   26.20 +import org.netbeans.modules.python.source.lexer.PythonCommentTokenId;
   26.21 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
   26.22 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
   26.23  import org.openide.filesystems.FileObject;
   26.24  import org.openide.util.Exceptions;
   26.25  import org.python.antlr.PythonTree;
    27.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonUtils.java	Sat Sep 12 23:03:15 2015 -0700
    27.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.3 @@ -1,529 +0,0 @@
    27.4 -/*
    27.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    27.6 - *
    27.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    27.8 - *
    27.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   27.10 - * Other names may be trademarks of their respective owners.
   27.11 - *
   27.12 - * The contents of this file are subject to the terms of either the GNU
   27.13 - * General Public License Version 2 only ("GPL") or the Common
   27.14 - * Development and Distribution License("CDDL") (collectively, the
   27.15 - * "License"). You may not use this file except in compliance with the
   27.16 - * License. You can obtain a copy of the License at
   27.17 - * http://www.netbeans.org/cddl-gplv2.html
   27.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   27.19 - * specific language governing permissions and limitations under the
   27.20 - * License.  When distributing the software, include this License Header
   27.21 - * Notice in each file and include the License file at
   27.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   27.23 - * particular file as subject to the "Classpath" exception as provided
   27.24 - * by Oracle in the GPL Version 2 section of the License file that
   27.25 - * accompanied this code. If applicable, add the following below the
   27.26 - * License Header, with the fields enclosed by brackets [] replaced by
   27.27 - * your own identifying information:
   27.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   27.29 - *
   27.30 - * Contributor(s):
   27.31 - *
   27.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   27.33 - */
   27.34 -package org.netbeans.modules.python.editor;
   27.35 -
   27.36 -import java.util.Comparator;
   27.37 -import java.util.List;
   27.38 -import javax.swing.text.Document;
   27.39 -import org.netbeans.api.annotations.common.NonNull;
   27.40 -import org.netbeans.api.project.FileOwnerQuery;
   27.41 -import org.netbeans.api.project.Project;
   27.42 -import org.netbeans.api.project.ProjectUtils;
   27.43 -import org.netbeans.api.project.SourceGroup;
   27.44 -import org.netbeans.api.project.Sources;
   27.45 -import org.netbeans.lib.editor.codetemplates.api.CodeTemplate;
   27.46 -import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager;
   27.47 -import org.netbeans.modules.python.api.PythonMIMEResolver;
   27.48 -import org.netbeans.modules.python.api.PythonPlatform;
   27.49 -import org.netbeans.modules.python.api.PythonPlatformManager;
   27.50 -import org.openide.filesystems.FileObject;
   27.51 -import org.openide.filesystems.FileUtil;
   27.52 -import org.openide.util.NbBundle;
   27.53 -import org.python.antlr.PythonTree;
   27.54 -import org.python.antlr.ast.Attribute;
   27.55 -import org.python.antlr.ast.Name;
   27.56 -
   27.57 -/**
   27.58 - *
   27.59 - * @author Tor Norbye
   27.60 - */
   27.61 -public class PythonUtils {
   27.62 -    public static boolean canContainPython(FileObject f) {
   27.63 -        String mimeType = f.getMIMEType();
   27.64 -        return PythonMIMEResolver.PYTHON_MIME_TYPE.equals(mimeType);
   27.65 -    // TODO:       "text/x-yaml".equals(mimeType) ||  // NOI18N
   27.66 -    // RubyInstallation.RHTML_MIME_TYPE.equals(mimeType);
   27.67 -    }
   27.68 -
   27.69 -    public static boolean isPythonFile(FileObject f) {
   27.70 -        return PythonMIMEResolver.PYTHON_MIME_TYPE.equals(f.getMIMEType());
   27.71 -    }
   27.72 -
   27.73 -    public static boolean isRstFile(FileObject f) {
   27.74 -        return "rst".equals(f.getExt()); // NOI18N
   27.75 -    }
   27.76 -
   27.77 -    public static boolean isPythonDocument(Document doc) {
   27.78 -        String mimeType = (String)doc.getProperty("mimeType"); // NOI18N
   27.79 -
   27.80 -        return PythonMIMEResolver.PYTHON_MIME_TYPE.equals(mimeType);
   27.81 -    }
   27.82 -    public static final String DOT__INIT__ = ".__init__"; // NOI18N
   27.83 -
   27.84 -    // From PythonProjectType
   27.85 -    public static final String SOURCES_TYPE_PYTHON = "python"; // NOI18N
   27.86 -
   27.87 -    // Cache
   27.88 -    private static FileObject prevParent;
   27.89 -    private static String prevRootUrl;
   27.90 -
   27.91 -    /**
   27.92 -     * Produce the module name (including packages) for a given python source file.
   27.93 -     * 
   27.94 -     * @param fo The source file (can be null, if file is not))
   27.95 -     * @param file The parser file (can be null, if fo is not).
   27.96 -     * @param fileName The filename (basename only)
   27.97 -     * @param projectRelativeName If non null, the path from the project root down to this file
   27.98 -     * @return A string for the full package module name
   27.99 -     */
  27.100 -    public static String getModuleName(@NonNull FileObject fo) {
  27.101 -
  27.102 -        // TODO - use PythonPlatform's library roots!
  27.103 -
  27.104 -        String module = fo.getName();
  27.105 -
  27.106 -        // First see if we're on the load path for the platform, and if so,
  27.107 -        // use that as the base
  27.108 -        // TODO - look up platform for the current search context instead of all platforms!!
  27.109 -        if (fo.getParent() != prevParent) {
  27.110 -            prevRootUrl = null;
  27.111 -            prevParent = fo.getParent();
  27.112 -        }
  27.113 -
  27.114 -        String url = fo.toURL().toExternalForm();
  27.115 -        if (prevRootUrl == null) {
  27.116 -            boolean found = false;
  27.117 -            PythonPlatformManager manager = PythonPlatformManager.getInstance();
  27.118 -
  27.119 -            PlatformSearch:
  27.120 -            for (String name : manager.getPlatformList()) {
  27.121 -                PythonPlatform platform = manager.getPlatform(name);
  27.122 -                if (platform != null) {
  27.123 -                    List<FileObject> unique = platform.getUniqueLibraryRoots();
  27.124 -                    for (FileObject root : unique) {
  27.125 -                        if (FileUtil.isParentOf(root, fo)) {
  27.126 -                            for (FileObject r : platform.getLibraryRoots()) {
  27.127 -                                if (FileUtil.isParentOf(r, fo)) {
  27.128 -                                    // See if the folder itself contains
  27.129 -                                    // an __init__.py file - if it does,
  27.130 -                                    // then include the directory itself
  27.131 -                                    // in the package name.
  27.132 -                                    if (r.getFileObject("__init__.py") != null) { // NOI18N
  27.133 -                                        r = r.getParent();
  27.134 -                                    }
  27.135 -
  27.136 -                                    prevRootUrl = r.toURL().toExternalForm();
  27.137 -                                    found = true;
  27.138 -                                    break PlatformSearch;
  27.139 -                                }
  27.140 -                            }
  27.141 -                            break PlatformSearch;
  27.142 -                        }
  27.143 -                    }
  27.144 -                }
  27.145 -            }
  27.146 -
  27.147 -            if (!found) {
  27.148 -                Project project = FileOwnerQuery.getOwner(fo);
  27.149 -                if (project != null) {
  27.150 -                    Sources source = ProjectUtils.getSources(project);
  27.151 -                    // Look up the source path
  27.152 -                    SourceGroup[] sourceGroups = source.getSourceGroups(SOURCES_TYPE_PYTHON);
  27.153 -                    for (SourceGroup group : sourceGroups) {
  27.154 -                        FileObject folder = group.getRootFolder();
  27.155 -                        if (FileUtil.isParentOf(folder, fo)) {
  27.156 -                            // See if the folder itself contains
  27.157 -                            // an __init__.py file - if it does,
  27.158 -                            // then include the directory itself
  27.159 -                            // in the package name.
  27.160 -                            if (folder.getFileObject("__init__.py") != null) { // NOI18N
  27.161 -                                folder = folder.getParent();
  27.162 -                            }
  27.163 -
  27.164 -                            prevRootUrl = folder.toURL().toExternalForm();
  27.165 -                            break;
  27.166 -                        }
  27.167 -                    }
  27.168 -                }
  27.169 -            }
  27.170 -        }
  27.171 -
  27.172 -        if (prevRootUrl != null) {
  27.173 -            module = url.substring(prevRootUrl.length());
  27.174 -            if (module.startsWith("/")) {
  27.175 -                module = module.substring(1);
  27.176 -            }
  27.177 -        }
  27.178 -
  27.179 -        // Strip off .y extension
  27.180 -        if (module.endsWith(".py")) { // NOI18N
  27.181 -            module = module.substring(0, module.length() - 3);
  27.182 -        }
  27.183 -
  27.184 -        if (module.indexOf('/') != -1) {
  27.185 -            module = module.replace('/', '.');
  27.186 -        }
  27.187 -
  27.188 -        if (module.endsWith(DOT__INIT__)) {
  27.189 -            module = module.substring(0, module.length() - DOT__INIT__.length());
  27.190 -        }
  27.191 -
  27.192 -        return module;
  27.193 -    }
  27.194 -
  27.195 -    // Keywords - according to http://docs.python.org/ref/keywords.html
  27.196 -    static final String[] PYTHON_KEYWORDS = new String[]{
  27.197 -        "and", // NOI18N
  27.198 -        "as", // NOI18N
  27.199 -        "assert", // NOI18N
  27.200 -        "break", // NOI18N
  27.201 -        "class", // NOI18N
  27.202 -        "continue", // NOI18N
  27.203 -        "def", // NOI18N
  27.204 -        "del", // NOI18N
  27.205 -        "elif", // NOI18N
  27.206 -        "else", // NOI18N
  27.207 -        "except", // NOI18N
  27.208 -        "exec", // NOI18N
  27.209 -        "finally", // NOI18N
  27.210 -        "for", // NOI18N
  27.211 -        "from", // NOI18N
  27.212 -        "global", // NOI18N
  27.213 -        "if", // NOI18N
  27.214 -        "import", // NOI18N
  27.215 -        "in", // NOI18N
  27.216 -        "is", // NOI18N
  27.217 -        "lambda", // NOI18N
  27.218 -        "not", // NOI18N
  27.219 -        "or", // NOI18N
  27.220 -        "pass", // NOI18N
  27.221 -        "print", // NOI18N
  27.222 -        "raise", // NOI18N
  27.223 -        "return", // NOI18N
  27.224 -        "try", // NOI18N
  27.225 -        "while", // NOI18N
  27.226 -        "with", // NOI18N
  27.227 -        "yield", // NOI18N
  27.228 -    };
  27.229 -
  27.230 -    public static boolean isPythonKeyword(String name) {
  27.231 -        for (String s : PYTHON_KEYWORDS) {
  27.232 -            if (s.equals(name)) {
  27.233 -                return true;
  27.234 -            }
  27.235 -        }
  27.236 -
  27.237 -        return false;
  27.238 -    }
  27.239 -
  27.240 -    /**
  27.241 -     * Return true iff the name is a class name
  27.242 -     * @param name The name
  27.243 -     * @param emptyDefault Whether empty or _ names should be considered a class name or not
  27.244 -     * @return True iff the name looks like a class name
  27.245 -     */
  27.246 -    public static boolean isClassName(String name, boolean emptyDefault) {
  27.247 -        if (name == null || name.length() == 0) {
  27.248 -            return emptyDefault;
  27.249 -        }
  27.250 -        if (name.startsWith("_") && name.length() > 1) {
  27.251 -            return Character.isUpperCase(name.charAt(1));
  27.252 -        }
  27.253 -
  27.254 -        return Character.isUpperCase(name.charAt(0));
  27.255 -    }
  27.256 -
  27.257 -    /**
  27.258 -     * Return true iff the name is a method name
  27.259 -     * @param name The name
  27.260 -     * @param emptyDefault Whether empty or _ names should be considered a class name or not
  27.261 -     * @return True iff the name looks like a method name
  27.262 -     */
  27.263 -    public static boolean isMethodName(String name, boolean emptyDefault) {
  27.264 -        if (name == null || name.length() == 0) {
  27.265 -            return emptyDefault;
  27.266 -        }
  27.267 -        if (name.startsWith("__") && name.length() > 2) {
  27.268 -            return Character.isLowerCase(name.charAt(2));
  27.269 -        }
  27.270 -        if (name.startsWith("_") && name.length() > 1) {
  27.271 -            return Character.isLowerCase(name.charAt(1));
  27.272 -        }
  27.273 -
  27.274 -        return Character.isLowerCase(name.charAt(0));
  27.275 -    }
  27.276 -
  27.277 -    public static String getCodeTemplate(CodeTemplateManager ctm, String abbrev, String textPrefix, String wrongTextPrefix) {
  27.278 -        String templateText = null;
  27.279 -        for (CodeTemplate t : ctm.getCodeTemplates()) {
  27.280 -            if (abbrev.equals(t.getAbbreviation())) {
  27.281 -                templateText = t.getParametrizedText();
  27.282 -                break;
  27.283 -            }
  27.284 -        }
  27.285 -        if (templateText == null) {
  27.286 -            for (CodeTemplate t : ctm.getCodeTemplates()) {
  27.287 -                String text = t.getParametrizedText();
  27.288 -                if (text.startsWith(textPrefix) && (wrongTextPrefix == null || !text.startsWith(wrongTextPrefix))) {
  27.289 -                    templateText = text;
  27.290 -                    break;
  27.291 -                }
  27.292 -            }
  27.293 -        }
  27.294 -
  27.295 -        return templateText;
  27.296 -    }
  27.297 -
  27.298 -    public static boolean isValidPythonClassName(String name) {
  27.299 -        if (isPythonKeyword(name)) {
  27.300 -            return false;
  27.301 -        }
  27.302 -
  27.303 -        if (name.trim().length() == 0) {
  27.304 -            return false;
  27.305 -        }
  27.306 -
  27.307 -        if (!Character.isUpperCase(name.charAt(0))) {
  27.308 -            return false;
  27.309 -        }
  27.310 -
  27.311 -        for (int i = 1; i < name.length(); i++) {
  27.312 -            char c = name.charAt(i);
  27.313 -            if (!Character.isJavaIdentifierPart(c)) {
  27.314 -                return false;
  27.315 -            }
  27.316 -
  27.317 -        }
  27.318 -
  27.319 -        return true;
  27.320 -    }
  27.321 -
  27.322 -    /** Is this name a valid operator name? */
  27.323 -    public static boolean isOperator(String name) {
  27.324 -        // TODO - update to Python
  27.325 -        if (name.length() == 0) {
  27.326 -            return false;
  27.327 -        }
  27.328 -
  27.329 -        switch (name.charAt(0)) {
  27.330 -        case '+':
  27.331 -            return name.equals("+") || name.equals("+@");
  27.332 -        case '-':
  27.333 -            return name.equals("-") || name.equals("-@");
  27.334 -        case '*':
  27.335 -            return name.equals("*") || name.equals("**");
  27.336 -        case '<':
  27.337 -            return name.equals("<") || name.equals("<<") || name.equals("<=") || name.equals("<=>");
  27.338 -        case '>':
  27.339 -            return name.equals(">") || name.equals(">>") || name.equals(">=");
  27.340 -        case '=':
  27.341 -            return name.equals("=") || name.equals("==") || name.equals("===") || name.equals("=~");
  27.342 -        case '!':
  27.343 -            return name.equals("!=") || name.equals("!~");
  27.344 -        case '&':
  27.345 -            return name.equals("&") || name.equals("&&");
  27.346 -        case '|':
  27.347 -            return name.equals("|") || name.equals("||");
  27.348 -        case '[':
  27.349 -            return name.equals("[]") || name.equals("[]=");
  27.350 -        case '%':
  27.351 -            return name.equals("%");
  27.352 -        case '/':
  27.353 -            return name.equals("/");
  27.354 -        case '~':
  27.355 -            return name.equals("~");
  27.356 -        case '^':
  27.357 -            return name.equals("^");
  27.358 -        case '`':
  27.359 -            return name.equals("`");
  27.360 -        default:
  27.361 -            return false;
  27.362 -        }
  27.363 -    }
  27.364 -
  27.365 -    public static boolean isValidPythonMethodName(String name) {
  27.366 -        if (isPythonKeyword(name)) {
  27.367 -            return false;
  27.368 -        }
  27.369 -
  27.370 -        if (name.trim().length() == 0) {
  27.371 -            return false;
  27.372 -        }
  27.373 -
  27.374 -        // TODO - allow operators
  27.375 -        if (isOperator(name)) {
  27.376 -            return true;
  27.377 -        }
  27.378 -
  27.379 -        if (Character.isUpperCase(name.charAt(0)) || Character.isWhitespace(name.charAt(0))) {
  27.380 -            return false;
  27.381 -        }
  27.382 -
  27.383 -        for (int i = 0; i < name.length(); i++) {
  27.384 -            char c = name.charAt(i);
  27.385 -            if (!(Character.isLetterOrDigit(c) || c == '_')) {
  27.386 -                return false;
  27.387 -            }
  27.388 -
  27.389 -        }
  27.390 -
  27.391 -        return true;
  27.392 -    }
  27.393 -
  27.394 -    public static boolean isValidPythonIdentifier(String name) {
  27.395 -        if (isPythonKeyword(name)) {
  27.396 -            return false;
  27.397 -        }
  27.398 -
  27.399 -        if (name.trim().length() == 0) {
  27.400 -            return false;
  27.401 -        }
  27.402 -
  27.403 -        for (int i = 0; i < name.length(); i++) {
  27.404 -            // Identifier char isn't really accurate - I can have a function named "[]" etc.
  27.405 -            // so just look for -obvious- mistakes
  27.406 -            if (Character.isWhitespace(name.charAt(i))) {
  27.407 -                return false;
  27.408 -            }
  27.409 -
  27.410 -        // TODO - make this more accurate, like the method validifier
  27.411 -        }
  27.412 -
  27.413 -        return true;
  27.414 -    }
  27.415 -
  27.416 -    /**
  27.417 -     * Ruby identifiers should consist of [a-zA-Z0-9_]
  27.418 -     * http://www.headius.com/rubyspec/index.php/Variables
  27.419 -     * <p>
  27.420 -     * This method also accepts the field/global chars
  27.421 -     * since it's unlikely
  27.422 -     */
  27.423 -    public static boolean isSafeIdentifierName(String name, int fromIndex) {
  27.424 -        int i = fromIndex;
  27.425 -        for (; i < name.length(); i++) {
  27.426 -            char c = name.charAt(i);
  27.427 -            if (!(c == '$' || c == '@' || c == ':')) {
  27.428 -                break;
  27.429 -            }
  27.430 -        }
  27.431 -        for (; i < name.length(); i++) {
  27.432 -            char c = name.charAt(i);
  27.433 -            if (!((c >= 'a' && c <= 'z') || (c == '_') ||
  27.434 -                    (c >= 'A' && c <= 'Z') ||
  27.435 -                    (c >= '0' && c <= '9') ||
  27.436 -                    (c == '?') || (c == '=') || (c == '!'))) { // Method suffixes; only allowed on the last line
  27.437 -
  27.438 -                if (isOperator(name)) {
  27.439 -                    return true;
  27.440 -                }
  27.441 -
  27.442 -                return false;
  27.443 -            }
  27.444 -        }
  27.445 -
  27.446 -        return true;
  27.447 -    }
  27.448 -
  27.449 -    /**
  27.450 -     * Return null if the given identifier name is valid, otherwise a localized
  27.451 -     * error message explaining the problem.
  27.452 -     */
  27.453 -    public static String getIdentifierWarning(String name, int fromIndex) {
  27.454 -        if (isSafeIdentifierName(name, fromIndex)) {
  27.455 -            return null;
  27.456 -        } else {
  27.457 -            return NbBundle.getMessage(PythonUtils.class, "UnsafeIdentifierName");
  27.458 -        }
  27.459 -    }
  27.460 -
  27.461 -    /** @todo Move into GsfUtilities after 6.5 */
  27.462 -    public static int getOffsetByLineCol(String source, int line, int col) {
  27.463 -        int offset = 0;
  27.464 -        for (int i = 0; i < line; i++) {
  27.465 -            offset = source.indexOf('\n', offset);
  27.466 -            if (offset == -1) {
  27.467 -                offset = source.length();
  27.468 -                break;
  27.469 -            }
  27.470 -            offset++;
  27.471 -        }
  27.472 -        if (col > 0) { // -1: invalid
  27.473 -            offset += col;
  27.474 -        }
  27.475 -
  27.476 -        return offset;
  27.477 -    }
  27.478 -    public static Comparator NAME_NODE_COMPARATOR = new Comparator<Name>() {
  27.479 -        @Override
  27.480 -        public int compare(Name n1, Name n2) {
  27.481 -            return n1.getInternalId().compareTo(n2.getInternalId());
  27.482 -        }
  27.483 -    };
  27.484 -    public static Comparator ATTRIBUTE_NAME_NODE_COMPARATOR = new Comparator<Object>() {
  27.485 -        @SuppressWarnings("unchecked")
  27.486 -        @Override
  27.487 -        public int compare(Object n1, Object n2) {
  27.488 -            String s1 = "";
  27.489 -            String s2 = "";
  27.490 -
  27.491 -            if (n1 instanceof Name) {
  27.492 -                s1 = ((Name)n1).getInternalId();
  27.493 -            } else if (n1 instanceof Attribute) {
  27.494 -                Attribute a = (Attribute)n1;
  27.495 -                String v = PythonAstUtils.getName(a.getInternalValue());
  27.496 -                if (v != null) {
  27.497 -                    s1 = a.getInternalAttr() + "." + v;
  27.498 -                } else {
  27.499 -                    s1 = a.getInternalAttr();
  27.500 -                }
  27.501 -            }
  27.502 -
  27.503 -            if (n2 instanceof Name) {
  27.504 -                s2 = ((Name)n2).getInternalId();
  27.505 -            } else if (n2 instanceof Attribute) {
  27.506 -                Attribute a = (Attribute)n2;
  27.507 -                String v = PythonAstUtils.getName(a.getInternalValue());
  27.508 -                if (v != null) {
  27.509 -                    s2 = a.getInternalAttr() + "." + v;
  27.510 -                } else {
  27.511 -                    s2 = a.getInternalAttr();
  27.512 -                }
  27.513 -            }
  27.514 -
  27.515 -            return s1.compareTo(s2);
  27.516 -        }
  27.517 -    };
  27.518 -    public static Comparator NODE_POS_COMPARATOR = new Comparator<PythonTree>() {
  27.519 -        @Override
  27.520 -        public int compare(PythonTree p1, PythonTree p2) {
  27.521 -            int ret = p1.getCharStartIndex() - p2.getCharStartIndex();
  27.522 -            if (ret != 0) {
  27.523 -                return ret;
  27.524 -            }
  27.525 -            ret = p2.getCharStopIndex() - p1.getCharStopIndex();
  27.526 -            if (ret != 0) {
  27.527 -                return ret;
  27.528 -            }
  27.529 -            return p2.getAntlrType() - p1.getAntlrType();
  27.530 -        }
  27.531 -    };
  27.532 -}
    28.1 --- a/python.editor/src/org/netbeans/modules/python/editor/QuerySupportFactory.java	Sat Sep 12 23:03:15 2015 -0700
    28.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/QuerySupportFactory.java	Sun Sep 13 11:47:42 2015 +0200
    28.3 @@ -41,6 +41,7 @@
    28.4   */
    28.5  package org.netbeans.modules.python.editor;
    28.6  
    28.7 +import org.netbeans.modules.python.source.PythonIndexer;
    28.8  import java.io.IOException;
    28.9  import java.util.Collection;
   28.10  import java.util.Collections;
   28.11 @@ -54,21 +55,5 @@
   28.12   */
   28.13  public class QuerySupportFactory {
   28.14      
   28.15 -    public static QuerySupport get(final Collection<FileObject> roots) {
   28.16 -        try {
   28.17 -            return QuerySupport.forRoots(PythonIndexer.NAME,
   28.18 -                    PythonIndexer.VERSION,
   28.19 -                    roots.toArray(new FileObject[roots.size()]));
   28.20 -        } catch (IOException ex) {
   28.21 -            Exceptions.printStackTrace(ex);
   28.22 -        }
   28.23 -        return null;
   28.24 -    }
   28.25      
   28.26 -    public static QuerySupport get(final FileObject source) {
   28.27 -        return get(QuerySupport.findRoots(source,
   28.28 -                null,
   28.29 -                null,
   28.30 -                Collections.<String>emptySet()));
   28.31 -    }
   28.32  }
    29.1 --- a/python.editor/src/org/netbeans/modules/python/editor/RstFormatter.java	Sat Sep 12 23:03:15 2015 -0700
    29.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.3 @@ -1,1342 +0,0 @@
    29.4 -/*
    29.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    29.6 - *
    29.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    29.8 - *
    29.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   29.10 - * Other names may be trademarks of their respective owners.
   29.11 - *
   29.12 - * The contents of this file are subject to the terms of either the GNU
   29.13 - * General Public License Version 2 only ("GPL") or the Common
   29.14 - * Development and Distribution License("CDDL") (collectively, the
   29.15 - * "License"). You may not use this file except in compliance with the
   29.16 - * License. You can obtain a copy of the License at
   29.17 - * http://www.netbeans.org/cddl-gplv2.html
   29.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   29.19 - * specific language governing permissions and limitations under the
   29.20 - * License.  When distributing the software, include this License Header
   29.21 - * Notice in each file and include the License file at
   29.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   29.23 - * particular file as subject to the "Classpath" exception as provided
   29.24 - * by Oracle in the GPL Version 2 section of the License file that
   29.25 - * accompanied this code. If applicable, add the following below the
   29.26 - * License Header, with the fields enclosed by brackets [] replaced by
   29.27 - * your own identifying information:
   29.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   29.29 - *
   29.30 - * If you wish your version of this file to be governed by only the CDDL
   29.31 - * or only the GPL Version 2, indicate your decision by adding
   29.32 - * "[Contributor] elects to include this software in this distribution
   29.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   29.34 - * single choice of license, a recipient has the option to distribute
   29.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   29.36 - * to extend the choice of license to its licensees as provided above.
   29.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   29.38 - * Version 2 license, then the option applies only if the new code is
   29.39 - * made subject to such option by the copyright holder.
   29.40 - *
   29.41 - * Contributor(s):
   29.42 - *
   29.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   29.44 - */
   29.45 -package org.netbeans.modules.python.editor;
   29.46 -
   29.47 -import java.awt.Color;
   29.48 -import java.io.CharConversionException;
   29.49 -import java.util.ArrayList;
   29.50 -import java.util.Collections;
   29.51 -import java.util.List;
   29.52 -import javax.swing.text.AttributeSet;
   29.53 -import javax.swing.text.BadLocationException;
   29.54 -import javax.swing.text.StyleConstants;
   29.55 -import org.netbeans.api.editor.mimelookup.MimeLookup;
   29.56 -import org.netbeans.api.editor.mimelookup.MimePath;
   29.57 -import org.netbeans.api.editor.settings.FontColorSettings;
   29.58 -import org.netbeans.api.lexer.Language;
   29.59 -import org.netbeans.api.lexer.Token;
   29.60 -import org.netbeans.api.lexer.TokenHierarchy;
   29.61 -import org.netbeans.api.lexer.TokenSequence;
   29.62 -import org.netbeans.editor.BaseDocument;
   29.63 -import org.netbeans.modules.csl.api.ElementHandle;
   29.64 -import org.netbeans.modules.csl.api.ElementKind;
   29.65 -import org.netbeans.modules.csl.spi.GsfUtilities;
   29.66 -import org.netbeans.modules.csl.spi.ParserResult;
   29.67 -import org.netbeans.modules.python.api.PythonMIMEResolver;
   29.68 -import org.netbeans.modules.python.editor.elements.Element;
   29.69 -import org.netbeans.modules.python.editor.elements.IndexedElement;
   29.70 -import org.netbeans.modules.python.editor.elements.IndexedMethod;
   29.71 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   29.72 -import org.openide.filesystems.FileObject;
   29.73 -import org.openide.util.Exceptions;
   29.74 -import org.openide.util.Lookup;
   29.75 -import org.openide.xml.XMLUtil;
   29.76 -import org.python.antlr.PythonTree;
   29.77 -
   29.78 -/**
   29.79 - * Support for reStructured text. Parse .rst files and rst content in
   29.80 - * Python doc strings and format it as HTML. Also provide functions
   29.81 - * to locate a code element in RST files.
   29.82 - * @see http://www.python.org/dev/peps/pep-0287/
   29.83 - * @see http://docutils.sourceforge.net/docs/user/rst/quickstart.html
   29.84 - *
   29.85 - * @todo Render verbatim blocks
   29.86 - * @todo Syntax highlight verbatim blocks?
   29.87 - * @todo Render *bold* and `identifier` stuff
   29.88 - * @todo For class definitions which nest the method documentation,
   29.89 - *    try to remove all items, or perhaps just make it shorter
   29.90 - * @todo Render note:: into something cleaner etc.
   29.91 - *
   29.92 - * @author Tor Norbye
   29.93 - */
   29.94 -public class RstFormatter {
   29.95 -    private static final String BRBR = "\n<br><br>\n"; // NOI18N
   29.96 -    private StringBuilder sb = new StringBuilder();
   29.97 -    private boolean lastWasEmpty = false;
   29.98 -    private int beginPos;
   29.99 -    private boolean inVerbatim;
  29.100 -    private boolean inIndex;
  29.101 -    private boolean inTable;
  29.102 -    private boolean inDiv;
  29.103 -    private int lastIndent;
  29.104 -    private boolean maybeVerbatim;
  29.105 -    private boolean inDocTest;
  29.106 -    private List<String> code;
  29.107 -
  29.108 -    public RstFormatter() {
  29.109 -    }
  29.110 -
  29.111 -    private void flush() {
  29.112 -        if (inTable) {
  29.113 -            sb.append("</pre>\n"); // NOI18N
  29.114 -            inTable = false;
  29.115 -            inVerbatim = false;
  29.116 -        } else if (inVerbatim) {
  29.117 -            // Process code and format as Python
  29.118 -            String html = getPythonHtml(code, true);
  29.119 -            if (html != null) {
  29.120 -                // <pre> tag is added as part of the rubyhtml (since it
  29.121 -                // needs to pick up the background color from the syntax
  29.122 -                // coloring settings)
  29.123 -                sb.append(html);
  29.124 -            } else {
  29.125 -                sb.append("<pre style=\"margin: 5px 5px; background: #ffffdd; border-size: 1px; padding: 5px\">"); // NOI18N
  29.126 -                sb.append("\n"); // NOI18N
  29.127 -                // Some kind of error; normal append
  29.128 -                for (String s : code) {
  29.129 -                    appendEscaped(s);
  29.130 -                    sb.append("<br>"); // NOI18N
  29.131 -                }
  29.132 -                sb.append("</pre>\n"); // NOI18N
  29.133 -            }
  29.134 -            inVerbatim = false;
  29.135 -            code = null;
  29.136 -        } else if (inDiv) {
  29.137 -            sb.append("</div>\n"); // NOI18N
  29.138 -            inDiv = false;
  29.139 -        }
  29.140 -    }
  29.141 -
  29.142 -    private void appendEscaped(char c) {
  29.143 -        if ('<' == c) {
  29.144 -            sb.append("&lt;"); // NOI18N
  29.145 -        } else if ('&' == c) {
  29.146 -            sb.append("&amp;"); // NOI18N
  29.147 -        } else {
  29.148 -            sb.append(c);
  29.149 -        }
  29.150 -    }
  29.151 -
  29.152 -    private void appendEscaped(CharSequence s) {
  29.153 -        for (int i = 0, n = s.length(); i < n; i++) {
  29.154 -            char c = s.charAt(i);
  29.155 -            if ('<' == c) {
  29.156 -                sb.append("&lt;"); // NOI18N
  29.157 -            } else if ('&' == c) {
  29.158 -                sb.append("&amp;"); // NOI18N
  29.159 -            } else {
  29.160 -                sb.append(c);
  29.161 -            }
  29.162 -        }
  29.163 -    }
  29.164 -
  29.165 -    private int appendColonCmd(String line, int i, String marker, boolean url) throws CharConversionException {
  29.166 -        String MARKER = ":" + marker + ":`"; // NOI18N
  29.167 -        if (line.startsWith(MARKER, i)) {
  29.168 -            int end = line.indexOf("`", i + MARKER.length()); // NOI18N
  29.169 -            if (end != -1) {
  29.170 -                String token = line.substring(i + MARKER.length(), end);
  29.171 -                if (url) {
  29.172 -                    sb.append("<a href=\""); // NOI18N
  29.173 -                    if ("pep".equals(marker)) { // NOI18N
  29.174 -                        sb.append("http://www.python.org/dev/peps/pep-"); // NOI18N
  29.175 -                        for (int j = 0; j < 4 - token.length(); j++) {
  29.176 -                            sb.append("0");
  29.177 -                        }
  29.178 -                        sb.append(token);
  29.179 -                        sb.append("/"); // NOI18N
  29.180 -                        sb.append("\">PEP "); // NOI18N
  29.181 -                        sb.append(token);
  29.182 -                        sb.append("</a>");
  29.183 -                        return end;
  29.184 -                    } else {
  29.185 -                        sb.append(marker);
  29.186 -                        sb.append(":"); // NOI18N
  29.187 -                        appendEscaped(token);
  29.188 -                    }
  29.189 -                    sb.append("\">"); // NOI18N
  29.190 -                } else if (marker.equals("keyword")) { // NOI18N
  29.191 -                    sb.append("<code style=\""); // NOI18N
  29.192 -
  29.193 -                    MimePath mimePath = MimePath.parse(PythonMIMEResolver.PYTHON_MIME_TYPE);
  29.194 -                    Lookup lookup = MimeLookup.getLookup(mimePath);
  29.195 -                    FontColorSettings fcs = lookup.lookup(FontColorSettings.class);
  29.196 -
  29.197 -                    AttributeSet attribs = fcs.getTokenFontColors("keyword"); // NOI18N
  29.198 -                    Color fg = (Color)attribs.getAttribute(StyleConstants.Foreground);
  29.199 -                    if (fg != null) {
  29.200 -                        sb.append("color:"); // NOI18N
  29.201 -                        sb.append(getHtmlColor(fg));
  29.202 -                        sb.append(";"); // NOI18N
  29.203 -                    }
  29.204 -                    Color bg = (Color)attribs.getAttribute(StyleConstants.Background);
  29.205 -                    // Only set the background for dark colors
  29.206 -                    if (bg != null && bg.getRed() < 128) {
  29.207 -                        sb.append("background:"); // NOI18N
  29.208 -                        sb.append(getHtmlColor(bg));
  29.209 -                    }
  29.210 -
  29.211 -                    sb.append("\">"); // NOI18N
  29.212 -                } else {
  29.213 -                    sb.append("<code>"); // NOI18N
  29.214 -                }
  29.215 -                appendEscaped(token);
  29.216 -                if (url) {
  29.217 -                    sb.append("</a>"); // NOI18N
  29.218 -                } else {
  29.219 -                    sb.append("</code>"); // NOI18N
  29.220 -                }
  29.221 -                //return end+1; // instead of end+2: get to end of ``, minus loop increment
  29.222 -                return end; // instead of end+2: get to end of ``, minus loop increment
  29.223 -            }
  29.224 -        }
  29.225 -
  29.226 -        return -1;
  29.227 -    }
  29.228 -
  29.229 -    private void appendRstLine(String line) throws CharConversionException {
  29.230 -        int n = line.length();
  29.231 -        char prev = 0;
  29.232 -        Loop:
  29.233 -        for (int i = 0; i < n; i++) {
  29.234 -            char c = line.charAt(i);
  29.235 -            if (c == '`') {
  29.236 -                if (i < n - 2 && line.charAt(i + 1) == '`') {
  29.237 -                    // See if it's an ``identifier``
  29.238 -                    int end = line.indexOf("``", i + 2);
  29.239 -                    if (end != -1) {
  29.240 -                        sb.append("<code>"); // NOI18N
  29.241 -                        appendEscaped(line.substring(i + 2, end));
  29.242 -                        sb.append("</code>"); // NOI18N
  29.243 -                        i = end + 1; // instead of end+2: get to end of ``, minus loop increment
  29.244 -                        continue;
  29.245 -                    }
  29.246 -                } else {
  29.247 -                    // Single identifier
  29.248 -                    for (int j = i + 1; j < n; j++) {
  29.249 -                        char d = line.charAt(j);
  29.250 -                        if (d == '`') {
  29.251 -                            sb.append("<code>"); // NOI18N
  29.252 -                            appendEscaped(line.substring(i + 1, j));
  29.253 -                            sb.append("</code>"); // NOI18N
  29.254 -                            i = j;
  29.255 -                            continue Loop;
  29.256 -                        } else if (!Character.isJavaIdentifierPart(d)) {
  29.257 -                            break;
  29.258 -                        }
  29.259 -                    }
  29.260 -                }
  29.261 -            } else if (c == ':') {
  29.262 -                int nextI = appendColonCmd(line, i, "class", true); // NOI18N
  29.263 -                if (nextI == -1) {
  29.264 -                    nextI = appendColonCmd(line, i, "exc", true); // NOI18N
  29.265 -                    if (nextI == -1) {
  29.266 -                        nextI = appendColonCmd(line, i, "var", false); // NOI18N
  29.267 -                        if (nextI == -1) {
  29.268 -                            nextI = appendColonCmd(line, i, "meth", true); // NOI18N
  29.269 -                            if (nextI == -1) {
  29.270 -                                nextI = appendColonCmd(line, i, "func", true); // NOI18N
  29.271 -                                if (nextI == -1) {
  29.272 -                                    nextI = appendColonCmd(line, i, "data", false); // NOI18N
  29.273 -                                    if (nextI == -1) {
  29.274 -                                        nextI = appendColonCmd(line, i, "attr", false); // NOI18N
  29.275 -                                        if (nextI == -1) {
  29.276 -                                            nextI = appendColonCmd(line, i, "envvar", false); // NOI18N
  29.277 -                                            if (nextI == -1) {
  29.278 -                                                nextI = appendColonCmd(line, i, "mod", true); // NOI18N
  29.279 -                                                if (nextI == -1) {
  29.280 -                                                    nextI = appendColonCmd(line, i, "pep", true); // NOI18N
  29.281 -                                                    if (nextI == -1) {
  29.282 -                                                        nextI = appendColonCmd(line, i, "ref", false); // NOI18N
  29.283 -                                                        if (nextI == -1) {
  29.284 -                                                            nextI = appendColonCmd(line, i, "mod", true); // NOI18N
  29.285 -                                                            if (nextI == -1) {
  29.286 -                                                                nextI = appendColonCmd(line, i, "keyword", false); // NOI18N
  29.287 -                                                                if (nextI == -1) {
  29.288 -                                                                    if (line.startsWith(":noindex:", i)) { // NOI18N
  29.289 -                                                                        nextI = i + 9;
  29.290 -                                                                    } else if (line.startsWith(":synopsis:", i)) { // NOI18N
  29.291 -                                                                        nextI = i + 10;
  29.292 -                                                                    } else if (line.startsWith(":deprecated:", i)) {
  29.293 -                                                                        sb.append("Deprecated. ");
  29.294 -                                                                        nextI = i + 12;
  29.295 -                                                                    } else if (line.startsWith(":platform:", i)) {
  29.296 -                                                                        sb.append("Platform: ");
  29.297 -                                                                        nextI = i + 10;
  29.298 -                                                                    }
  29.299 -                                                                }
  29.300 -                                                            }
  29.301 -                                                        }
  29.302 -                                                    }
  29.303 -                                                }
  29.304 -                                            }
  29.305 -                                        }
  29.306 -                                    }
  29.307 -                                }
  29.308 -                            }
  29.309 -                        }
  29.310 -                    }
  29.311 -                }
  29.312 -                if (nextI != -1) {
  29.313 -                    i = nextI;
  29.314 -                    continue;
  29.315 -                }
  29.316 -            } else if (c == '*') {
  29.317 -                // Bold?
  29.318 -                if (i < n - 1 && Character.isJavaIdentifierPart(line.charAt(i + 1)) && !Character.isJavaIdentifierPart(prev)) { // TODO Use PythonUtils
  29.319 -                    // Peek ahead to see if we have [not-identifier-char]*[identifierchars]*[not-identifier-chars]
  29.320 -                    for (int j = i + 1; j < n; j++) {
  29.321 -                        char d = line.charAt(j);
  29.322 -                        if (d == '*') {
  29.323 -                            if (j == n - 1 || !Character.isJavaIdentifierPart(line.charAt(j + 1))) {
  29.324 -                                // Yess, make bold
  29.325 -                                sb.append("<b>"); // NOI18N
  29.326 -                                appendEscaped(line.substring(i + 1, j));
  29.327 -                                sb.append("</b>"); // NOI18N
  29.328 -                                i = j;
  29.329 -                                continue Loop;
  29.330 -                            }
  29.331 -                        } else if (!Character.isJavaIdentifierPart(d)) {
  29.332 -                            break;
  29.333 -                        }
  29.334 -                    }
  29.335 -                }
  29.336 -            } // TODO: :addedin, :deprecated, etc
  29.337 -
  29.338 -            appendEscaped(c);
  29.339 -            prev = c;
  29.340 -        }
  29.341 -    }
  29.342 -
  29.343 -    public void append(String line) {
  29.344 -        try {
  29.345 -            String trim = line.trim();
  29.346 -            if (trim.length() == 0) {
  29.347 -                inDocTest = false;
  29.348 -                if (inIndex) {
  29.349 -                    // Completely swallow all indexing entries
  29.350 -                    return;
  29.351 -                } else if (inTable) {
  29.352 -                    sb.append("</pre>\n"); // NOI18N
  29.353 -                    inVerbatim = false;
  29.354 -                    inTable = false;
  29.355 -                } else if (inVerbatim) {
  29.356 -                    sb.append("\n"); // NOI18N
  29.357 -                } else if (!lastWasEmpty && sb.length() > beginPos) {
  29.358 -                    sb.append(BRBR); // NOI18N
  29.359 -                }
  29.360 -                lastWasEmpty = true;
  29.361 -            } else {
  29.362 -                if (!lastWasEmpty && trim.startsWith("- ")) { // NOI18N
  29.363 -                    // lists - make sure they're on a new line
  29.364 -                    sb.append("<br>"); // NOI18N
  29.365 -                }
  29.366 -
  29.367 -                lastWasEmpty = false;
  29.368 -
  29.369 -                if (maybeVerbatim) {
  29.370 -                    int indent = getIndentation(line, 0);
  29.371 -                    if (indent > lastIndent) {
  29.372 -                        // Truncate last whitespace separator before <pre> if any
  29.373 -                        if (sb.length() > BRBR.length() && sb.substring(sb.length() - BRBR.length()).equals(BRBR)) {
  29.374 -                            sb.setLength(sb.length() - BRBR.length());
  29.375 -                        }
  29.376 -                        inVerbatim = true;
  29.377 -                        code = new ArrayList<>();
  29.378 -                        code.add(line);
  29.379 -                        maybeVerbatim = false;
  29.380 -                        return;
  29.381 -                    }
  29.382 -                    maybeVerbatim = false;
  29.383 -                } else if (inVerbatim || inTable) {
  29.384 -                    int indent = getIndentation(line, 0);
  29.385 -                    if (indent <= lastIndent) {
  29.386 -////                        // Truncate trailing whitespace
  29.387 -////                        while (sb.length() > 0 && sb.charAt(sb.length()-1) == '\n') {
  29.388 -////                            sb.setLength(sb.length()-1);
  29.389 -////                        }
  29.390 -////                        sb.append("</pre>"); // NOI18N
  29.391 -//                        inVerbatim = false;
  29.392 -//                        inTable = false;
  29.393 -                        flush();
  29.394 -                        lastWasEmpty = true;
  29.395 -                    } else if (inVerbatim) {
  29.396 -                        // We need to buffer up the text such that we can lex it as a unit
  29.397 -                        // (and determine when done with the section if it's code or regular text)
  29.398 -                        code.add(line);
  29.399 -                        return;
  29.400 -                    } else {
  29.401 -                        appendEscaped(line);
  29.402 -                        sb.append("\n"); // NOI18N
  29.403 -                        return;
  29.404 -                    }
  29.405 -                } else if (inDiv) {
  29.406 -                    int indent = getIndentation(line, 0);
  29.407 -                    if (indent <= lastIndent) {
  29.408 -                        // Truncate last whitespace separator before <pre> if any
  29.409 -                        if (sb.length() > BRBR.length() && sb.substring(sb.length() - BRBR.length()).equals(BRBR)) {
  29.410 -                            sb.setLength(sb.length() - BRBR.length());
  29.411 -                        }
  29.412 -                        sb.append("</div>\n"); // NOI18N
  29.413 -                        inDiv = false;
  29.414 -                        lastWasEmpty = true;
  29.415 -                    } else {
  29.416 -                        appendRstLine(line);
  29.417 -                        sb.append("\n"); // NOI18N
  29.418 -                        return;
  29.419 -                    }
  29.420 -                } else if (inIndex) {
  29.421 -                    int indent = getIndentation(line, 0);
  29.422 -                    if (indent <= lastIndent) {
  29.423 -                        inIndex = false;
  29.424 -                        lastWasEmpty = true;
  29.425 -                    } else {
  29.426 -                        return;
  29.427 -                    }
  29.428 -
  29.429 -                }
  29.430 -
  29.431 -                if (trim.startsWith(".. method:: ")) { // NOI18N
  29.432 -                    String sig = trim.substring(12).trim();
  29.433 -                    sb.append("<a href=\"meth:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
  29.434 -                    return;
  29.435 -                } else if (trim.startsWith(".. function:: ")) { // NOI18N
  29.436 -                    String sig = trim.substring(14).trim();
  29.437 -                    sb.append("<a href=\"func:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
  29.438 -                    return;
  29.439 -                } else if (trim.startsWith(".. class:: ")) { // NOI18N
  29.440 -                    String sig = trim.substring(11).trim();
  29.441 -                    sb.append("<a href=\"class:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
  29.442 -                    return;
  29.443 -                } else if (trim.startsWith(".. attribute:: ")) { // NOI18N
  29.444 -                    String sig = trim.substring(15).trim();
  29.445 -                    sb.append("<a href=\"attr:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
  29.446 -                    return;
  29.447 -                } else if (trim.startsWith(".. data:: ")) { // NOI18N
  29.448 -                    String sig = trim.substring(10).trim();
  29.449 -                    sb.append("<a href=\"data:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
  29.450 -                    return;
  29.451 -                } else if (trim.startsWith(".. module:: ")) { // NOI18N
  29.452 -                    String sig = trim.substring(12).trim();
  29.453 -                    sb.append("<a href=\"module:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>"); // NOI18N
  29.454 -                    sb.append("<br>\n");
  29.455 -                    return;
  29.456 -                } else if (trim.startsWith(".. productionlist:")) {
  29.457 -                    lastIndent = getIndentation(line, 0);
  29.458 -                    inVerbatim = true;
  29.459 -                    code = new ArrayList<>();
  29.460 -                    code.add(line);
  29.461 -                    maybeVerbatim = false;
  29.462 -                    return;
  29.463 -                }
  29.464 -
  29.465 -                if (trim.startsWith(">>>") || inDocTest) { // NOI18N
  29.466 -                    if (!trim.startsWith(">>>")) { // NOI18N
  29.467 -                        sb.append("<code>"); // NOI18N
  29.468 -                        appendEscaped(line); // NOI18N
  29.469 -                        // Wait until there is an empty line before we mark doctest done!
  29.470 -                        // inDocTest = false;
  29.471 -                        sb.append("</code><br>"); // NOI18N
  29.472 -                    } else {
  29.473 -                        sb.append("<code>"); // NOI18N
  29.474 -                        appendEscaped(">>>"); // NOI18N
  29.475 -                        String html = getPythonHtml(Collections.singletonList(trim.substring(3)), false);
  29.476 -                        sb.append(html);
  29.477 -                        sb.append("</code>"); // NOI18N
  29.478 -                        inDocTest = true;
  29.479 -                    }
  29.480 -                    return;
  29.481 -                }
  29.482 -                inDocTest = false;
  29.483 -
  29.484 -                if (trim.startsWith(".. note::") || trim.startsWith(".. warning::") || trim.startsWith(".. seealso:")) { // NOI18N
  29.485 -                    // Truncate last whitespace separator before <pre> if any
  29.486 -                    if (sb.length() > BRBR.length() && sb.substring(sb.length() - BRBR.length()).equals(BRBR)) {
  29.487 -                        sb.setLength(sb.length() - BRBR.length());
  29.488 -                    }
  29.489 -                    sb.append("<div style=\"margin: 5px 5px; "); // NOI18N
  29.490 -                    if (!trim.contains("seealso")) { // NOI18N
  29.491 -                        sb.append("background: #ffdddd; "); // NOI18N
  29.492 -                    } else {
  29.493 -                        sb.append("background: #ddffdd; "); // NOI18N
  29.494 -                    }
  29.495 -                    sb.append("border-size: 1px; padding: 5px\">"); // NOI18N
  29.496 -                    if (trim.contains("note:")) {
  29.497 -                        sb.append("<b>NOTE</b>: "); // NOI18N
  29.498 -                    } else if (trim.contains("warning")) {
  29.499 -                        sb.append("<b>WARNING</b>: "); // NOI18N
  29.500 -                    } else {
  29.501 -                        sb.append("<b>See Also</b>: "); // NOI18N
  29.502 -                    }
  29.503 -                    sb.append("\n"); // NOI18N
  29.504 -                    inDiv = true;
  29.505 -                    lastIndent = getIndentation(line, 0);
  29.506 -                    maybeVerbatim = false;
  29.507 -                    return;
  29.508 -                } else if (trim.startsWith(".. versionadded::") || trim.startsWith(".. versionchanged::") || trim.startsWith(".. deprecated::")) { // NOI18N
  29.509 -                    // Truncate last whitespace separator before <pre> if any
  29.510 -                    if (sb.length() > BRBR.length() && sb.substring(sb.length() - BRBR.length()).equals(BRBR)) {
  29.511 -                        sb.setLength(sb.length() - BRBR.length());
  29.512 -                    }
  29.513 -                    sb.append("<div style=\"margin: 5px 5px; background: #dddddd; border-size: 1px; padding: 5px\">"); // NOI18N
  29.514 -                    if (trim.contains("added:")) {
  29.515 -                        sb.append("<b>Version Added</b>: "); // NOI18N
  29.516 -                    } else if (trim.contains("changed")) {
  29.517 -                        sb.append("<b>Version Changed</b>: "); // NOI18N
  29.518 -                    } else {
  29.519 -                        assert trim.contains("deprecated"); // NOI18N
  29.520 -                        sb.append("<b>Deprecated</b>: "); // NOI18N
  29.521 -                    }
  29.522 -                    sb.append(trim.substring(trim.indexOf("::") + 2));
  29.523 -                    sb.append("\n"); // NOI18N
  29.524 -                    inDiv = true;
  29.525 -                    lastIndent = getIndentation(line, 0);
  29.526 -                    maybeVerbatim = false;
  29.527 -                    return;
  29.528 -                } else if (trim.startsWith(".. index:")) { // NOI18N
  29.529 -                    inIndex = true;
  29.530 -                    lastIndent = getIndentation(line, 0);
  29.531 -                    return;
  29.532 -                } else if (trim.startsWith(".. _") && trim.endsWith(":")) {
  29.533 -                    // skip lines like .. _pyzipfile-objects: 
  29.534 -                    return;
  29.535 -                } else if (trim.startsWith(".. moduleauthor::") || trim.startsWith(".. sectionauthor::")) { // NOI18N
  29.536 -                    if (trim.startsWith(".. mod")) {
  29.537 -                        sb.append("<br>Module Author:</b>");
  29.538 -                    } else {
  29.539 -                        sb.append("<br>Section Author:</b>");
  29.540 -                    }
  29.541 -                    appendEscaped(trim.substring(trim.indexOf("::") + 2)); //
  29.542 -                    sb.append("\n");
  29.543 -                    return;
  29.544 -                } else if (trim.endsWith("::")) { // NOI18N
  29.545 -                    maybeVerbatim = true;
  29.546 -                    lastIndent = getIndentation(line, 0);
  29.547 -                } else if (trim.startsWith("+-----")) { // NOI18N
  29.548 -                    // A table
  29.549 -                    sb.append("<pre>"); // NOI18N
  29.550 -                    appendEscaped(line);
  29.551 -                    sb.append("\n"); // NOI18N
  29.552 -                    inTable = true;
  29.553 -                    lastIndent = getIndentation(line, 0) - 1;
  29.554 -                    return;
  29.555 -                } else if (line.startsWith("======") || line.startsWith("------") || line.startsWith("******") || line.startsWith("^^^^^^^^")) { // NOI18N
  29.556 -                    // PREVIOUS line could be a title.
  29.557 -                    // Note -- we're comparing on "line" and not "trim" here because in indented contexts,
  29.558 -                    //  === sometimes represents parts of tables -- see the turtle.rst file for examples.
  29.559 -
  29.560 -                    int n = sb.length();
  29.561 -                    if (n > 0 && sb.charAt(n - 1) == '\n') {
  29.562 -                        n--;
  29.563 -                    }
  29.564 -                    int index = n - 1;
  29.565 -                    for (; index >= 0; index--) {
  29.566 -                        char c = sb.charAt(index);
  29.567 -                        if (c == '\n') {
  29.568 -                            index++;
  29.569 -                            break;
  29.570 -                        }
  29.571 -                    }
  29.572 -                    if (index == -1) {
  29.573 -                        index = 0;
  29.574 -                    }
  29.575 -                    // Index now points to the beginning of the previous line
  29.576 -                    boolean empty = true;
  29.577 -//                    boolean okay = true;
  29.578 -                    int start = index;
  29.579 -                    for (; index < n; index++) {
  29.580 -                        char c = sb.charAt(index);
  29.581 -                        if (c == '\n') {
  29.582 -                            break;
  29.583 -                        }
  29.584 -                        empty = false;
  29.585 -//                        if (c == '<') {
  29.586 -//                            okay = false;
  29.587 -//                        }
  29.588 -                    }
  29.589 -                    if (!empty/* && okay*/) {
  29.590 -                        String tag = "h2"; // NOI18N
  29.591 -                        if (line.startsWith("-") || line.startsWith("^")) { // NOI18N
  29.592 -                            tag = "h3"; // NOI18N
  29.593 -                        }
  29.594 -                        sb.insert(start, "<" + tag + ">"); // NOI18N
  29.595 -                        sb.append("</" + tag + ">\n"); // NOI18N
  29.596 -                        lastWasEmpty = true;
  29.597 -                        return;
  29.598 -                    }
  29.599 -                }
  29.600 -
  29.601 -                //sb.append(line);
  29.602 -                appendRstLine(line);
  29.603 -
  29.604 -                sb.append("\n"); // NOI18N
  29.605 -            }
  29.606 -        } catch (CharConversionException ex) {
  29.607 -            Exceptions.printStackTrace(ex);
  29.608 -        }
  29.609 -    }
  29.610 -
  29.611 -    public void appendSignature(Element element) {
  29.612 -        sb.append("<pre>"); // NOI18N
  29.613 -
  29.614 -        if (element instanceof IndexedMethod) {
  29.615 -            IndexedMethod executable = (IndexedMethod)element;
  29.616 -            if (element.getIn() != null && !PythonIndex.isBuiltinModule(element.getIn())) {
  29.617 -                String in = element.getIn();
  29.618 -                sb.append("<i>"); // NOI18N
  29.619 -                sb.append(in);
  29.620 -                sb.append("</i>"); // NOI18N
  29.621 -                sb.append("<br>"); // NOI18N
  29.622 -            }
  29.623 -            // TODO - share this between Navigator implementation and here...
  29.624 -            sb.append("<b>"); // NOI18N
  29.625 -            sb.append(element.getName());
  29.626 -            sb.append("</b>"); // NOI18N
  29.627 -            String[] parameters = executable.getParams();
  29.628 -
  29.629 -            if ((parameters != null) && (parameters.length > 0)) {
  29.630 -                sb.append("("); // NOI18N
  29.631 -
  29.632 -                sb.append("<font color=\"#808080\">"); // NOI18N
  29.633 -
  29.634 -                boolean first = true;
  29.635 -                for (String parameter : parameters) {
  29.636 -                    if (first) {
  29.637 -                        first = false;
  29.638 -                    } else {
  29.639 -                        sb.append(", ");
  29.640 -                    }
  29.641 -                    sb.append(parameter);
  29.642 -                }
  29.643 -
  29.644 -                sb.append("</font>"); // NOI18N
  29.645 -
  29.646 -                sb.append(")"); // NOI18N
  29.647 -            }
  29.648 -        } else if (element instanceof IndexedElement) {
  29.649 -            //IndexedElement clz = (IndexedElement)element;
  29.650 -            String name = element.getName();
  29.651 -//            final String fqn = clz.getFqn();
  29.652 -//            if (fqn != null && !name.equals(fqn)) {
  29.653 -//                signature.append("<i>"); // NOI18N
  29.654 -//                signature.append(fqn); // NOI18N
  29.655 -//                signature.append("</i>"); // NOI18N
  29.656 -//                signature.append("<br>"); // NOI18N
  29.657 -//            }
  29.658 -            sb.append("<b>"); // NOI18N
  29.659 -            sb.append(name);
  29.660 -            sb.append("</b>"); // NOI18N
  29.661 -        } else {
  29.662 -            sb.append(element.getName());
  29.663 -        }
  29.664 -
  29.665 -        sb.append("</pre>\n"); // NOI18N
  29.666 -    }
  29.667 -
  29.668 -    public void appendHtml(String html) {
  29.669 -        sb.append(html);
  29.670 -    }
  29.671 -
  29.672 -    public void markEmpty() {
  29.673 -        beginPos = sb.length();
  29.674 -    }
  29.675 -
  29.676 -    public String toHtml() {
  29.677 -        flush();
  29.678 -        return sb.toString();
  29.679 -    }
  29.680 -
  29.681 -    public static String document(String rst) {
  29.682 -        RstFormatter formatter = new RstFormatter();
  29.683 -        String[] lines = rst.split("\n"); // NOI18N
  29.684 -        for (String line : lines) {
  29.685 -            formatter.append(line);
  29.686 -        }
  29.687 -        return formatter.toHtml();
  29.688 -    }
  29.689 -
  29.690 -    public static String getDocumentation(IndexedElement indexedElement) {
  29.691 -        RstFormatter formatter = new RstFormatter();
  29.692 -        FileObject fileObject = indexedElement.getFileObject();
  29.693 -        if (fileObject == null) {
  29.694 -            return null;
  29.695 -        }
  29.696 -        BaseDocument document = GsfUtilities.getDocument(fileObject, true);
  29.697 -        if (document == null) {
  29.698 -            return null;
  29.699 -        }
  29.700 -
  29.701 -        String[] signatureHolder = new String[1];
  29.702 -        String rst = formatter.extractRst(indexedElement, document, signatureHolder);
  29.703 -        if (rst != null && rst.length() > 0) {
  29.704 -            String signature = signatureHolder[0];
  29.705 -            if (signature == null) {
  29.706 -                formatter.appendSignature(indexedElement);
  29.707 -                formatter.appendHtml("\n<hr>\n"); // NOI18N
  29.708 -                formatter.markEmpty();
  29.709 -            } else {
  29.710 -                formatter.appendHtml("<pre>"); // NOI18N
  29.711 -                formatter.appendHtml("<b>"); // NOI18N
  29.712 -                int paren = signature.indexOf('(');
  29.713 -                if (paren != -1) {
  29.714 -                    formatter.appendHtml(signature.substring(0, paren));
  29.715 -                    formatter.appendHtml("</b>"); // NOI18N
  29.716 -                    formatter.appendHtml("<font color=\"#808080\">"); // NOI18N
  29.717 -                    formatter.appendHtml(signature.substring(paren));
  29.718 -                    formatter.appendHtml("</font>"); // NOI18N
  29.719 -                } else {
  29.720 -                    formatter.appendHtml(signature);
  29.721 -                    formatter.appendHtml("()"); // NOI18N
  29.722 -                    formatter.appendHtml("</b>"); // NOI18N
  29.723 -                }
  29.724 -                formatter.appendHtml("</pre>"); // NOI18N
  29.725 -                formatter.appendHtml("\n<hr>\n"); // NOI18N
  29.726 -                formatter.markEmpty();
  29.727 -            }
  29.728 -
  29.729 -            String[] lines = rst.split("\n"); // NOI18N
  29.730 -            for (String line : lines) {
  29.731 -                formatter.append(line);
  29.732 -            }
  29.733 -            return formatter.toHtml();
  29.734 -        }
  29.735 -
  29.736 -        return null;
  29.737 -    }
  29.738 -
  29.739 -    /**
  29.740 -     * Find the reStructured text for the documentation for the given element
  29.741 -     * in the given RST document
  29.742 -     * @param indexedElement
  29.743 -     * @param document
  29.744 -     * @return
  29.745 -     */
  29.746 -    private String extractRst(IndexedElement element, BaseDocument doc, String[] signatureHolder) {
  29.747 -        return extractRst(element.getName(), element.getClz(), element.getKind(), doc, signatureHolder);
  29.748 -    }
  29.749 -
  29.750 -    String extractRst(String name, String clz, ElementKind kind, BaseDocument doc, String[] signatureHolder) {
  29.751 -        try {
  29.752 -            String text = doc.getText(0, doc.getLength());
  29.753 -            // What about functions?
  29.754 -            if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
  29.755 -                int offset = findElementMatch(text, "function::", name, true); // NOI18N
  29.756 -                if (offset == -1) {
  29.757 -                    offset = findElementMatch(text, "method::", name, false); // NOI18N
  29.758 -                    if (offset == -1 && kind == ElementKind.CONSTRUCTOR) {
  29.759 -                        offset = findElementMatch(text, "class::", name, false); // NOI18N
  29.760 -                        if (offset == -1 && clz != null && clz.length() > 0 && "__init__".equals(name)) { // NOI18N
  29.761 -                            offset = findElementMatch(text, "method::", clz, false); // NOI18N
  29.762 -                            if (offset == -1) {
  29.763 -                                offset = findElementMatch(text, "class::", clz, false); // NOI18N
  29.764 -                            }
  29.765 -                        }
  29.766 -                    }
  29.767 -                }
  29.768 -                if (offset != -1) {
  29.769 -                    int end = findElementEnd(text, offset);
  29.770 -                    int nextLine = getNextLineOffset(text, offset);
  29.771 -                    if (nextLine < end) {
  29.772 -                        if (signatureHolder != null) {
  29.773 -                            String signature = text.substring(text.indexOf("::", offset) + 2, nextLine).trim(); // NOI18N
  29.774 -                            signatureHolder[0] = signature;
  29.775 -                        }
  29.776 -                        return text.substring(nextLine, end);
  29.777 -                    }
  29.778 -                }
  29.779 -            } else if (kind == ElementKind.CLASS) {
  29.780 -                int offset = findElementMatch(text, "class::", name, false); // NOI18N
  29.781 -                if (offset == -1) {
  29.782 -                    offset = findElementMatch(text, "exception::", name, false); // NOI18N
  29.783 -                }
  29.784 -                if (offset != -1) {
  29.785 -                    int end = findElementEnd(text, offset);
  29.786 -                    int nextLine = getNextLineOffset(text, offset);
  29.787 -                    if (nextLine < end) {
  29.788 -                        String elementText = text.substring(nextLine, end);
  29.789 -                        return elementText;
  29.790 -                    }
  29.791 -                }
  29.792 -            } else if (kind == ElementKind.MODULE) {
  29.793 -                int offset = findElementMatch(text, "module::", name, false); // NOI18N
  29.794 -                if (offset == -1) {
  29.795 -                    offset = findElementMatch(text, "currentmodule::", name, false); // NOI18N
  29.796 -                }
  29.797 -                if (offset != -1) {
  29.798 -                    int end = findElementEnd(text, offset);
  29.799 -                    int nextLine = getNextLineOffset(text, offset);
  29.800 -                    if (nextLine < end) {
  29.801 -                        String elementText = text.substring(nextLine, end);
  29.802 -                        return elementText;
  29.803 -                    }
  29.804 -                }
  29.805 -            } else {
  29.806 -//                assert kind == ElementKind.ATTRIBUTE :;
  29.807 -                int offset = findElementMatch(text, "data::", name, true); // NOI18N
  29.808 -                if (offset == -1) {
  29.809 -                    offset = findElementMatch(text, "attribute::", name, false); // NOI18N
  29.810 -                }
  29.811 -                if (offset != -1) {
  29.812 -                    int end = findElementEnd(text, offset);
  29.813 -                    int nextLine = getNextLineOffset(text, offset);
  29.814 -                    if (nextLine < end) {
  29.815 -                        String elementText = text.substring(nextLine, end);
  29.816 -                        return elementText;
  29.817 -                    }
  29.818 -                }
  29.819 -            }
  29.820 -        } catch (BadLocationException ex) {
  29.821 -            Exceptions.printStackTrace(ex);
  29.822 -            return "";
  29.823 -        }
  29.824 -
  29.825 -//        while (true) {
  29.826 -//            try {
  29.827 -//                int ret = doc.find(new FinderFactory.StringFwdFinder(".. " + key + "::", true), offset, -1);
  29.828 -//                if (ret == -1) {
  29.829 -//                    break;
  29.830 -//                }
  29.831 -//            } catch (BadLocationException ex) {
  29.832 -//                Exceptions.printStackTrace(ex);
  29.833 -//            }
  29.834 -//        }
  29.835 -
  29.836 -
  29.837 -        return "";
  29.838 -    }
  29.839 -
  29.840 -    public static int getIndentation(String text, int lineBegin) {
  29.841 -        for (int i = lineBegin; i < text.length(); i++) {
  29.842 -            char c = text.charAt(i);
  29.843 -            if (c == '\n') {
  29.844 -                // Empty lines don't count
  29.845 -                return -1;
  29.846 -            }
  29.847 -            if (!Character.isWhitespace(c)) {
  29.848 -                // Doesn't quite work for tabs etc. but those aren't
  29.849 -                // really used in rst files... Fix when I switch to
  29.850 -                // direct document iteration
  29.851 -                return i - lineBegin;
  29.852 -            }
  29.853 -        }
  29.854 -
  29.855 -        return -1;
  29.856 -    }
  29.857 -
  29.858 -    public static int getNextLineOffset(String text, int offset) {
  29.859 -        int index = text.indexOf('\n', offset);
  29.860 -        if (index == -1) {
  29.861 -            return -1;
  29.862 -        } else {
  29.863 -            return index + 1;
  29.864 -        }
  29.865 -    }
  29.866 -
  29.867 -    public static int findElementEnd(String text, int offset) {
  29.868 -        // Find beginning of line
  29.869 -        int lineBegin = 0;
  29.870 -        for (int i = offset; i > 0; i--) {
  29.871 -            char c = text.charAt(i);
  29.872 -            if (c == '\n') {
  29.873 -                lineBegin = i + 1;
  29.874 -                break;
  29.875 -            }
  29.876 -        }
  29.877 -
  29.878 -        // Compute indentation of the ..
  29.879 -        int firstIndent = getIndentation(text, lineBegin);
  29.880 -        offset = getNextLineOffset(text, lineBegin);
  29.881 -        while (true) {
  29.882 -            offset = getNextLineOffset(text, offset);
  29.883 -            if (offset == -1) {
  29.884 -                return text.length();
  29.885 -            }
  29.886 -            int indent = getIndentation(text, offset);
  29.887 -            if (indent == -1) {
  29.888 -                // Empty line - doesn't count
  29.889 -                continue;
  29.890 -            } else if (indent <= firstIndent) {
  29.891 -                return offset;
  29.892 -            }
  29.893 -        }
  29.894 -    }
  29.895 -
  29.896 -    public static int findElementMatch(String text, String key, String name, boolean checkAdjacentLines) {
  29.897 -        int nameLength = name.length();
  29.898 -        int offset = 0;
  29.899 -        int keyLength = key.length();
  29.900 -        while (true) {
  29.901 -            int next = text.indexOf(key, offset);
  29.902 -            if (next == -1) {
  29.903 -                break;
  29.904 -            }
  29.905 -            offset = next + keyLength;
  29.906 -
  29.907 -            int lineEnd = text.indexOf('\n', offset);
  29.908 -            if (lineEnd == -1) {
  29.909 -                lineEnd = text.length(); // on last line with no crlf at the end
  29.910 -            }
  29.911 -
  29.912 -            // Skip whitespace
  29.913 -            for (; offset < lineEnd; offset++) {
  29.914 -                char c = text.charAt(offset);
  29.915 -                if (c != ' ') {
  29.916 -                    break;
  29.917 -                }
  29.918 -            }
  29.919 -
  29.920 -            int nameBegin = offset;
  29.921 -            int nameEnd = -1;
  29.922 -
  29.923 -            // Pick out the bame
  29.924 -            for (int i = offset; i < lineEnd; i++) {
  29.925 -                char c = text.charAt(i);
  29.926 -                if (c == '(' || c == ' ') {
  29.927 -                    nameEnd = i;
  29.928 -                    break;
  29.929 -                } else if (c == '.') {
  29.930 -                    nameBegin = i + 1;
  29.931 -                }
  29.932 -            }
  29.933 -            if (nameEnd == -1) {
  29.934 -                nameEnd = lineEnd;
  29.935 -            }
  29.936 -
  29.937 -
  29.938 -            if (nameEnd - nameBegin == nameLength &&
  29.939 -                    text.regionMatches(nameBegin, name, 0, nameLength)) {
  29.940 -                // TODO - validate the arguments list?
  29.941 -                return next;
  29.942 -            }
  29.943 -
  29.944 -            // Look on subsequent lines too - we sometimes have adjacent lines
  29.945 -            // with additional signatures
  29.946 -            if (checkAdjacentLines) {
  29.947 -                while (true) {
  29.948 -                    int lineBegin = lineEnd+1;
  29.949 -                    if (lineBegin >= text.length()) {
  29.950 -                        break;
  29.951 -                    }
  29.952 -
  29.953 -                    lineEnd = text.indexOf('\n', lineBegin);
  29.954 -                    if (lineEnd == -1) {
  29.955 -                        lineEnd = text.length(); // on last line with no crlf at the end
  29.956 -                    }
  29.957 -
  29.958 -                    while (lineBegin < lineEnd) {
  29.959 -                        char c = text.charAt(lineBegin);
  29.960 -                        if (!Character.isWhitespace(c)) {
  29.961 -                            break;
  29.962 -                        }
  29.963 -                        lineBegin++;
  29.964 -                    }
  29.965 -
  29.966 -                    while (lineEnd > lineBegin) {
  29.967 -                        char c = text.charAt(lineEnd-1);
  29.968 -                        if (!Character.isWhitespace(c)) {
  29.969 -                            break;
  29.970 -                        }
  29.971 -                        lineEnd--;
  29.972 -                    }
  29.973 -
  29.974 -                    if (lineEnd <= lineBegin) {
  29.975 -                        break;
  29.976 -                    }
  29.977 -
  29.978 -                    nameBegin = lineBegin;
  29.979 -                    nameEnd = -1;
  29.980 -
  29.981 -                    // Pick out the name
  29.982 -                    for (int i = lineBegin; i < lineEnd; i++) {
  29.983 -                        char c = text.charAt(i);
  29.984 -                        if (c == '(' || c == ' ') {
  29.985 -                            nameEnd = i;
  29.986 -                            break;
  29.987 -                        } else if (c == '.') {
  29.988 -                            nameBegin = i + 1;
  29.989 -                        }
  29.990 -                    }
  29.991 -                    if (nameEnd == -1) {
  29.992 -                        nameEnd = lineEnd;
  29.993 -                    }
  29.994 -
  29.995 -                    if (nameEnd - nameBegin == nameLength &&
  29.996 -                            text.regionMatches(nameBegin, name, 0, nameLength)) {
  29.997 -                        // TODO - validate the arguments list?
  29.998 -                        return next;
  29.999 -                    }
 29.1000 -                }
 29.1001 -            }
 29.1002 -
 29.1003 -        }
 29.1004 -
 29.1005 -        return -1;
 29.1006 -    }
 29.1007 -
 29.1008 -    public static String document(ParserResult info, ElementHandle element) {
 29.1009 -        if (element instanceof IndexedElement) {
 29.1010 -            IndexedElement indexedElement = (IndexedElement)element;
 29.1011 -
 29.1012 -            FileObject fo = indexedElement.getFileObject();
 29.1013 -
 29.1014 -            if (fo == null) {
 29.1015 -                return null;
 29.1016 -            }
 29.1017 -
 29.1018 -            if (PythonUtils.isRstFile(fo)) {
 29.1019 -                return getDocumentation(indexedElement);
 29.1020 -            }
 29.1021 -
 29.1022 -
 29.1023 -            PythonTree node = indexedElement.getNode();
 29.1024 -            if (node != null) {
 29.1025 -                return document(info, node, indexedElement);
 29.1026 -            }
 29.1027 -        }
 29.1028 -        return null;
 29.1029 -    }
 29.1030 -
 29.1031 -    public static String document(ParserResult info, PythonTree node, IndexedElement element) {
 29.1032 -        if (node != null) {
 29.1033 -            String doc = PythonAstUtils.getDocumentation(node);
 29.1034 -            if (doc != null) {
 29.1035 -                // Honor empty lines: paragraphs
 29.1036 -                RstFormatter formatter = new RstFormatter();
 29.1037 -                if (element != null) {
 29.1038 -                    formatter.appendSignature(element);
 29.1039 -                }
 29.1040 -                if (doc.indexOf('\n') != -1) {
 29.1041 -                    formatter.appendHtml("\n<hr>\n"); // NOI18N
 29.1042 -                    formatter.markEmpty();
 29.1043 -                    String[] lines = doc.split("\n"); // NOI18N
 29.1044 -                    for (String line : lines) {
 29.1045 -                        formatter.append(line);
 29.1046 -                    }
 29.1047 -                } else if (doc.length() > 0) {
 29.1048 -                    formatter.appendHtml("\n<hr>\n"); // NOI18N
 29.1049 -                    formatter.markEmpty();
 29.1050 -                    formatter.append(doc);
 29.1051 -                }
 29.1052 -
 29.1053 -                return formatter.toHtml();
 29.1054 -            }
 29.1055 -        }
 29.1056 -
 29.1057 -        return null;
 29.1058 -    }
 29.1059 -
 29.1060 -    public static String getSignature(Element element) {
 29.1061 -        StringBuilder signature = new StringBuilder();
 29.1062 -        // TODO:
 29.1063 -        signature.append("<pre>"); // NOI18N
 29.1064 -
 29.1065 -        if (element instanceof IndexedMethod) {
 29.1066 -            IndexedMethod executable = (IndexedMethod)element;
 29.1067 -            if (element.getIn() != null) {
 29.1068 -                String in = element.getIn();
 29.1069 -                signature.append("<i>"); // NOI18N
 29.1070 -                signature.append(in);
 29.1071 -                signature.append("</i>"); // NOI18N
 29.1072 -                signature.append("<br>"); // NOI18N
 29.1073 -            }
 29.1074 -            // TODO - share this between Navigator implementation and here...
 29.1075 -            signature.append("<b>"); // NOI18N
 29.1076 -            signature.append(element.getName());
 29.1077 -            signature.append("</b>"); // NOI18N
 29.1078 -            String[] parameters = executable.getParams();
 29.1079 -
 29.1080 -            if ((parameters != null) && (parameters.length > 0)) {
 29.1081 -                signature.append("("); // NOI18N
 29.1082 -
 29.1083 -                signature.append("<font color=\"#808080\">"); // NOI18N
 29.1084 -
 29.1085 -                boolean first = true;
 29.1086 -                for (String parameter : parameters) {
 29.1087 -                    if (first) {
 29.1088 -                        first = false;
 29.1089 -                    } else {
 29.1090 -                        signature.append(", "); // NOI18N
 29.1091 -                    }
 29.1092 -                    signature.append(parameter);
 29.1093 -                }
 29.1094 -
 29.1095 -                signature.append("</font>"); // NOI18N
 29.1096 -
 29.1097 -                signature.append(")"); // NOI18N
 29.1098 -            }
 29.1099 -        } else if (element instanceof IndexedElement) {
 29.1100 -//            IndexedElement clz = (IndexedElement)element;
 29.1101 -            String name = element.getName();
 29.1102 -//            final String fqn = clz.getFqn();
 29.1103 -//            if (fqn != null && !name.equals(fqn)) {
 29.1104 -//                signature.append("<i>"); // NOI18N
 29.1105 -//                signature.append(fqn); // NOI18N
 29.1106 -//                signature.append("</i>"); // NOI18N
 29.1107 -//                signature.append("<br>"); // NOI18N
 29.1108 -//            }
 29.1109 -            signature.append("<b>"); // NOI18N
 29.1110 -            signature.append(name);
 29.1111 -            signature.append("</b>"); // NOI18N
 29.1112 -        } else {
 29.1113 -            signature.append(element.getName());
 29.1114 -        }
 29.1115 -
 29.1116 -        signature.append("</pre>\n"); // NOI18N
 29.1117 -
 29.1118 -        return signature.toString();
 29.1119 -    }
 29.1120 -
 29.1121 -    @SuppressWarnings("unchecked")
 29.1122 -    private String getPythonHtml(List<String> source, boolean addPre) {
 29.1123 -        StringBuilder python = new StringBuilder(500);
 29.1124 -
 29.1125 -        for (String s : source) {
 29.1126 -            python.append(s);
 29.1127 -            python.append("\n"); // NOI18N
 29.1128 -        }
 29.1129 -
 29.1130 -        Language<?> language = PythonTokenId.language();
 29.1131 -        String mimeType = PythonMIMEResolver.PYTHON_MIME_TYPE;
 29.1132 -        // TODO - handle YAML and other languages I can see in the documentation...
 29.1133 -        /*if (python.indexOf(" <%") != -1) { // NOI18N
 29.1134 -        mimeType = "application/x-httpd-eruby"; // RHTML
 29.1135 -        Collection<LanguageProvider> providers = (Collection<LanguageProvider>) Lookup.getDefault().lookupAll(LanguageProvider.class);
 29.1136 -        for (LanguageProvider provider : providers) {
 29.1137 -        language = provider.findLanguage(mimeType);
 29.1138 -        if (language != null) {
 29.1139 -        break;
 29.1140 -        }
 29.1141 -        }
 29.1142 -
 29.1143 -        if (language == null) {
 29.1144 -        mimeType = PythonTokenId.PYTHON_MIME_TYPE;
 29.1145 -        language = PythonTokenId.language();
 29.1146 -        }
 29.1147 -        } else*/ if (source.get(0).trim().startsWith("<")) {
 29.1148 -            // Looks like markup (other than RHTML) - don't colorize it
 29.1149 -            // since we don't know how
 29.1150 -            return null;
 29.1151 -        }
 29.1152 -
 29.1153 -        StringBuilder buffer = new StringBuilder(1500);
 29.1154 -
 29.1155 -        boolean errors = appendSequence(buffer, python.toString(), language, mimeType, addPre);
 29.1156 -        return errors ? null : buffer.toString();
 29.1157 -    }
 29.1158 -
 29.1159 -    @SuppressWarnings("unchecked")
 29.1160 -    private boolean appendSequence(StringBuilder sb, String text,
 29.1161 -            Language<?> language, String mimeType, boolean addPre) {
 29.1162 -        // XXX is this getting called twice?
 29.1163 -        MimePath mimePath = MimePath.parse(mimeType);
 29.1164 -        Lookup lookup = MimeLookup.getLookup(mimePath);
 29.1165 -        FontColorSettings fcs = lookup.lookup(FontColorSettings.class);
 29.1166 -
 29.1167 -        if (addPre) {
 29.1168 -            sb.append("<pre style=\""); // NOI18N
 29.1169 -
 29.1170 -            sb.append("border-color: #dddddd; border-style: solid; border-width: 1px; ");
 29.1171 -
 29.1172 -            AttributeSet attribs = fcs.getTokenFontColors("default"); // NOI18N
 29.1173 -            Color fg = (Color)attribs.getAttribute(StyleConstants.Foreground);
 29.1174 -            if (fg != null) {
 29.1175 -                sb.append("color:"); // NOI18N
 29.1176 -                sb.append(getHtmlColor(fg));
 29.1177 -                sb.append(";"); // NOI18N
 29.1178 -            }
 29.1179 -            Color bg = (Color)attribs.getAttribute(StyleConstants.Background);
 29.1180 -            // Only set the background for dark colors
 29.1181 -            if (bg != null && bg.getRed() < 128) {
 29.1182 -                sb.append("background:"); // NOI18N
 29.1183 -                sb.append(getHtmlColor(bg));
 29.1184 -            }
 29.1185 -
 29.1186 -            sb.append("\">\n"); // NOI18N
 29.1187 -        }
 29.1188 -        TokenHierarchy hi = TokenHierarchy.create(text, language);
 29.1189 -        TokenSequence ts = hi.tokenSequence();
 29.1190 -
 29.1191 -        int offset = 0;
 29.1192 -        ts.move(offset);
 29.1193 -
 29.1194 -        if (ts.moveNext()) {
 29.1195 -            do {
 29.1196 -                Token t = ts.token();
 29.1197 -                String tokenText = t.text().toString();
 29.1198 -
 29.1199 -                // TODO - make style classes instead of inlining everything as font!
 29.1200 -                String category = t.id().name();
 29.1201 -                String primaryCategory = t.id().primaryCategory();
 29.1202 -
 29.1203 -                if ("error".equals(primaryCategory)) { // NOI18N
 29.1204 -                    // Abort: an error token means the output probably isn't
 29.1205 -                    // code, or it's code or markup but in a different language
 29.1206 -                    // than we're trying to process it as
 29.1207 -                    return true;
 29.1208 -                }
 29.1209 -
 29.1210 -                AttributeSet attribs = fcs.getTokenFontColors(category);
 29.1211 -                String escapedText = tokenText;
 29.1212 -                try {
 29.1213 -                    escapedText = XMLUtil.toElementContent(tokenText);
 29.1214 -                } catch (CharConversionException cce) {
 29.1215 -                    Exceptions.printStackTrace(cce);
 29.1216 -                }
 29.1217 -
 29.1218 -                if (attribs == null) {
 29.1219 -                    category = primaryCategory;
 29.1220 -                    attribs = fcs.getTokenFontColors(category);
 29.1221 -
 29.1222 -                }
 29.1223 -
 29.1224 -                TokenSequence embedded = ts.embedded();
 29.1225 -                if (embedded != null) {
 29.1226 -                    //embedded.languagePath().mimePath();
 29.1227 -                    String embeddedMimeType = MimePath.parse(embedded.languagePath().mimePath()).getPath();
 29.1228 -                    Color bg = null;
 29.1229 -                    Color fg = null;
 29.1230 -                    if (attribs != null) {
 29.1231 -                        bg = (Color)attribs.getAttribute(StyleConstants.Background);
 29.1232 -                        fg = (Color)attribs.getAttribute(StyleConstants.Foreground);
 29.1233 -                        if (fg != null || bg != null) {
 29.1234 -                            sb.append("<span style=\"");
 29.1235 -                            if (bg != null) {
 29.1236 -                                sb.append("background:"); // NOI18N
 29.1237 -                                sb.append(getHtmlColor(bg));
 29.1238 -                                sb.append(";");
 29.1239 -                            }
 29.1240 -                            if (fg != null) {
 29.1241 -                                sb.append("color:"); // NOI18N
 29.1242 -                                sb.append(getHtmlColor(fg));
 29.1243 -                            }
 29.1244 -                            sb.append("\">"); // NOI18N
 29.1245 -                        }
 29.1246 -                    }
 29.1247 -                    appendSequence(sb, tokenText, embedded.language(), embeddedMimeType, false);
 29.1248 -                    if (fg != null || bg != null) {
 29.1249 -                        sb.append("</span>"); // NOI18N
 29.1250 -                    }
 29.1251 -                    continue;
 29.1252 -                }
 29.1253 -
 29.1254 -                if (attribs == null) {
 29.1255 -                    sb.append(escapedText);
 29.1256 -
 29.1257 -                    continue;
 29.1258 -                }
 29.1259 -
 29.1260 -                if (escapedText.indexOf('\n') != -1) {
 29.1261 -                    escapedText = escapedText.replace("\n", "<br>"); // NOI18N
 29.1262 -                }
 29.1263 -
 29.1264 -                if (t.id() == PythonTokenId.WHITESPACE) {
 29.1265 -                    sb.append(escapedText);
 29.1266 -                } else {
 29.1267 -                    sb.append("<span style=\""); // NOI18N
 29.1268 -
 29.1269 -                    Color fg = (Color)attribs.getAttribute(StyleConstants.Foreground);
 29.1270 -
 29.1271 -                    if (fg != null) {
 29.1272 -                        sb.append("color:"); // NOI18N
 29.1273 -                        sb.append(getHtmlColor(fg));
 29.1274 -                        sb.append(";"); // NOI18N
 29.1275 -                    }
 29.1276 -
 29.1277 -                    Color bg = (Color)attribs.getAttribute(StyleConstants.Background);
 29.1278 -
 29.1279 -                    if (bg != null) {
 29.1280 -                        sb.append("background:"); // NOI18N
 29.1281 -                        sb.append(getHtmlColor(bg));
 29.1282 -                        sb.append(";"); // NOI18NP
 29.1283 -                    }
 29.1284 -
 29.1285 -                    Boolean b = (Boolean)attribs.getAttribute(StyleConstants.Bold);
 29.1286 -
 29.1287 -                    if ((b != null) && b) {
 29.1288 -                        sb.append("font-weight:bold;"); // NOI18N
 29.1289 -                    }
 29.1290 -
 29.1291 -                    b = (Boolean)attribs.getAttribute(StyleConstants.Italic);
 29.1292 -
 29.1293 -                    if ((b != null) && b) {
 29.1294 -                        sb.append("font-style:italic;"); // NOI18N
 29.1295 -                    }
 29.1296 -
 29.1297 -                    // TODO - underline, strikethrough, ... and FONTS!
 29.1298 -                    sb.append("\">"); // NOI18N
 29.1299 -                    sb.append(escapedText);
 29.1300 -                    sb.append("</span>"); // NOI18N
 29.1301 -                }
 29.1302 -            } while (ts.moveNext());
 29.1303 -        }
 29.1304 -
 29.1305 -        if (addPre) {
 29.1306 -            sb.append("</pre>\n");
 29.1307 -        }
 29.1308 -
 29.1309 -        return false;
 29.1310 -    }
 29.1311 -
 29.1312 -
 29.1313 -    // TODO - move to GsfUtilities?
 29.1314 -    private static String getHtmlColor(Color c) {
 29.1315 -        int r = c.getRed();
 29.1316 -        int g = c.getGreen();
 29.1317 -        int b = c.getBlue();
 29.1318 -        StringBuffer result = new StringBuffer();
 29.1319 -        result.append('#');
 29.1320 -
 29.1321 -        String rs = Integer.toHexString(r);
 29.1322 -        String gs = Integer.toHexString(g);
 29.1323 -        String bs = Integer.toHexString(b);
 29.1324 -
 29.1325 -        if (r < 0x10) {
 29.1326 -            result.append('0');
 29.1327 -        }
 29.1328 -
 29.1329 -        result.append(rs);
 29.1330 -
 29.1331 -        if (g < 0x10) {
 29.1332 -            result.append('0');
 29.1333 -        }
 29.1334 -
 29.1335 -        result.append(gs);
 29.1336 -
 29.1337 -        if (b < 0x10) {
 29.1338 -            result.append('0');
 29.1339 -        }
 29.1340 -
 29.1341 -        result.append(bs);
 29.1342 -
 29.1343 -        return result.toString();
 29.1344 -    }
 29.1345 -}
    30.1 --- a/python.editor/src/org/netbeans/modules/python/editor/codecoverage/PythonCoverageProvider.java	Sat Sep 12 23:03:15 2015 -0700
    30.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/codecoverage/PythonCoverageProvider.java	Sun Sep 13 11:47:42 2015 +0200
    30.3 @@ -74,8 +74,8 @@
    30.4  import org.netbeans.modules.gsf.codecoverage.api.FileCoverageSummary;
    30.5  import org.netbeans.modules.python.api.PythonExecution;
    30.6  import org.netbeans.modules.python.api.PythonMIMEResolver;
    30.7 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
    30.8 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
    30.9 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
   30.10 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
   30.11  import org.openide.filesystems.FileObject;
   30.12  import org.openide.filesystems.FileUtil;
   30.13  import org.openide.modules.InstalledFileLocator;
    31.1 --- a/python.editor/src/org/netbeans/modules/python/editor/codegen/ClassCodeGenerator.java	Sat Sep 12 23:03:15 2015 -0700
    31.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/codegen/ClassCodeGenerator.java	Sun Sep 13 11:47:42 2015 +0200
    31.3 @@ -46,7 +46,7 @@
    31.4  import javax.swing.text.JTextComponent;
    31.5  import org.netbeans.editor.BaseDocument;
    31.6  import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager;
    31.7 -import org.netbeans.modules.python.editor.PythonUtils;
    31.8 +import org.netbeans.modules.python.source.PythonUtils;
    31.9  import org.netbeans.spi.editor.codegen.CodeGenerator;
   31.10  import org.netbeans.spi.editor.codegen.CodeGeneratorContextProvider;
   31.11  import org.openide.util.Lookup;
   31.12 @@ -119,7 +119,7 @@
   31.13          final BaseDocument doc = (BaseDocument)target.getDocument();
   31.14          final CodeTemplateManager ctm = CodeTemplateManager.get(doc);
   31.15          if (ctm != null) {
   31.16 -            String template = PythonUtils.getCodeTemplate(ctm, "cls", "class ", null); // NOI18N
   31.17 +            String template = CodeGenUtils.getCodeTemplate(ctm, "cls", "class ", null); // NOI18N
   31.18              if (template == null) {
   31.19                  template = "class ${name}${1 default=\"(Extends)\"}:\n${initialindent editable=\"false\"}${indent editable=\"false\"}\"\"\"\n${initialindent editable=\"false\"}${indent editable=\"false\"}${Documentation}\n${initialindent editable=\"false\"}${indent editable=\"false\"}\"\"\"\n${initialindent editable=\"false\"}${indent editable=\"false\"}${cursor}\n";
   31.20              }
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/codegen/CodeGenUtils.java	Sun Sep 13 11:47:42 2015 +0200
    32.3 @@ -0,0 +1,77 @@
    32.4 +/*
    32.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    32.6 + *
    32.7 + * Copyright 2015 Oracle and/or its affiliates. All rights reserved.
    32.8 + *
    32.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   32.10 + * Other names may be trademarks of their respective owners.
   32.11 + *
   32.12 + * The contents of this file are subject to the terms of either the GNU
   32.13 + * General Public License Version 2 only ("GPL") or the Common
   32.14 + * Development and Distribution License("CDDL") (collectively, the
   32.15 + * "License"). You may not use this file except in compliance with the
   32.16 + * License. You can obtain a copy of the License at
   32.17 + * http://www.netbeans.org/cddl-gplv2.html
   32.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   32.19 + * specific language governing permissions and limitations under the
   32.20 + * License.  When distributing the software, include this License Header
   32.21 + * Notice in each file and include the License file at
   32.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   32.23 + * particular file as subject to the "Classpath" exception as provided
   32.24 + * by Oracle in the GPL Version 2 section of the License file that
   32.25 + * accompanied this code. If applicable, add the following below the
   32.26 + * License Header, with the fields enclosed by brackets [] replaced by
   32.27 + * your own identifying information:
   32.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   32.29 + *
   32.30 + * If you wish your version of this file to be governed by only the CDDL
   32.31 + * or only the GPL Version 2, indicate your decision by adding
   32.32 + * "[Contributor] elects to include this software in this distribution
   32.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   32.34 + * single choice of license, a recipient has the option to distribute
   32.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   32.36 + * to extend the choice of license to its licensees as provided above.
   32.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   32.38 + * Version 2 license, then the option applies only if the new code is
   32.39 + * made subject to such option by the copyright holder.
   32.40 + *
   32.41 + * Contributor(s):
   32.42 + *
   32.43 + * Portions Copyrighted 2015 Sun Microsystems, Inc.
   32.44 + */
   32.45 +package org.netbeans.modules.python.editor.codegen;
   32.46 +
   32.47 +import org.netbeans.lib.editor.codetemplates.api.CodeTemplate;
   32.48 +import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager;
   32.49 +
   32.50 +/**
   32.51 + *
   32.52 + * @author Ralph Ruijs
   32.53 + */
   32.54 +public final class CodeGenUtils {
   32.55 +
   32.56 +    private CodeGenUtils() {
   32.57 +    }
   32.58 +    
   32.59 +    public static String getCodeTemplate(CodeTemplateManager ctm, String abbrev, String textPrefix, String wrongTextPrefix) {
   32.60 +        String templateText = null;
   32.61 +        for (CodeTemplate t : ctm.getCodeTemplates()) {
   32.62 +            if (abbrev.equals(t.getAbbreviation())) {
   32.63 +                templateText = t.getParametrizedText();
   32.64 +                break;
   32.65 +            }
   32.66 +        }
   32.67 +        if (templateText == null) {
   32.68 +            for (CodeTemplate t : ctm.getCodeTemplates()) {
   32.69 +                String text = t.getParametrizedText();
   32.70 +                if (text.startsWith(textPrefix) && (wrongTextPrefix == null || !text.startsWith(wrongTextPrefix))) {
   32.71 +                    templateText = text;
   32.72 +                    break;
   32.73 +                }
   32.74 +            }
   32.75 +        }
   32.76 +
   32.77 +        return templateText;
   32.78 +    }
   32.79 +
   32.80 +}
    33.1 --- a/python.editor/src/org/netbeans/modules/python/editor/codegen/ConstructorGenerator.java	Sat Sep 12 23:03:15 2015 -0700
    33.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/codegen/ConstructorGenerator.java	Sun Sep 13 11:47:42 2015 +0200
    33.3 @@ -46,7 +46,7 @@
    33.4  import javax.swing.text.JTextComponent;
    33.5  import org.netbeans.editor.BaseDocument;
    33.6  import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager;
    33.7 -import org.netbeans.modules.python.editor.PythonUtils;
    33.8 +import org.netbeans.modules.python.source.PythonUtils;
    33.9  import org.netbeans.spi.editor.codegen.CodeGenerator;
   33.10  import org.openide.util.Lookup;
   33.11  import org.openide.util.NbBundle;
   33.12 @@ -80,7 +80,7 @@
   33.13          final BaseDocument doc = (BaseDocument)target.getDocument();
   33.14          final CodeTemplateManager ctm = CodeTemplateManager.get(doc);
   33.15          if (ctm != null) {
   33.16 -            String template = PythonUtils.getCodeTemplate(ctm, "init", "def __init__", null); // NOI18N
   33.17 +            String template = CodeGenUtils.getCodeTemplate(ctm, "init", "def __init__", null); // NOI18N
   33.18              if (template == null) {
   33.19                  template = "def __init__(self${1 default=\", parameters\"}):\n        ${cursor})"; // NOI18N
   33.20              }
    34.1 --- a/python.editor/src/org/netbeans/modules/python/editor/codegen/MethodCodeGenerator.java	Sat Sep 12 23:03:15 2015 -0700
    34.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/codegen/MethodCodeGenerator.java	Sun Sep 13 11:47:42 2015 +0200
    34.3 @@ -46,7 +46,7 @@
    34.4  import javax.swing.text.JTextComponent;
    34.5  import org.netbeans.editor.BaseDocument;
    34.6  import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager;
    34.7 -import org.netbeans.modules.python.editor.PythonUtils;
    34.8 +import org.netbeans.modules.python.source.PythonUtils;
    34.9  import org.netbeans.spi.editor.codegen.CodeGenerator;
   34.10  import org.netbeans.spi.editor.codegen.CodeGeneratorContextProvider;
   34.11  import org.openide.util.Lookup;
   34.12 @@ -117,7 +117,7 @@
   34.13          final BaseDocument doc = (BaseDocument)target.getDocument();
   34.14          final CodeTemplateManager ctm = CodeTemplateManager.get(doc);
   34.15          if (ctm != null) {
   34.16 -            String template = PythonUtils.getCodeTemplate(ctm, "def", "def ", "def __"); // NOI18N
   34.17 +            String template = CodeGenUtils.getCodeTemplate(ctm, "def", "def ", "def __"); // NOI18N
   34.18              if (template == null) {
   34.19                  template="def ${name}(${1 default=\"parameters\"}):\n${initialindent editable=\"false\"}${indent editable=\"false\"}\"\"\"${Documentation}\"\"\"\n${initialindent editable=\"false\"}${indent editable=\"false\"}${cursor}\n";
   34.20              }
    35.1 --- a/python.editor/src/org/netbeans/modules/python/editor/elements/AstElement.java	Sat Sep 12 23:03:15 2015 -0700
    35.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.3 @@ -1,117 +0,0 @@
    35.4 -/*
    35.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    35.6 - *
    35.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    35.8 - *
    35.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   35.10 - * Other names may be trademarks of their respective owners.
   35.11 - *
   35.12 - * The contents of this file are subject to the terms of either the GNU
   35.13 - * General Public License Version 2 only ("GPL") or the Common
   35.14 - * Development and Distribution License("CDDL") (collectively, the
   35.15 - * "License"). You may not use this file except in compliance with the
   35.16 - * License. You can obtain a copy of the License at
   35.17 - * http://www.netbeans.org/cddl-gplv2.html
   35.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   35.19 - * specific language governing permissions and limitations under the
   35.20 - * License.  When distributing the software, include this License Header
   35.21 - * Notice in each file and include the License file at
   35.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   35.23 - * particular file as subject to the "Classpath" exception as provided
   35.24 - * by Oracle in the GPL Version 2 section of the License file that
   35.25 - * accompanied this code. If applicable, add the following below the
   35.26 - * License Header, with the fields enclosed by brackets [] replaced by
   35.27 - * your own identifying information:
   35.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   35.29 - *
   35.30 - * Contributor(s):
   35.31 - *
   35.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   35.33 - */
   35.34 -package org.netbeans.modules.python.editor.elements;
   35.35 -
   35.36 -import java.util.Set;
   35.37 -import org.netbeans.modules.csl.api.ElementKind;
   35.38 -import org.netbeans.modules.csl.api.Modifier;
   35.39 -import org.netbeans.modules.csl.api.OffsetRange;
   35.40 -import org.netbeans.modules.csl.spi.ParserResult;
   35.41 -import org.netbeans.modules.python.editor.PythonAstUtils;
   35.42 -import org.netbeans.modules.python.editor.PythonParserResult;
   35.43 -import org.netbeans.modules.python.editor.PythonStructureItem;
   35.44 -import org.netbeans.modules.python.editor.PythonStructureScanner;
   35.45 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
   35.46 -import org.python.antlr.PythonTree;
   35.47 -import org.python.antlr.ast.Call;
   35.48 -import org.python.antlr.ast.ClassDef;
   35.49 -import org.python.antlr.ast.FunctionDef;
   35.50 -import org.python.antlr.ast.Name;
   35.51 -
   35.52 -/**
   35.53 - * Elements representing a node in a parse tree
   35.54 - *
   35.55 - * @author Tor Norbye
   35.56 - */
   35.57 -public class AstElement extends Element {
   35.58 -    protected PythonTree node;
   35.59 -    protected String name;
   35.60 -    protected ElementKind kind;
   35.61 -    //protected CompilationInfo info;
   35.62 -    protected Set<Modifier> modifiers;
   35.63 -    protected SymbolTable scopes;
   35.64 -
   35.65 -    public AstElement(SymbolTable scopes, PythonTree node, String name, ElementKind kind) {
   35.66 -        //this.info = info;
   35.67 -        this.scopes = scopes;
   35.68 -        this.node = node;
   35.69 -        this.name = name;
   35.70 -        this.kind = kind;
   35.71 -    }
   35.72 -
   35.73 -    public static AstElement create(PythonParserResult result, PythonTree node) {
   35.74 -        SymbolTable scopes = result.getSymbolTable();
   35.75 -
   35.76 -        if (node instanceof FunctionDef) {
   35.77 -            return new PythonStructureItem(scopes, (FunctionDef)node);
   35.78 -        } else if (node instanceof ClassDef) {
   35.79 -            return new PythonStructureItem(scopes, (ClassDef)node);
   35.80 -        } else if (node instanceof Call) {
   35.81 -            String name = PythonAstUtils.getCallName((Call)node);
   35.82 -            return new AstElement(scopes, node, name, ElementKind.METHOD);
   35.83 -        } else if (node instanceof Name) {
   35.84 -            return new AstElement(scopes, node, ((Name)node).getInternalId(), ElementKind.VARIABLE);
   35.85 -        } else {
   35.86 -            return new AstElement(scopes, node, null, ElementKind.OTHER);
   35.87 -        }
   35.88 -    }
   35.89 -
   35.90 -    public PythonTree getNode() {
   35.91 -        return node;
   35.92 -    }
   35.93 -
   35.94 -    @Override
   35.95 -    public String getName() {
   35.96 -        return name;
   35.97 -    }
   35.98 -
   35.99 -    @Override
  35.100 -    public ElementKind getKind() {
  35.101 -        return kind;
  35.102 -    }
  35.103 -
  35.104 -    @Override
  35.105 -    public Set<Modifier> getModifiers() {
  35.106 -        if (modifiers == null) {
  35.107 -            if (name != null && scopes.isPrivate(node, name)) {
  35.108 -                modifiers = IndexedElement.PRIVATE_MODIFIERS;
  35.109 -            } else {
  35.110 -                modifiers = IndexedElement.PUBLIC_MODIFIERS;
  35.111 -            }
  35.112 -        }
  35.113 -
  35.114 -        return modifiers;
  35.115 -    }
  35.116 -
  35.117 -    public Object getSignature() {
  35.118 -        return name;
  35.119 -    }
  35.120 -}
    36.1 --- a/python.editor/src/org/netbeans/modules/python/editor/elements/Element.java	Sat Sep 12 23:03:15 2015 -0700
    36.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.3 @@ -1,85 +0,0 @@
    36.4 -/*
    36.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    36.6 - *
    36.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    36.8 - *
    36.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   36.10 - * Other names may be trademarks of their respective owners.
   36.11 - *
   36.12 - * The contents of this file are subject to the terms of either the GNU
   36.13 - * General Public License Version 2 only ("GPL") or the Common
   36.14 - * Development and Distribution License("CDDL") (collectively, the
   36.15 - * "License"). You may not use this file except in compliance with the
   36.16 - * License. You can obtain a copy of the License at
   36.17 - * http://www.netbeans.org/cddl-gplv2.html
   36.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   36.19 - * specific language governing permissions and limitations under the
   36.20 - * License.  When distributing the software, include this License Header
   36.21 - * Notice in each file and include the License file at
   36.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   36.23 - * particular file as subject to the "Classpath" exception as provided
   36.24 - * by Oracle in the GPL Version 2 section of the License file that
   36.25 - * accompanied this code. If applicable, add the following below the
   36.26 - * License Header, with the fields enclosed by brackets [] replaced by
   36.27 - * your own identifying information:
   36.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   36.29 - *
   36.30 - * Contributor(s):
   36.31 - *
   36.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   36.33 - */
   36.34 -package org.netbeans.modules.python.editor.elements;
   36.35 -
   36.36 -import java.util.Collections;
   36.37 -import java.util.Set;
   36.38 -import org.netbeans.modules.csl.api.ElementHandle;
   36.39 -import org.netbeans.modules.csl.api.ElementKind;
   36.40 -import org.netbeans.modules.csl.api.Modifier;
   36.41 -import org.netbeans.modules.csl.api.OffsetRange;
   36.42 -import org.netbeans.modules.csl.spi.ParserResult;
   36.43 -import org.netbeans.modules.python.api.PythonMIMEResolver;
   36.44 -import org.openide.filesystems.FileObject;
   36.45 -
   36.46 -/**
   36.47 - *
   36.48 - * @author Tor Norbye
   36.49 - */
   36.50 -public abstract class Element implements ElementHandle {
   36.51 -    @Override
   36.52 -    public abstract String getName();
   36.53 -
   36.54 -    @Override
   36.55 -    public abstract ElementKind getKind();
   36.56 -
   36.57 -    @Override
   36.58 -    public String getMimeType() {
   36.59 -        return PythonMIMEResolver.PYTHON_MIME_TYPE;
   36.60 -    }
   36.61 -
   36.62 -    @Override
   36.63 -    public boolean signatureEquals(ElementHandle handle) {
   36.64 -        // XXX TODO
   36.65 -        return false;
   36.66 -    }
   36.67 -
   36.68 -    @Override
   36.69 -    public OffsetRange getOffsetRange(ParserResult pr) {
   36.70 -        // XXX TODO
   36.71 -        return null;
   36.72 -    }
   36.73 -
   36.74 -    @Override
   36.75 -    public FileObject getFileObject() {
   36.76 -        return null;
   36.77 -    }
   36.78 -
   36.79 -    @Override
   36.80 -    public Set<Modifier> getModifiers() {
   36.81 -        return Collections.emptySet();
   36.82 -    }
   36.83 -
   36.84 -    @Override
   36.85 -    public String getIn() {
   36.86 -        return null;
   36.87 -    }
   36.88 -}
    37.1 --- a/python.editor/src/org/netbeans/modules/python/editor/elements/IndexedElement.java	Sat Sep 12 23:03:15 2015 -0700
    37.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.3 @@ -1,527 +0,0 @@
    37.4 -/*
    37.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    37.6 - *
    37.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    37.8 - *
    37.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   37.10 - * Other names may be trademarks of their respective owners.
   37.11 - *
   37.12 - * The contents of this file are subject to the terms of either the GNU
   37.13 - * General Public License Version 2 only ("GPL") or the Common
   37.14 - * Development and Distribution License("CDDL") (collectively, the
   37.15 - * "License"). You may not use this file except in compliance with the
   37.16 - * License. You can obtain a copy of the License at
   37.17 - * http://www.netbeans.org/cddl-gplv2.html
   37.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   37.19 - * specific language governing permissions and limitations under the
   37.20 - * License.  When distributing the software, include this License Header
   37.21 - * Notice in each file and include the License file at
   37.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   37.23 - * particular file as subject to the "Classpath" exception as provided
   37.24 - * by Oracle in the GPL Version 2 section of the License file that
   37.25 - * accompanied this code. If applicable, add the following below the
   37.26 - * License Header, with the fields enclosed by brackets [] replaced by
   37.27 - * your own identifying information:
   37.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   37.29 - *
   37.30 - * Contributor(s):
   37.31 - *
   37.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   37.33 - */
   37.34 -package org.netbeans.modules.python.editor.elements;
   37.35 -
   37.36 -import java.util.Collections;
   37.37 -import java.util.EnumSet;
   37.38 -import java.util.Set;
   37.39 -import org.netbeans.modules.csl.api.ElementKind;
   37.40 -import org.netbeans.modules.csl.api.Modifier;
   37.41 -import org.netbeans.modules.csl.api.OffsetRange;
   37.42 -import org.netbeans.modules.csl.spi.ParserResult;
   37.43 -import org.netbeans.modules.python.editor.PythonIndex;
   37.44 -import org.netbeans.modules.python.editor.PythonAstUtils;
   37.45 -import org.openide.filesystems.FileObject;
   37.46 -import org.python.antlr.PythonTree;
   37.47 -
   37.48 -/**
   37.49 - * Elements representing information coming from the persistent index
   37.50 - *
   37.51 - * @author Tor Norbye
   37.52 - */
   37.53 -public class IndexedElement extends Element {
   37.54 -    public static final EnumSet<Modifier> PRIVATE_MODIFIERS = EnumSet.of(Modifier.PRIVATE);
   37.55 -    public static final EnumSet<Modifier> PROTECTED_MODIFIERS = EnumSet.of(Modifier.PROTECTED);
   37.56 -    public static final EnumSet<Modifier> STATIC_MODIFIERS = EnumSet.of(Modifier.STATIC);
   37.57 -    public static final EnumSet<Modifier> PRIVATE_STATIC_MODIFIERS = EnumSet.of(Modifier.STATIC, Modifier.PRIVATE);
   37.58 -    public static final EnumSet<Modifier> PROTECTED_STATIC_MODIFIERS = EnumSet.of(Modifier.STATIC, Modifier.PROTECTED);
   37.59 -    public static final Set<Modifier> PUBLIC_MODIFIERS = Collections.emptySet();
   37.60 -
   37.61 -    // Plan: Stash a single item for class entries so I can search by document for the class.
   37.62 -    // Add more types into the types
   37.63 -    /** This method is documented */
   37.64 -    public static final int DOCUMENTED = 1 << 0;
   37.65 -    /** This method is private */
   37.66 -    public static final int PRIVATE = 1 << 2;
   37.67 -    /** This is a function, not a property */
   37.68 -    public static final int FUNCTION = 1 << 3;
   37.69 -    /** This element is "static" (e.g. it's a classvar for fields, class method for methods etc) */
   37.70 -    public static final int STATIC = 1 << 4;
   37.71 -    /** This element is deliberately not documented (rdoc :nodoc:) */
   37.72 -    public static final int NODOC = 1 << 5;
   37.73 -    /** This is a global variable */
   37.74 -    public static final int GLOBAL = 1 << 6;
   37.75 -    /** This is a constructor */
   37.76 -    public static final int CONSTRUCTOR = 1 << 7;
   37.77 -    /** This is a deprecated */
   37.78 -    public static final int DEPRECATED = 1 << 8;
   37.79 -    /** This is a documentation-only definition */
   37.80 -    public static final int DOC_ONLY = 1 << 9;
   37.81 -    /** This is a constant/final */
   37.82 -    public static final int FINAL = 1 << 10;
   37.83 -
   37.84 -    // Flags noting semicolon positions in attributes
   37.85 -    public static final int NAME_INDEX = 0;
   37.86 -    public static final int TYPE_INDEX = 1;
   37.87 -    public static final int FLAG_INDEX = 2;
   37.88 -    public static final int ARG_INDEX = 3;
   37.89 -//    public static final int IN_INDEX = 1;
   37.90 -//    public static final int CASE_SENSITIVE_INDEX = 2;
   37.91 -//    public static final int FLAG_INDEX = 3;
   37.92 -//    public static final int ARG_INDEX = 4;
   37.93 -//    public static final int NODE_INDEX = 5;
   37.94 -//    public static final int DOC_INDEX = 6;
   37.95 -//    public static final int BROWSER_INDEX = 7;
   37.96 -//    public static final int TYPE_INDEX = 8;
   37.97 -    protected final String name;
   37.98 -    protected final ElementKind kind;
   37.99 -    protected String url;
  37.100 -    protected FileObject fileObject;
  37.101 -    protected final String module;
  37.102 -    protected String rhs;
  37.103 -    protected boolean smart;
  37.104 -    protected boolean inherited;
  37.105 -    protected Set<Modifier> modifiers;
  37.106 -    protected PythonTree node;
  37.107 -    protected int flags;
  37.108 -    protected final String attributes;
  37.109 -    protected final String clz;
  37.110 -    protected int order;
  37.111 -
  37.112 -    public IndexedElement(String name, ElementKind kind, String url, String module, String clz, String attributes) {
  37.113 -        this.name = name;
  37.114 -        this.kind = kind;
  37.115 -        this.url = url;
  37.116 -        this.module = module;
  37.117 -        this.clz = clz;
  37.118 -        this.attributes = attributes;
  37.119 -
  37.120 -    // Should be IndexedMethod:
  37.121 -    //assert !((!(this instanceof IndexedMethod)) && (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR)) : this;
  37.122 -    }
  37.123 -
  37.124 -    public static IndexedElement create(String signature, String module, String url, String clz) {
  37.125 -        int semi = signature.indexOf(';');
  37.126 -        assert semi != -1;
  37.127 -
  37.128 -        String name = signature.substring(0, semi);
  37.129 -        int flags = IndexedElement.decode(signature, semi + 3, 0);
  37.130 -
  37.131 -        char type = signature.charAt(semi + 1);
  37.132 -        ElementKind kind;
  37.133 -        switch (type) {
  37.134 -        case 'C':
  37.135 -            kind = ElementKind.CLASS;
  37.136 -            break;
  37.137 -        case 'I':
  37.138 -            kind = ElementKind.MODULE;
  37.139 -            break;
  37.140 -        case 'D':
  37.141 -            kind = ElementKind.VARIABLE;
  37.142 -            break;
  37.143 -        case 'A':
  37.144 -            kind = ElementKind.ATTRIBUTE;
  37.145 -            break;
  37.146 -        case 'F':
  37.147 -        case 'M':
  37.148 -        case 'c': {
  37.149 -            kind = type == 'c' ? ElementKind.CONSTRUCTOR : ElementKind.METHOD;
  37.150 -            IndexedMethod method = new IndexedMethod(name, kind, url, module, clz, signature);
  37.151 -            method.flags = flags;
  37.152 -            return method;
  37.153 -        }
  37.154 -        default:
  37.155 -            kind = ElementKind.OTHER;
  37.156 -            break;
  37.157 -        }
  37.158 -
  37.159 -        IndexedElement element = new IndexedElement(name, kind, url, module, clz, signature);
  37.160 -        element.flags = flags;
  37.161 -        return element;
  37.162 -    }
  37.163 -
  37.164 -    @Override
  37.165 -    public boolean equals(Object obj) {
  37.166 -        if (obj == null) {
  37.167 -            return false;
  37.168 -        }
  37.169 -        if (getClass() != obj.getClass()) {
  37.170 -            return false;
  37.171 -        }
  37.172 -        final IndexedElement other = (IndexedElement)obj;
  37.173 -        if (this.name != other.name && (this.name == null || !this.name.equals(other.name))) {
  37.174 -            return false;
  37.175 -        }
  37.176 -        if (this.module != other.module && (this.module == null || !this.module.equals(other.module))) {
  37.177 -            return false;
  37.178 -        }
  37.179 -        if (this.kind != other.kind) {
  37.180 -            return false;
  37.181 -        }
  37.182 -        return true;
  37.183 -    }
  37.184 -
  37.185 -    public String getModule() {
  37.186 -        return module;
  37.187 -    }
  37.188 -
  37.189 -    @Override
  37.190 -    public int hashCode() {
  37.191 -        int hash = 3;
  37.192 -        hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0);
  37.193 -        hash = 67 * hash + (this.kind != null ? this.kind.hashCode() : 0);
  37.194 -        return hash;
  37.195 -    }
  37.196 -
  37.197 -    @Override
  37.198 -    public String getName() {
  37.199 -        return name;
  37.200 -    }
  37.201 -
  37.202 -    @Override
  37.203 -    public ElementKind getKind() {
  37.204 -        return kind;
  37.205 -    }
  37.206 -
  37.207 -    public String getFilenameUrl() {
  37.208 -        return url;
  37.209 -    }
  37.210 -
  37.211 -    @Override
  37.212 -    public FileObject getFileObject() {
  37.213 -        if ((fileObject == null) && (url != null)) {
  37.214 -            fileObject = PythonIndex.getFileObject(url);
  37.215 -
  37.216 -            if (fileObject == null) {
  37.217 -                // Don't try again
  37.218 -                url = null;
  37.219 -            }
  37.220 -        }
  37.221 -
  37.222 -        return fileObject;
  37.223 -    }
  37.224 -
  37.225 -    public void setFlags(int flags) {
  37.226 -        this.flags = flags;
  37.227 -    }
  37.228 -
  37.229 -    public void setInherited(boolean inherited) {
  37.230 -        this.inherited = inherited;
  37.231 -    }
  37.232 -
  37.233 -    public boolean isInherited() {
  37.234 -        return inherited;
  37.235 -    }
  37.236 -
  37.237 -    public String getType() {
  37.238 -        return null;
  37.239 -    }
  37.240 -
  37.241 -    public String getOrigin() {
  37.242 -        return module;
  37.243 -    }
  37.244 -
  37.245 -    public boolean isSmart() {
  37.246 -        return smart;
  37.247 -    }
  37.248 -
  37.249 -    public void setSmart(boolean smart) {
  37.250 -        this.smart = smart;
  37.251 -    }
  37.252 -
  37.253 -    public String getRhs() {
  37.254 -        if (rhs == null) {
  37.255 -            rhs = module;
  37.256 -            if (rhs.equals("stub_missing")) { // NOI18N
  37.257 -                rhs = "<i>builtin</i>";
  37.258 -            }
  37.259 -        }
  37.260 -        return rhs;
  37.261 -    }
  37.262 -
  37.263 -    public void setRhs(String rhs) {
  37.264 -        this.rhs = rhs;
  37.265 -    }
  37.266 -
  37.267 -    @Override
  37.268 -    public String getIn() {
  37.269 -        return module;
  37.270 -    }
  37.271 -
  37.272 -    public String getSignature() {
  37.273 -        if (clz != null) {
  37.274 -            return clz + "." + name;
  37.275 -        }
  37.276 -
  37.277 -        return name;
  37.278 -    }
  37.279 -
  37.280 -    public String getClz() {
  37.281 -        return clz;
  37.282 -    }
  37.283 -
  37.284 -    public int getOrder() {
  37.285 -        return order;
  37.286 -    }
  37.287 -
  37.288 -    public void setOrder(int order) {
  37.289 -        this.order = order;
  37.290 -    }
  37.291 -
  37.292 -    public static Set<Modifier> getModifiersForName(String name, boolean isPrivate, boolean isProtected, boolean isStatic) {
  37.293 -        Set<Modifier> modifiers;
  37.294 -
  37.295 -        // Private variables: start with __ but doesn't end with __
  37.296 -        // Section 9.6 Private Variables - http://docs.python.org/tut/node11.html
  37.297 -        if (name != null && name.startsWith("__") && !name.endsWith("__")) { // NOI18N
  37.298 -            isPrivate = true;
  37.299 -        } else if (name != null && name.startsWith("_") && !name.endsWith("_")) { // NOI18N
  37.300 -            // From PEP8: Single_leading_underscore: weak "internal use" indicator
  37.301 -            // (e.g. "from M import *" does not import objects whose name
  37.302 -            // starts with an underscore).
  37.303 -            // The protected modifier might work well to visually indicate this.
  37.304 -            isProtected = true;
  37.305 -        }
  37.306 -        if (isPrivate) {
  37.307 -            if (isStatic) {
  37.308 -                modifiers = PRIVATE_STATIC_MODIFIERS;
  37.309 -            } else {
  37.310 -                modifiers = PRIVATE_MODIFIERS;
  37.311 -            }
  37.312 -        } else if (isProtected) {
  37.313 -            if (isStatic) {
  37.314 -                modifiers = PROTECTED_STATIC_MODIFIERS;
  37.315 -            } else {
  37.316 -                modifiers = PROTECTED_MODIFIERS;
  37.317 -            }
  37.318 -        } else {
  37.319 -            if (isStatic) {
  37.320 -                modifiers = STATIC_MODIFIERS;
  37.321 -            } else {
  37.322 -                modifiers = PUBLIC_MODIFIERS;
  37.323 -            }
  37.324 -        }
  37.325 -
  37.326 -        return modifiers;
  37.327 -    }
  37.328 -
  37.329 -    @Override
  37.330 -    public Set<Modifier> getModifiers() {
  37.331 -        if (modifiers == null) {
  37.332 -            modifiers = getModifiersForName(name, isPrivate(), false, isStatic());
  37.333 -        }
  37.334 -
  37.335 -        return modifiers;
  37.336 -    }
  37.337 -
  37.338 -    public PythonTree getNode() {
  37.339 -        if (node == null) {
  37.340 -            node = PythonAstUtils.getForeignNode(this, null);
  37.341 -        }
  37.342 -        return node;
  37.343 -    }
  37.344 -
  37.345 -    @Override
  37.346 -    public String toString() {
  37.347 -        return "IndexedElement:" + name + "," + kind + "," + rhs;
  37.348 -    }
  37.349 -
  37.350 -    protected int getAttributeSection(int section) {
  37.351 -        assert section != 0; // Obtain directly, and logic below (+1) is wrong
  37.352 -        int attributeIndex = 0;
  37.353 -        for (int i = 0; i < section; i++) {
  37.354 -            attributeIndex = attributes.indexOf(';', attributeIndex + 1);
  37.355 -        }
  37.356 -
  37.357 -        assert attributeIndex != -1;
  37.358 -        return attributeIndex + 1;
  37.359 -    }
  37.360 -
  37.361 -    /** Return a string (suitable for persistence) encoding the given flags */
  37.362 -    public static String encode(int flags) {
  37.363 -        return Integer.toString(flags, 16);
  37.364 -    }
  37.365 -
  37.366 -    /** Return flag corresponding to the given encoding chars */
  37.367 -    public static int decode(String s, int startIndex, int defaultValue) {
  37.368 -        int value = 0;
  37.369 -        for (int i = startIndex, n = s.length(); i < n; i++) {
  37.370 -            char c = s.charAt(i);
  37.371 -            if (c == ';') {
  37.372 -                if (i == startIndex) {
  37.373 -                    return defaultValue;
  37.374 -                }
  37.375 -                break;
  37.376 -            }
  37.377 -
  37.378 -            value = value << 4;
  37.379 -
  37.380 -            if (c > '9') {
  37.381 -                value += c - 'a' + 10;
  37.382 -            } else {
  37.383 -                value += c - '0';
  37.384 -            }
  37.385 -        }
  37.386 -
  37.387 -        return value;
  37.388 -    }
  37.389 -
  37.390 -    public static int getFlags(AstElement element) {
  37.391 -        // Return the flags corresponding to the given AST element
  37.392 -        int value = 0;
  37.393 -
  37.394 -        ElementKind k = element.getKind();
  37.395 -        if (k == ElementKind.CONSTRUCTOR) {
  37.396 -            value = value | CONSTRUCTOR;
  37.397 -        }
  37.398 -        if (k == ElementKind.METHOD || k == ElementKind.CONSTRUCTOR) {
  37.399 -            value = value | FUNCTION;
  37.400 -        } else if (k == ElementKind.GLOBAL) {
  37.401 -            value = value | GLOBAL;
  37.402 -        }
  37.403 -        if (element.getModifiers().contains(Modifier.STATIC)) {
  37.404 -            value = value | STATIC;
  37.405 -        }
  37.406 -        if (element.getModifiers().contains(Modifier.DEPRECATED)) {
  37.407 -            value = value | DEPRECATED;
  37.408 -        }
  37.409 -        if (element.getModifiers().contains(Modifier.PRIVATE)) {
  37.410 -            value = value | PRIVATE;
  37.411 -        }
  37.412 -
  37.413 -        return value;
  37.414 -    }
  37.415 -
  37.416 -    public boolean isDocumented() {
  37.417 -        return (flags & DOCUMENTED) != 0;
  37.418 -    }
  37.419 -
  37.420 -    public boolean isPublic() {
  37.421 -        return (flags & PRIVATE) == 0;
  37.422 -    }
  37.423 -
  37.424 -    public boolean isPrivate() {
  37.425 -        return (flags & PRIVATE) != 0;
  37.426 -    }
  37.427 -
  37.428 -    public boolean isFunction() {
  37.429 -        return (flags & FUNCTION) != 0;
  37.430 -    }
  37.431 -
  37.432 -    public boolean isStatic() {
  37.433 -        return (flags & STATIC) != 0;
  37.434 -    }
  37.435 -
  37.436 -    public boolean isNoDoc() {
  37.437 -        return (flags & NODOC) != 0;
  37.438 -    }
  37.439 -
  37.440 -    public boolean isFinal() {
  37.441 -        return (flags & FINAL) != 0;
  37.442 -    }
  37.443 -
  37.444 -    public boolean isConstructor() {
  37.445 -        return (flags & CONSTRUCTOR) != 0;
  37.446 -    }
  37.447 -
  37.448 -    public boolean isDeprecated() {
  37.449 -        return (flags & DEPRECATED) != 0;
  37.450 -    }
  37.451 -
  37.452 -    public boolean isDocOnly() {
  37.453 -        return (flags & DOC_ONLY) != 0;
  37.454 -    }
  37.455 -
  37.456 -    public static String decodeFlags(int flags) {
  37.457 -        StringBuilder sb = new StringBuilder();
  37.458 -        if ((flags & DOCUMENTED) != 0) {
  37.459 -            sb.append("|DOCUMENTED");
  37.460 -        }
  37.461 -
  37.462 -        if ((flags & PRIVATE) != 0) {
  37.463 -            sb.append("|PRIVATE");
  37.464 -        }
  37.465 -
  37.466 -        if ((flags & CONSTRUCTOR) != 0) {
  37.467 -            sb.append("|CONSTRUCTOR");
  37.468 -        } else if ((flags & FUNCTION) != 0) {
  37.469 -            sb.append("|FUNCTION");
  37.470 -        } else if ((flags & GLOBAL) != 0) {
  37.471 -            sb.append("|GLOBAL");
  37.472 -        }
  37.473 -
  37.474 -        if ((flags & STATIC) != 0) {
  37.475 -            sb.append("|STATIC");
  37.476 -        }
  37.477 -
  37.478 -        if ((flags & NODOC) != 0) {
  37.479 -            sb.append("|NODOC");
  37.480 -        }
  37.481 -
  37.482 -        if ((flags & DEPRECATED) != 0) {
  37.483 -            sb.append("|DEPRECATED");
  37.484 -        }
  37.485 -
  37.486 -        if ((flags & DOC_ONLY) != 0) {
  37.487 -            sb.append("|DOC_ONLY");
  37.488 -        }
  37.489 -
  37.490 -        if ((flags & FINAL) != 0) {
  37.491 -            sb.append("|FINAL");
  37.492 -        }
  37.493 -
  37.494 -        if (sb.length() > 0) {
  37.495 -            sb.append("|");
  37.496 -        }
  37.497 -        return sb.toString();
  37.498 -    }
  37.499 -
  37.500 -    // For testsuite
  37.501 -    public static int stringToFlags(String string) {
  37.502 -        int flags = 0;
  37.503 -        if (string.contains("|DOCUMENTED")) {
  37.504 -            flags |= DOCUMENTED;
  37.505 -        }
  37.506 -        if (string.contains("|PRIVATE")) {
  37.507 -            flags |= PRIVATE;
  37.508 -        }
  37.509 -        if (string.contains("|DEPRECATED")) {
  37.510 -            flags |= DEPRECATED;
  37.511 -        }
  37.512 -        if (string.contains("|CONSTRUCTOR")) {
  37.513 -            flags |= CONSTRUCTOR;
  37.514 -        }
  37.515 -//        if (string.indexOf("|PROTECTED") != -1) {
  37.516 -//            flags |= PROTECTED;
  37.517 -//        }
  37.518 -//        if (string.indexOf("|TOPLEVEL") != -1) {
  37.519 -//            flags |= TOPLEVEL;
  37.520 -//        }
  37.521 -        if (string.contains("|STATIC")) {
  37.522 -            flags |= STATIC;
  37.523 -        }
  37.524 -        if (string.contains("|NODOC")) {
  37.525 -            flags |= NODOC;
  37.526 -        }
  37.527 -
  37.528 -        return flags;
  37.529 -    }
  37.530 -}
    38.1 --- a/python.editor/src/org/netbeans/modules/python/editor/elements/IndexedMethod.java	Sat Sep 12 23:03:15 2015 -0700
    38.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.3 @@ -1,88 +0,0 @@
    38.4 -/*
    38.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    38.6 - *
    38.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    38.8 - *
    38.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   38.10 - * Other names may be trademarks of their respective owners.
   38.11 - *
   38.12 - * The contents of this file are subject to the terms of either the GNU
   38.13 - * General Public License Version 2 only ("GPL") or the Common
   38.14 - * Development and Distribution License("CDDL") (collectively, the
   38.15 - * "License"). You may not use this file except in compliance with the
   38.16 - * License. You can obtain a copy of the License at
   38.17 - * http://www.netbeans.org/cddl-gplv2.html
   38.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   38.19 - * specific language governing permissions and limitations under the
   38.20 - * License.  When distributing the software, include this License Header
   38.21 - * Notice in each file and include the License file at
   38.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   38.23 - * particular file as subject to the "Classpath" exception as provided
   38.24 - * by Oracle in the GPL Version 2 section of the License file that
   38.25 - * accompanied this code. If applicable, add the following below the
   38.26 - * License Header, with the fields enclosed by brackets [] replaced by
   38.27 - * your own identifying information:
   38.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   38.29 - *
   38.30 - * Contributor(s):
   38.31 - *
   38.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   38.33 - */
   38.34 -package org.netbeans.modules.python.editor.elements;
   38.35 -
   38.36 -import org.netbeans.modules.csl.api.ElementKind;
   38.37 -
   38.38 -/**
   38.39 - *
   38.40 - * @author Tor Norbye
   38.41 - */
   38.42 -public class IndexedMethod extends IndexedElement {
   38.43 -    private String[] params;
   38.44 -
   38.45 -    public IndexedMethod(String name, ElementKind kind, String url, String module, String clz, String signature) {
   38.46 -        super(name, kind, url, module, clz, signature);
   38.47 -    }
   38.48 -
   38.49 -    public String[] getParams() {
   38.50 -        if (params == null) {
   38.51 -            //int argsBegin = name.length()+3;
   38.52 -            int argsBegin = getAttributeSection(IndexedElement.ARG_INDEX);
   38.53 -            int argsEnd = attributes.indexOf(';', argsBegin);
   38.54 -            assert argsEnd != -1 : attributes;
   38.55 -            if (argsEnd > argsBegin) {
   38.56 -                String paramString = attributes.substring(argsBegin, argsEnd);
   38.57 -                params = paramString.split(",");
   38.58 -            } else {
   38.59 -                params = new String[0];
   38.60 -            }
   38.61 -        }
   38.62 -
   38.63 -        return params;
   38.64 -    }
   38.65 -
   38.66 -    @Override
   38.67 -    public boolean equals(Object obj) {
   38.68 -        if (obj == null) {
   38.69 -            return false;
   38.70 -        }
   38.71 -        if (getClass() != obj.getClass()) {
   38.72 -            return false;
   38.73 -        }
   38.74 -        final IndexedMethod other = (IndexedMethod)obj;
   38.75 -        if (this.attributes != other.attributes && (this.attributes == null || !this.attributes.equals(other.attributes))) {
   38.76 -            return false;
   38.77 -        }
   38.78 -        if (this.clz != other.clz && (this.clz == null || !this.clz.equals(other.clz))) {
   38.79 -            return false;
   38.80 -        }
   38.81 -        return true;
   38.82 -    }
   38.83 -
   38.84 -    @Override
   38.85 -    public int hashCode() {
   38.86 -        int hash = 7;
   38.87 -        hash = 53 * hash + (this.attributes != null ? this.attributes.hashCode() : 0);
   38.88 -        hash = 53 * hash + (this.clz != null ? this.clz.hashCode() : 0);
   38.89 -        return hash;
   38.90 -    }
   38.91 -}
    39.1 --- a/python.editor/src/org/netbeans/modules/python/editor/elements/IndexedPackage.java	Sat Sep 12 23:03:15 2015 -0700
    39.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.3 @@ -1,106 +0,0 @@
    39.4 -/*
    39.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    39.6 - *
    39.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    39.8 - *
    39.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   39.10 - * Other names may be trademarks of their respective owners.
   39.11 - *
   39.12 - * The contents of this file are subject to the terms of either the GNU
   39.13 - * General Public License Version 2 only ("GPL") or the Common
   39.14 - * Development and Distribution License("CDDL") (collectively, the
   39.15 - * "License"). You may not use this file except in compliance with the
   39.16 - * License. You can obtain a copy of the License at
   39.17 - * http://www.netbeans.org/cddl-gplv2.html
   39.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   39.19 - * specific language governing permissions and limitations under the
   39.20 - * License.  When distributing the software, include this License Header
   39.21 - * Notice in each file and include the License file at
   39.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   39.23 - * particular file as subject to the "Classpath" exception as provided
   39.24 - * by Oracle in the GPL Version 2 section of the License file that
   39.25 - * accompanied this code. If applicable, add the following below the
   39.26 - * License Header, with the fields enclosed by brackets [] replaced by
   39.27 - * your own identifying information:
   39.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   39.29 - *
   39.30 - * If you wish your version of this file to be governed by only the CDDL
   39.31 - * or only the GPL Version 2, indicate your decision by adding
   39.32 - * "[Contributor] elects to include this software in this distribution
   39.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   39.34 - * single choice of license, a recipient has the option to distribute
   39.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   39.36 - * to extend the choice of license to its licensees as provided above.
   39.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   39.38 - * Version 2 license, then the option applies only if the new code is
   39.39 - * made subject to such option by the copyright holder.
   39.40 - *
   39.41 - * Contributor(s):
   39.42 - *
   39.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   39.44 - */
   39.45 -package org.netbeans.modules.python.editor.elements;
   39.46 -
   39.47 -import java.util.Collections;
   39.48 -import java.util.Set;
   39.49 -import org.netbeans.modules.csl.api.ElementKind;
   39.50 -import org.netbeans.modules.csl.api.Modifier;
   39.51 -
   39.52 -/**
   39.53 - *
   39.54 - * @author Tor Norbye
   39.55 - */
   39.56 -public class IndexedPackage extends IndexedElement {
   39.57 -    private String pkg;
   39.58 -    private boolean hasMore;
   39.59 -
   39.60 -    public IndexedPackage(String name, String pkg, String url, boolean hasMore) {
   39.61 -        super(name, ElementKind.PACKAGE, url, null, null, null);
   39.62 -        this.pkg = pkg;
   39.63 -        this.hasMore = hasMore;
   39.64 -    }
   39.65 -
   39.66 -    @Override
   39.67 -    public Set<Modifier> getModifiers() {
   39.68 -        return Collections.emptySet();
   39.69 -    }
   39.70 -
   39.71 -    public String getPkg() {
   39.72 -        return pkg;
   39.73 -    }
   39.74 -
   39.75 -    public boolean hasMore() {
   39.76 -        return hasMore;
   39.77 -    }
   39.78 -
   39.79 -    @Override
   39.80 -    public boolean equals(Object obj) {
   39.81 -        if (obj == null) {
   39.82 -            return false;
   39.83 -        }
   39.84 -        if (getClass() != obj.getClass()) {
   39.85 -            return false;
   39.86 -        }
   39.87 -        final IndexedPackage other = (IndexedPackage)obj;
   39.88 -
   39.89 -        // Side effect:
   39.90 -        // If any element thinks we have more
   39.91 -        if (other.hasMore) {
   39.92 -            this.hasMore = other.hasMore;
   39.93 -        } else if (this.hasMore) {
   39.94 -            other.hasMore = this.hasMore;
   39.95 -        }
   39.96 -
   39.97 -        if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
   39.98 -            return false;
   39.99 -        }
  39.100 -        return true;
  39.101 -    }
  39.102 -
  39.103 -    @Override
  39.104 -    public int hashCode() {
  39.105 -        int hash = 7;
  39.106 -        hash = 73 * hash + (this.name != null ? this.name.hashCode() : 0);
  39.107 -        return hash;
  39.108 -    }
  39.109 -}
    40.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/AccessToProtected.java	Sat Sep 12 23:03:15 2015 -0700
    40.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.3 @@ -1,150 +0,0 @@
    40.4 -/*
    40.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    40.6 - *
    40.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    40.8 - *
    40.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   40.10 - * Other names may be trademarks of their respective owners.
   40.11 - *
   40.12 - * The contents of this file are subject to the terms of either the GNU
   40.13 - * General Public License Version 2 only ("GPL") or the Common
   40.14 - * Development and Distribution License("CDDL") (collectively, the
   40.15 - * "License"). You may not use this file except in compliance with the
   40.16 - * License. You can obtain a copy of the License at
   40.17 - * http://www.netbeans.org/cddl-gplv2.html
   40.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   40.19 - * specific language governing permissions and limitations under the
   40.20 - * License.  When distributing the software, include this License Header
   40.21 - * Notice in each file and include the License file at
   40.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   40.23 - * particular file as subject to the "Classpath" exception as provided
   40.24 - * by Oracle in the GPL Version 2 section of the License file that
   40.25 - * accompanied this code. If applicable, add the following below the
   40.26 - * License Header, with the fields enclosed by brackets [] replaced by
   40.27 - * your own identifying information:
   40.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   40.29 - *
   40.30 - * If you wish your version of this file to be governed by only the CDDL
   40.31 - * or only the GPL Version 2, indicate your decision by adding
   40.32 - * "[Contributor] elects to include this software in this distribution
   40.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   40.34 - * single choice of license, a recipient has the option to distribute
   40.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   40.36 - * to extend the choice of license to its licensees as provided above.
   40.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   40.38 - * Version 2 license, then the option applies only if the new code is
   40.39 - * made subject to such option by the copyright holder.
   40.40 - *
   40.41 - * Contributor(s):
   40.42 - *
   40.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   40.44 - */
   40.45 -package org.netbeans.modules.python.editor.hints;
   40.46 -
   40.47 -import java.util.Collections;
   40.48 -import java.util.List;
   40.49 -import java.util.Set;
   40.50 -import java.util.prefs.Preferences;
   40.51 -import javax.swing.JComponent;
   40.52 -import org.netbeans.modules.csl.api.Hint;
   40.53 -import org.netbeans.modules.csl.api.HintFix;
   40.54 -import org.netbeans.modules.csl.api.HintSeverity;
   40.55 -import org.netbeans.modules.csl.api.OffsetRange;
   40.56 -import org.netbeans.modules.csl.api.RuleContext;
   40.57 -import org.netbeans.modules.python.editor.PythonAstUtils;
   40.58 -import org.netbeans.modules.python.editor.PythonParserResult;
   40.59 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   40.60 -import org.netbeans.modules.python.editor.scopes.SymInfo;
   40.61 -import org.openide.util.NbBundle;
   40.62 -import org.python.antlr.ast.Attribute;
   40.63 -import org.python.antlr.ast.Name;
   40.64 -import org.python.antlr.base.expr;
   40.65 -
   40.66 -/**
   40.67 - * Check direct acces to parent protected variables or methods
   40.68 - * @author jean-yves Mengant
   40.69 - */
   40.70 -public class AccessToProtected extends PythonAstRule {
   40.71 -    private final static String ACCESS_PROTECTED_ID = "AccessProtected"; // NOI18N
   40.72 -    private final static String ACCESS_PROTECTED_VARIABLE = "AccessProtectedVariable"; // NOI18N
   40.73 -    private final static String ACCESS_PROTECTED_DESC = "AccessProtectedDesc"; // NOI18N
   40.74 -
   40.75 -    @Override
   40.76 -    public Set<Class> getKinds() {
   40.77 -        return Collections.<Class>singleton(Attribute.class);
   40.78 -    }
   40.79 -
   40.80 -    @Override
   40.81 -    public void run(PythonRuleContext context, List<Hint> result) {
   40.82 -        PythonParserResult info = (PythonParserResult) context.parserResult;
   40.83 -        Attribute cur = (Attribute)context.node;
   40.84 -        String curAttr = cur.getInternalAttr();
   40.85 -        if (curAttr == null) {
   40.86 -            return;
   40.87 -        }
   40.88 -
   40.89 -        if (SymInfo.isProtectedName(curAttr)) {
   40.90 -            expr curValue = cur.getInternalValue();
   40.91 -            if (curValue instanceof Name) {
   40.92 -                Name nam = (Name)curValue;
   40.93 -                String id = nam.getInternalId();
   40.94 -                if (id.equals("self")) { // NOI18N
   40.95 -                    return; // normal access from class instance
   40.96 -                }
   40.97 -                if (PythonAstUtils.getParentClassFromNode(context.path, null, id) != null) {
   40.98 -                    return; // parent access
   40.99 -                }
  40.100 -                // we should warn here : Access to protected Attributes from non child
  40.101 -                // classes
  40.102 -                OffsetRange range = PythonAstUtils.getRange(cur);
  40.103 -                range = PythonLexerUtils.getLexerOffsets(info, range);
  40.104 -                if (range != OffsetRange.NONE) {
  40.105 -                    List<HintFix> fixList = Collections.emptyList();
  40.106 -                    String message = NbBundle.getMessage(NameRule.class, ACCESS_PROTECTED_VARIABLE, curAttr);
  40.107 -                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
  40.108 -                    result.add(desc);
  40.109 -                }
  40.110 -            }
  40.111 -        }
  40.112 -    }
  40.113 -
  40.114 -    @Override
  40.115 -    public String getId() {
  40.116 -        return ACCESS_PROTECTED_ID;
  40.117 -    }
  40.118 -
  40.119 -    @Override
  40.120 -    public String getDescription() {
  40.121 -        return NbBundle.getMessage(RelativeImports.class, ACCESS_PROTECTED_DESC);
  40.122 -    }
  40.123 -
  40.124 -    @Override
  40.125 -    public boolean getDefaultEnabled() {
  40.126 -        return false;
  40.127 -    }
  40.128 -
  40.129 -    @Override
  40.130 -    public JComponent getCustomizer(Preferences node) {
  40.131 -        return null;
  40.132 -    }
  40.133 -
  40.134 -    @Override
  40.135 -    public boolean appliesTo(RuleContext context) {
  40.136 -        return true;
  40.137 -    }
  40.138 -
  40.139 -    @Override
  40.140 -    public String getDisplayName() {
  40.141 -        return NbBundle.getMessage(AccessToProtected.class, ACCESS_PROTECTED_ID);
  40.142 -    }
  40.143 -
  40.144 -    @Override
  40.145 -    public boolean showInTasklist() {
  40.146 -        return true;
  40.147 -    }
  40.148 -
  40.149 -    @Override
  40.150 -    public HintSeverity getDefaultSeverity() {
  40.151 -        return HintSeverity.WARNING;
  40.152 -    }
  40.153 -}
    41.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/AllAssignExists.java	Sat Sep 12 23:03:15 2015 -0700
    41.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.3 @@ -1,148 +0,0 @@
    41.4 -/*
    41.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    41.6 - *
    41.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    41.8 - *
    41.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   41.10 - * Other names may be trademarks of their respective owners.
   41.11 - *
   41.12 - * The contents of this file are subject to the terms of either the GNU
   41.13 - * General Public License Version 2 only ("GPL") or the Common
   41.14 - * Development and Distribution License("CDDL") (collectively, the
   41.15 - * "License"). You may not use this file except in compliance with the
   41.16 - * License. You can obtain a copy of the License at
   41.17 - * http://www.netbeans.org/cddl-gplv2.html
   41.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   41.19 - * specific language governing permissions and limitations under the
   41.20 - * License.  When distributing the software, include this License Header
   41.21 - * Notice in each file and include the License file at
   41.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   41.23 - * particular file as subject to the "Classpath" exception as provided
   41.24 - * by Oracle in the GPL Version 2 section of the License file that
   41.25 - * accompanied this code. If applicable, add the following below the
   41.26 - * License Header, with the fields enclosed by brackets [] replaced by
   41.27 - * your own identifying information:
   41.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   41.29 - *
   41.30 - * If you wish your version of this file to be governed by only the CDDL
   41.31 - * or only the GPL Version 2, indicate your decision by adding
   41.32 - * "[Contributor] elects to include this software in this distribution
   41.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   41.34 - * single choice of license, a recipient has the option to distribute
   41.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   41.36 - * to extend the choice of license to its licensees as provided above.
   41.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   41.38 - * Version 2 license, then the option applies only if the new code is
   41.39 - * made subject to such option by the copyright holder.
   41.40 - *
   41.41 - * Contributor(s):
   41.42 - *
   41.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   41.44 - */
   41.45 -package org.netbeans.modules.python.editor.hints;
   41.46 -
   41.47 -import java.util.Collections;
   41.48 -import java.util.List;
   41.49 -import java.util.Set;
   41.50 -import java.util.prefs.Preferences;
   41.51 -import javax.swing.JComponent;
   41.52 -import org.netbeans.modules.csl.api.Hint;
   41.53 -import org.netbeans.modules.csl.api.HintFix;
   41.54 -import org.netbeans.modules.csl.api.HintSeverity;
   41.55 -import org.netbeans.modules.csl.api.OffsetRange;
   41.56 -import org.netbeans.modules.csl.api.RuleContext;
   41.57 -import org.netbeans.modules.python.editor.PythonAstUtils;
   41.58 -import org.netbeans.modules.python.editor.PythonParserResult;
   41.59 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   41.60 -import org.netbeans.modules.python.editor.scopes.ScopeInfo;
   41.61 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
   41.62 -import org.netbeans.modules.python.editor.scopes.SymInfo;
   41.63 -import org.openide.util.NbBundle;
   41.64 -import org.python.antlr.ast.Module;
   41.65 -import org.python.antlr.ast.Str;
   41.66 -
   41.67 -/**
   41.68 - *
   41.69 - * @author Tor Norbye
   41.70 - */
   41.71 -public class AllAssignExists extends PythonAstRule {
   41.72 -    @Override
   41.73 -    public Set<Class> getKinds() {
   41.74 -        return Collections.<Class>singleton(Module.class);
   41.75 -    }
   41.76 -
   41.77 -    @Override
   41.78 -    public void run(PythonRuleContext context, List<Hint> result) {
   41.79 -        PythonParserResult ppr = (PythonParserResult)context.parserResult;
   41.80 -        SymbolTable symbolTable = ppr.getSymbolTable();
   41.81 -        List<Str> publicSymbols = symbolTable.getPublicSymbols();
   41.82 -        if (publicSymbols != null) {
   41.83 -            // Check that we actually have all the symbols called for
   41.84 -            // by the all-list
   41.85 -
   41.86 -            ScopeInfo topScope = symbolTable.getScopeInfo(context.node);
   41.87 -            assert topScope != null;
   41.88 -
   41.89 -            // Mark all other symbols private!
   41.90 -            for (Str str : publicSymbols) {
   41.91 -                //String name = PythonAstUtils.getExprName(expr);
   41.92 -                String name = PythonAstUtils.getStrContent(str);
   41.93 -                if (name != null) {
   41.94 -                    SymInfo sym = topScope.tbl.get(name);
   41.95 -                    if (sym == null) {
   41.96 -                        // Uh oh -- missing!
   41.97 -                        PythonParserResult info = (PythonParserResult) context.parserResult;
   41.98 -                        OffsetRange range = PythonAstUtils.getNameRange(info, str);
   41.99 -                        range = PythonLexerUtils.getLexerOffsets(info, range);
  41.100 -                        if (range != OffsetRange.NONE) {
  41.101 -                            List<HintFix> fixList = Collections.emptyList();
  41.102 -                            String message = NbBundle.getMessage(AllAssignExists.class, "AllAssignExistsMsg", name);
  41.103 -                            Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 205);
  41.104 -                            result.add(desc);
  41.105 -                        }
  41.106 -                    }
  41.107 -                }
  41.108 -            }
  41.109 -        }
  41.110 -    }
  41.111 -
  41.112 -    @Override
  41.113 -    public String getId() {
  41.114 -        return "AllAssignExists"; // NOI18N
  41.115 -    }
  41.116 -
  41.117 -    @Override
  41.118 -    public String getDescription() {
  41.119 -        return NbBundle.getMessage(AllAssignExists.class, "AllAssignExistsDesc");
  41.120 -    }
  41.121 -
  41.122 -    @Override
  41.123 -    public boolean getDefaultEnabled() {
  41.124 -        return true;
  41.125 -    }
  41.126 -
  41.127 -    @Override
  41.128 -    public JComponent getCustomizer(Preferences node) {
  41.129 -        return null;
  41.130 -    }
  41.131 -
  41.132 -    @Override
  41.133 -    public boolean appliesTo(RuleContext context) {
  41.134 -        return true;
  41.135 -    }
  41.136 -
  41.137 -    @Override
  41.138 -    public String getDisplayName() {
  41.139 -        return NbBundle.getMessage(AllAssignExists.class, "AllAssignExists");
  41.140 -    }
  41.141 -
  41.142 -    @Override
  41.143 -    public boolean showInTasklist() {
  41.144 -        return true;
  41.145 -    }
  41.146 -
  41.147 -    @Override
  41.148 -    public HintSeverity getDefaultSeverity() {
  41.149 -        return HintSeverity.ERROR;
  41.150 -    }
  41.151 -}
    42.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/AssignToVariable.java	Sat Sep 12 23:03:15 2015 -0700
    42.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.3 @@ -1,245 +0,0 @@
    42.4 -/*
    42.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    42.6 - *
    42.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    42.8 - *
    42.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   42.10 - * Other names may be trademarks of their respective owners.
   42.11 - *
   42.12 - * The contents of this file are subject to the terms of either the GNU
   42.13 - * General Public License Version 2 only ("GPL") or the Common
   42.14 - * Development and Distribution License("CDDL") (collectively, the
   42.15 - * "License"). You may not use this file except in compliance with the
   42.16 - * License. You can obtain a copy of the License at
   42.17 - * http://www.netbeans.org/cddl-gplv2.html
   42.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   42.19 - * specific language governing permissions and limitations under the
   42.20 - * License.  When distributing the software, include this License Header
   42.21 - * Notice in each file and include the License file at
   42.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   42.23 - * particular file as subject to the "Classpath" exception as provided
   42.24 - * by Oracle in the GPL Version 2 section of the License file that
   42.25 - * accompanied this code. If applicable, add the following below the
   42.26 - * License Header, with the fields enclosed by brackets [] replaced by
   42.27 - * your own identifying information:
   42.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   42.29 - *
   42.30 - * If you wish your version of this file to be governed by only the CDDL
   42.31 - * or only the GPL Version 2, indicate your decision by adding
   42.32 - * "[Contributor] elects to include this software in this distribution
   42.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   42.34 - * single choice of license, a recipient has the option to distribute
   42.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   42.36 - * to extend the choice of license to its licensees as provided above.
   42.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   42.38 - * Version 2 license, then the option applies only if the new code is
   42.39 - * made subject to such option by the copyright holder.
   42.40 - *
   42.41 - * Contributor(s):
   42.42 - *
   42.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   42.44 - */
   42.45 -package org.netbeans.modules.python.editor.hints;
   42.46 -
   42.47 -import java.util.ArrayList;
   42.48 -import java.util.Collections;
   42.49 -import java.util.List;
   42.50 -import java.util.Set;
   42.51 -import java.util.prefs.Preferences;
   42.52 -import javax.swing.JComponent;
   42.53 -import javax.swing.text.BadLocationException;
   42.54 -import javax.swing.text.JTextComponent;
   42.55 -import javax.swing.text.Position;
   42.56 -import org.netbeans.modules.python.editor.PythonAstUtils;
   42.57 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   42.58 -import org.netbeans.editor.BaseDocument;
   42.59 -import org.netbeans.editor.Utilities;
   42.60 -import org.netbeans.modules.csl.api.EditList;
   42.61 -import org.netbeans.modules.csl.api.Hint;
   42.62 -import org.netbeans.modules.csl.api.HintFix;
   42.63 -import org.netbeans.modules.csl.api.HintSeverity;
   42.64 -import org.netbeans.modules.csl.api.OffsetRange;
   42.65 -import org.netbeans.modules.csl.api.PreviewableFix;
   42.66 -import org.netbeans.modules.csl.api.RuleContext;
   42.67 -import org.netbeans.modules.csl.spi.GsfUtilities;
   42.68 -import org.netbeans.modules.python.editor.PythonParserResult;
   42.69 -import org.openide.util.Exceptions;
   42.70 -import org.openide.util.NbBundle;
   42.71 -import org.python.antlr.PythonTree;
   42.72 -import org.python.antlr.ast.Call;
   42.73 -import org.python.antlr.ast.Expr;
   42.74 -import org.python.antlr.ast.FunctionDef;
   42.75 -import org.python.antlr.ast.Str;
   42.76 -import org.python.antlr.base.expr;
   42.77 -import org.python.antlr.base.stmt;
   42.78 -
   42.79 -/**
   42.80 - * Assign an expression to a variable
   42.81 - *
   42.82 - * @author Tor Norbye
   42.83 - */
   42.84 -public class AssignToVariable extends PythonAstRule {
   42.85 -    @Override
   42.86 -    public Set<Class> getKinds() {
   42.87 -        return Collections.singleton((Class)Expr.class);
   42.88 -    }
   42.89 -
   42.90 -    @Override
   42.91 -    public void run(PythonRuleContext context, List<Hint> result) {
   42.92 -        PythonTree node = context.node;
   42.93 -        Expr expr = (Expr)node;
   42.94 -        expr exprValue = expr.getInternalValue();
   42.95 -        if (exprValue instanceof Str) {
   42.96 -            // Skip triple-quoted strings (typically doc strings)
   42.97 -            Str str = (Str)exprValue;
   42.98 -            String s = str.getText();
   42.99 -            if (s.startsWith("'''") || s.startsWith("\"\"\"")) { // NOI18N
  42.100 -                return;
  42.101 -            }
  42.102 -            PythonTree grandParent = context.path.leafGrandParent();
  42.103 -            if (grandParent instanceof FunctionDef) {
  42.104 -                FunctionDef def = (FunctionDef)grandParent;
  42.105 -                List<stmt> body = def.getInternalBody();
  42.106 -                if (body != null && body.size() > 0 && body.get(0) == expr) {
  42.107 -                    // First string in a function -- it's a docstring
  42.108 -                    return;
  42.109 -                }
  42.110 -            }
  42.111 -        }
  42.112 -        if (exprValue instanceof Call) {
  42.113 -            // Skip calls - they may have side effects
  42.114 -            // ...unless it looks like a "getter" style Python method
  42.115 -            Call call = (Call)exprValue;
  42.116 -            if (!PythonAstUtils.isGetter(call, false)) {
  42.117 -                return;
  42.118 -            }
  42.119 -        }
  42.120 -        PythonParserResult info = (PythonParserResult) context.parserResult;
  42.121 -        OffsetRange astOffsets = PythonAstUtils.getNameRange(info, node);
  42.122 -        OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
  42.123 -        BaseDocument doc = context.doc;
  42.124 -        try {
  42.125 -            if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
  42.126 -                    (context.caretOffset == -1 ||
  42.127 -                    Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
  42.128 -                List<HintFix> fixList = new ArrayList<>();
  42.129 -                fixList.add(new AssignToVariableFix(context, node));
  42.130 -                String displayName = getDisplayName();
  42.131 -                Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
  42.132 -                result.add(desc);
  42.133 -            }
  42.134 -        } catch (BadLocationException ex) {
  42.135 -            Exceptions.printStackTrace(ex);
  42.136 -        }
  42.137 -    }
  42.138 -
  42.139 -    @Override
  42.140 -    public String getId() {
  42.141 -        return "AssignToVariable"; // NOI18N
  42.142 -    }
  42.143 -
  42.144 -    @Override
  42.145 -    public String getDisplayName() {
  42.146 -        return NbBundle.getMessage(AssignToVariable.class, "AssignToVariable");
  42.147 -    }
  42.148 -
  42.149 -    @Override
  42.150 -    public String getDescription() {
  42.151 -        return NbBundle.getMessage(AssignToVariable.class, "AssignToVariableDesc");
  42.152 -    }
  42.153 -
  42.154 -    @Override
  42.155 -    public boolean getDefaultEnabled() {
  42.156 -        return true;
  42.157 -    }
  42.158 -
  42.159 -    @Override
  42.160 -    public JComponent getCustomizer(Preferences node) {
  42.161 -        return null;
  42.162 -    }
  42.163 -
  42.164 -    @Override
  42.165 -    public boolean appliesTo(RuleContext context) {
  42.166 -        return true;
  42.167 -    }
  42.168 -
  42.169 -    @Override
  42.170 -    public boolean showInTasklist() {
  42.171 -        return false;
  42.172 -    }
  42.173 -
  42.174 -    @Override
  42.175 -    public HintSeverity getDefaultSeverity() {
  42.176 -        return HintSeverity.CURRENT_LINE_WARNING;
  42.177 -    }
  42.178 -
  42.179 -    private static class AssignToVariableFix implements PreviewableFix {
  42.180 -        private final PythonRuleContext context;
  42.181 -        private final PythonTree node;
  42.182 -        private int varOffset;
  42.183 -        private String varName;
  42.184 -
  42.185 -        private AssignToVariableFix(PythonRuleContext context, PythonTree node) {
  42.186 -            this.context = context;
  42.187 -            this.node = node;
  42.188 -        }
  42.189 -
  42.190 -        @Override
  42.191 -        public String getDescription() {
  42.192 -            return NbBundle.getMessage(AssignToVariable.class, "AssignToVariableFix");
  42.193 -        }
  42.194 -
  42.195 -        @Override
  42.196 -        public boolean canPreview() {
  42.197 -            return true;
  42.198 -        }
  42.199 -
  42.200 -        @Override
  42.201 -        public EditList getEditList() throws Exception {
  42.202 -            BaseDocument doc = context.doc;
  42.203 -            EditList edits = new EditList(doc);
  42.204 -
  42.205 -            OffsetRange astRange = PythonAstUtils.getRange(node);
  42.206 -            if (astRange != OffsetRange.NONE) {
  42.207 -                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets((PythonParserResult) context.parserResult, astRange);
  42.208 -                if (lexRange != OffsetRange.NONE) {
  42.209 -                    int offset = lexRange.getStart();
  42.210 -                    StringBuilder sb = new StringBuilder();
  42.211 -                    varName = NbBundle.getMessage(AssignToVariable.class, "VarName");
  42.212 -                    sb.append(varName);
  42.213 -                    sb.append(" = "); // NOI18N
  42.214 -                    varOffset = offset;
  42.215 -                    edits.replace(offset, 0, sb.toString(), false, 0);
  42.216 -                }
  42.217 -            }
  42.218 -
  42.219 -            return edits;
  42.220 -        }
  42.221 -
  42.222 -        @Override
  42.223 -        public void implement() throws Exception {
  42.224 -            EditList edits = getEditList();
  42.225 -
  42.226 -            Position pos = edits.createPosition(varOffset);
  42.227 -            edits.apply();
  42.228 -            if (pos != null && pos.getOffset() != -1) {
  42.229 -                JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
  42.230 -                if (target != null) {
  42.231 -                    int start = pos.getOffset();
  42.232 -                    int end = start + varName.length();
  42.233 -                    target.select(start, end);
  42.234 -                }
  42.235 -            }
  42.236 -        }
  42.237 -
  42.238 -        @Override
  42.239 -        public boolean isSafe() {
  42.240 -            return true;
  42.241 -        }
  42.242 -
  42.243 -        @Override
  42.244 -        public boolean isInteractive() {
  42.245 -            return false;
  42.246 -        }
  42.247 -    }
  42.248 -}
    43.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/AttributeDefinedOutsideInit.java	Sat Sep 12 23:03:15 2015 -0700
    43.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.3 @@ -1,140 +0,0 @@
    43.4 -/*
    43.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    43.6 - *
    43.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    43.8 - *
    43.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   43.10 - * Other names may be trademarks of their respective owners.
   43.11 - *
   43.12 - * The contents of this file are subject to the terms of either the GNU
   43.13 - * General Public License Version 2 only ("GPL") or the Common
   43.14 - * Development and Distribution License("CDDL") (collectively, the
   43.15 - * "License"). You may not use this file except in compliance with the
   43.16 - * License. You can obtain a copy of the License at
   43.17 - * http://www.netbeans.org/cddl-gplv2.html
   43.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   43.19 - * specific language governing permissions and limitations under the
   43.20 - * License.  When distributing the software, include this License Header
   43.21 - * Notice in each file and include the License file at
   43.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   43.23 - * particular file as subject to the "Classpath" exception as provided
   43.24 - * by Oracle in the GPL Version 2 section of the License file that
   43.25 - * accompanied this code. If applicable, add the following below the
   43.26 - * License Header, with the fields enclosed by brackets [] replaced by
   43.27 - * your own identifying information:
   43.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   43.29 - *
   43.30 - * If you wish your version of this file to be governed by only the CDDL
   43.31 - * or only the GPL Version 2, indicate your decision by adding
   43.32 - * "[Contributor] elects to include this software in this distribution
   43.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   43.34 - * single choice of license, a recipient has the option to distribute
   43.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   43.36 - * to extend the choice of license to its licensees as provided above.
   43.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   43.38 - * Version 2 license, then the option applies only if the new code is
   43.39 - * made subject to such option by the copyright holder.
   43.40 - *
   43.41 - * Contributor(s):
   43.42 - *
   43.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   43.44 - */
   43.45 -package org.netbeans.modules.python.editor.hints;
   43.46 -
   43.47 -import java.util.Collections;
   43.48 -import java.util.List;
   43.49 -import java.util.Set;
   43.50 -import java.util.prefs.Preferences;
   43.51 -import javax.swing.JComponent;
   43.52 -import org.netbeans.modules.csl.api.Hint;
   43.53 -import org.netbeans.modules.csl.api.HintFix;
   43.54 -import org.netbeans.modules.csl.api.HintSeverity;
   43.55 -import org.netbeans.modules.csl.api.OffsetRange;
   43.56 -import org.netbeans.modules.csl.api.RuleContext;
   43.57 -import org.netbeans.modules.python.editor.PythonAstUtils;
   43.58 -import org.netbeans.modules.python.editor.PythonParserResult;
   43.59 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   43.60 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
   43.61 -import org.openide.util.NbBundle;
   43.62 -import org.python.antlr.ast.Attribute;
   43.63 -import org.python.antlr.ast.Module;
   43.64 -
   43.65 -/**
   43.66 - *
   43.67 - * @author Jean-Yves Mengant
   43.68 - */
   43.69 -public class AttributeDefinedOutsideInit extends PythonAstRule {
   43.70 -    private final static String ATTRIBUTE_DEFINED_OUTSIDE_INIT = "AttributeDefinedOutsideInit";
   43.71 -    private final static String ATTRIBUTE_DEFINED_OUTSITE_INIT_VAR = "AttributeDefinedOutsideInitVariable";
   43.72 -    private final static String ATTRIBUTE_DEFINED_OUTSIDE_INIT_DESC = "AttributeDefinedOutsideInitDesc";
   43.73 -
   43.74 -    @Override
   43.75 -    public Set<Class> getKinds() {
   43.76 -        return Collections.<Class>singleton(Module.class);
   43.77 -    }
   43.78 -
   43.79 -    @Override
   43.80 -    public void run(PythonRuleContext context, List<Hint> result) {
   43.81 -        PythonParserResult info = (PythonParserResult) context.parserResult;
   43.82 -        PythonParserResult pr = PythonAstUtils.getParseResult(info);
   43.83 -        SymbolTable symbolTable = pr.getSymbolTable();
   43.84 -
   43.85 -
   43.86 -        List<Attribute> notInIntBound = symbolTable.getNotInInitAttributes(info);
   43.87 -        if (notInIntBound.size() > 0) {
   43.88 -            for (Attribute cur : notInIntBound) {
   43.89 -                OffsetRange range = PythonAstUtils.getRange(cur);
   43.90 -                range = PythonLexerUtils.getLexerOffsets(info, range);
   43.91 -                if (range != OffsetRange.NONE) {
   43.92 -                    List<HintFix> fixList = Collections.emptyList();
   43.93 -                    String message = NbBundle.getMessage(NameRule.class,
   43.94 -                            ATTRIBUTE_DEFINED_OUTSITE_INIT_VAR,
   43.95 -                            cur.getInternalAttr());
   43.96 -                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
   43.97 -                    result.add(desc);
   43.98 -                }
   43.99 -            }
  43.100 -        }
  43.101 -
  43.102 -    }
  43.103 -
  43.104 -    @Override
  43.105 -    public String getId() {
  43.106 -        return ATTRIBUTE_DEFINED_OUTSIDE_INIT;
  43.107 -    }
  43.108 -
  43.109 -    @Override
  43.110 -    public String getDescription() {
  43.111 -        return NbBundle.getMessage(RelativeImports.class, ATTRIBUTE_DEFINED_OUTSIDE_INIT_DESC);
  43.112 -    }
  43.113 -
  43.114 -    @Override
  43.115 -    public boolean getDefaultEnabled() {
  43.116 -        return false;
  43.117 -    }
  43.118 -
  43.119 -    @Override
  43.120 -    public JComponent getCustomizer(Preferences node) {
  43.121 -        return null;
  43.122 -    }
  43.123 -
  43.124 -    @Override
  43.125 -    public boolean appliesTo(RuleContext context) {
  43.126 -        return true;
  43.127 -    }
  43.128 -
  43.129 -    @Override
  43.130 -    public String getDisplayName() {
  43.131 -        return NbBundle.getMessage(AccessToProtected.class, ATTRIBUTE_DEFINED_OUTSIDE_INIT);
  43.132 -    }
  43.133 -
  43.134 -    @Override
  43.135 -    public boolean showInTasklist() {
  43.136 -        return true;
  43.137 -    }
  43.138 -
  43.139 -    @Override
  43.140 -    public HintSeverity getDefaultSeverity() {
  43.141 -        return HintSeverity.WARNING;
  43.142 -    }
  43.143 -}
    44.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/Bundle.properties	Sat Sep 12 23:03:15 2015 -0700
    44.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.3 @@ -1,146 +0,0 @@
    44.4 -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    44.5 -#
    44.6 -# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    44.7 -#
    44.8 -# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    44.9 -# Other names may be trademarks of their respective owners.
   44.10 -#
   44.11 -# The contents of this file are subject to the terms of either the GNU
   44.12 -# General Public License Version 2 only ("GPL") or the Common
   44.13 -# Development and Distribution License("CDDL") (collectively, the
   44.14 -# "License"). You may not use this file except in compliance with the
   44.15 -# License. You can obtain a copy of the License at
   44.16 -# http://www.netbeans.org/cddl-gplv2.html
   44.17 -# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   44.18 -# specific language governing permissions and limitations under the
   44.19 -# License.  When distributing the software, include this License Header
   44.20 -# Notice in each file and include the License file at
   44.21 -# nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   44.22 -# particular file as subject to the "Classpath" exception as provided
   44.23 -# by Oracle in the GPL Version 2 section of the License file that
   44.24 -# accompanied this code. If applicable, add the following below the
   44.25 -# License Header, with the fields enclosed by brackets [] replaced by
   44.26 -# your own identifying information:
   44.27 -# "Portions Copyrighted [year] [name of copyright owner]"
   44.28 -#
   44.29 -# Contributor(s):
   44.30 -#
   44.31 -# The Original Software is NetBeans. The Initial Developer of the Original
   44.32 -# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   44.33 -# Microsystems, Inc. All Rights Reserved.
   44.34 -#
   44.35 -# If you wish your version of this file to be governed by only the CDDL
   44.36 -# or only the GPL Version 2, indicate your decision by adding
   44.37 -# "[Contributor] elects to include this software in this distribution
   44.38 -# under the [CDDL or GPL Version 2] license." If you do not indicate a
   44.39 -# single choice of license, a recipient has the option to distribute
   44.40 -# your version of this file under either the CDDL, the GPL Version 2 or
   44.41 -# to extend the choice of license to its licensees as provided above.
   44.42 -# However, if you add GPL Version 2 code and therefore, elected the GPL
   44.43 -# Version 2 license, then the option applies only if the new code is
   44.44 -# made subject to such option by the copyright holder.
   44.45 -
   44.46 -# Category descriptions in the Options Panel
   44.47 -gsf-hints/text/x-python/hints/general=General
   44.48 -
   44.49 -# NameRule
   44.50 -NameRule=Naming Conventions
   44.51 -NameRuleDesc=Check class, function and variable names for style guide compliance (see http://www.python.org/dev/peps/pep-0008/ for rules)
   44.52 -NameRuleWrongNoArg=First argument should be 'self' or 'cls'
   44.53 -NameRuleWrongArg=First argument ({0}) should be 'self' or 'cls'
   44.54 -WrongStyle=Name "{0}" is not a valid {1} name according to your code style ({2})
   44.55 -Module=module
   44.56 -Function=function
   44.57 -Class=class
   44.58 -Variable=variable
   44.59 -ChangeStyle=Change preferred {0} name style to {1}
   44.60 -ChangeNoStyle=Turn off {0} name style checks
   44.61 -IgnoreWord=Ignore name violations for "{0}"
   44.62 -NameRulePrefs.selfCb.text=First method params should be "self" or "cls"
   44.63 -NameRulePrefs.moduleLabel.text=Modules:
   44.64 -NameRulePrefs.classLabel.text=Classes:
   44.65 -NameRulePrefs.functionLabel.text=Functions:
   44.66 -NameRulePrefs.parameterLabel.text=Parameters:
   44.67 -NameRulePrefs.variableLabel.text=Variables:
   44.68 -NoPreference=No Preference
   44.69 -NameRulePrefs.ignoreLabel.text=Ignored:
   44.70 -
   44.71 -CreateDocString=Create document comment
   44.72 -CreateDocStringDesc=Offer to create a documentation comment for the current function, class or module
   44.73 -CreateDocStringFix=Add a one-liner docstring
   44.74 -CreateDocStringFixMulti=Add a multi-line docstring
   44.75 -
   44.76 -AssignToVariable=Assign expression to a variable
   44.77 -AssignToVariableDesc=Assign expression under the caret to a variable
   44.78 -AssignToVariableFix=Assign expression to a variable
   44.79 -VarName=name
   44.80 -
   44.81 -SplitImports=Multiple imports per import statement is discouraged
   44.82 -SplitImportsDesc=Split an import which imports multiple modules into individual import statements as recommended by the Python styleguide
   44.83 -SplitImportsFix=Split import into individual import statements
   44.84 -
   44.85 -RelativeImports=Relative imports for intra-package imports are actively discouraged (as per PEP-008)
   44.86 -RelativeImportsDesc=Relative imports for intra-package imports are actively discouraged (as per PEP-008) and this rule warns about usages of relative imports
   44.87 -RelativeImportsFix=Replace with absolute import
   44.88 -
   44.89 -Deprecations=Deprecated
   44.90 -DeprecationsMsg={0} is deprecated
   44.91 -DeprecationsMsgDetail={0} is deprecated. {1}
   44.92 -DeprecationsDesc=Check for deprecated modules
   44.93 -
   44.94 -SurroundWith=Surround With...
   44.95 -#SurroundWithDesc=Offer to surround selected code with try/catch, etc
   44.96 -SurroundWithTE=Surround With Try/Except
   44.97 -SurroundWithTEF=Surround With Try/Except/Finally
   44.98 -SurroundWithTF=Surround With Try/Finally
   44.99 -InsertSelf=Insert a new first parameter "self"
  44.100 -RenameSelf=Rename first parameter "{0}" to self
  44.101 -
  44.102 -ExtractCode=Extract Code
  44.103 -IntroduceMethod=Extract Method
  44.104 -IntroduceVariable=Introduce Variable
  44.105 -IntroduceConstant=Introduce Constant
  44.106 -IntroduceField=Introduce Field
  44.107 -
  44.108 -UnusedImport=Unused Import
  44.109 -UnusedImportSymbols=Some symbols are unused ({0})
  44.110 -UnusedImports=Find Unused Imports
  44.111 -UnusedImportsDesc=Find imports that aren't used in this module and can be removed
  44.112 -UnusedFix=Remove Unused Import
  44.113 -UnusedFixSymbols=Remove {0} from import
  44.114 -OrganizeImports=Clean up and Organize Imports
  44.115 -DeleteAllUnused=Remove All Unused Imports
  44.116 -
  44.117 -Unused=Find Unused Variables
  44.118 -UnusedDesc=Find variables that are defined but never used
  44.119 -UnusedVariable=Unused Variable {0}
  44.120 -
  44.121 -Unresolved=Find Undefined Names
  44.122 -UnresolvedDesc=Find names that are used but have not been bound
  44.123 -UnresolvedVariable=Undefined name "{0}"
  44.124 -UnresolvedVariableMaybe=Undefined name "{0}" - did you mean "{1}" ?
  44.125 -FixImport=Import {0}
  44.126 -
  44.127 -UnresolvedAttributes=Find Unresolved classes attributes and parentages
  44.128 -UnresolvedAttributesDesc=Find class attributes that are used but have not been bound and undefined inherited classes
  44.129 -UnresolvedAttributesVariable=Undefined attribute "{0}"
  44.130 -UnresolvedInheritanceVariable=Inheriting from undefined parent class "{0}"
  44.131 -
  44.132 -AccessProtected=Access Protected Attributes
  44.133 -AccessProtectedDesc=Find access to protected variables/methods of non parent classes
  44.134 -AccessProtectedVariable=Access to protected variable "{0}"
  44.135 -
  44.136 -AttributeDefinedOutsideInit=Attribute Defined Outside __init__
  44.137 -AttributeDefinedOutsideInitDesc=Class Attribute defined outside __init__ constructor
  44.138 -AttributeDefinedOutsideInitVariable=Attribute Defined Outside __init__ "{0}"
  44.139 -
  44.140 -ClassCircularRedundancy=Parent Child circular redundancy
  44.141 -ClassCircularRedundancyDesc=Parent Child circular redundancy = A inherits B and B inherits A
  44.142 -ClassCircularRedundancyVariable=Parent/child {0} inheritance circular redundancy
  44.143 -
  44.144 -AllAssignExists=Symbol defined in __all__ does not exist
  44.145 -AllAssignExistsDesc=Checks that all symbols listed in __all__ actually exist
  44.146 -AllAssignExistsMsg="{0}" defined in __all__ does not exist!
  44.147 -UnusedDetectorPrefs.skipParams.text=Ignore unused function parameters
  44.148 -UnusedDetectorPrefs.ignoredLabel.text=Ignored names:
  44.149 -UnusedDetectorPrefs.skipTupleAssignments.text=Ignore unused variables in tuple-assignments
    45.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/ClassCircularRedundancy.java	Sat Sep 12 23:03:15 2015 -0700
    45.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.3 @@ -1,140 +0,0 @@
    45.4 -/*
    45.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    45.6 - *
    45.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    45.8 - *
    45.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   45.10 - * Other names may be trademarks of their respective owners.
   45.11 - *
   45.12 - * The contents of this file are subject to the terms of either the GNU
   45.13 - * General Public License Version 2 only ("GPL") or the Common
   45.14 - * Development and Distribution License("CDDL") (collectively, the
   45.15 - * "License"). You may not use this file except in compliance with the
   45.16 - * License. You can obtain a copy of the License at
   45.17 - * http://www.netbeans.org/cddl-gplv2.html
   45.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   45.19 - * specific language governing permissions and limitations under the
   45.20 - * License.  When distributing the software, include this License Header
   45.21 - * Notice in each file and include the License file at
   45.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   45.23 - * particular file as subject to the "Classpath" exception as provided
   45.24 - * by Oracle in the GPL Version 2 section of the License file that
   45.25 - * accompanied this code. If applicable, add the following below the
   45.26 - * License Header, with the fields enclosed by brackets [] replaced by
   45.27 - * your own identifying information:
   45.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   45.29 - *
   45.30 - * If you wish your version of this file to be governed by only the CDDL
   45.31 - * or only the GPL Version 2, indicate your decision by adding
   45.32 - * "[Contributor] elects to include this software in this distribution
   45.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   45.34 - * single choice of license, a recipient has the option to distribute
   45.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   45.36 - * to extend the choice of license to its licensees as provided above.
   45.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   45.38 - * Version 2 license, then the option applies only if the new code is
   45.39 - * made subject to such option by the copyright holder.
   45.40 - *
   45.41 - * Contributor(s):
   45.42 - *
   45.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   45.44 - */
   45.45 -package org.netbeans.modules.python.editor.hints;
   45.46 -
   45.47 -import java.util.Collections;
   45.48 -import java.util.HashMap;
   45.49 -import java.util.List;
   45.50 -import java.util.Map.Entry;
   45.51 -import java.util.Set;
   45.52 -import java.util.prefs.Preferences;
   45.53 -import javax.swing.JComponent;
   45.54 -import org.netbeans.modules.csl.api.Hint;
   45.55 -import org.netbeans.modules.csl.api.HintFix;
   45.56 -import org.netbeans.modules.csl.api.HintSeverity;
   45.57 -import org.netbeans.modules.csl.api.OffsetRange;
   45.58 -import org.netbeans.modules.csl.api.RuleContext;
   45.59 -import org.netbeans.modules.python.editor.PythonAstUtils;
   45.60 -import org.netbeans.modules.python.editor.PythonParserResult;
   45.61 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
   45.62 -import org.openide.util.NbBundle;
   45.63 -import org.python.antlr.ast.ClassDef;
   45.64 -import org.python.antlr.ast.Module;
   45.65 -
   45.66 -/**
   45.67 - * check for redundancy cycling in parent child
   45.68 - * @author Jean-Yves Mengant
   45.69 - */
   45.70 -public class ClassCircularRedundancy extends PythonAstRule {
   45.71 -    private final static String CLASS_CIRCULAR_REDUNDANCY = "ClassCircularRedundancy";
   45.72 -    private final static String CLASS_CIRCULAR_REDUNDANCY_VAR = "ClassCircularRedundancyVariable";
   45.73 -    private final static String CLASS_CIRCULAR_REDUNDANCY_DESC = "ClassCircularRedundancyDesc";
   45.74 -
   45.75 -    @Override
   45.76 -    public Set<Class> getKinds() {
   45.77 -        return Collections.<Class>singleton(Module.class);
   45.78 -    }
   45.79 -
   45.80 -    @Override
   45.81 -    public void run(PythonRuleContext context, List<Hint> result) {
   45.82 -        PythonParserResult info = (PythonParserResult) context.parserResult;
   45.83 -        SymbolTable symbolTable = info.getSymbolTable();
   45.84 -
   45.85 -
   45.86 -        HashMap<ClassDef, String> cyclingRedundancies = symbolTable.getClassesCyclingRedundancies(info);
   45.87 -        if (cyclingRedundancies.size() > 0) {
   45.88 -            Set<Entry<ClassDef, String>> wk = cyclingRedundancies.entrySet();
   45.89 -            for (Entry<ClassDef, String> cur : wk) {
   45.90 -                ClassDef curClass = cur.getKey();
   45.91 -                String curCyclingMsg = curClass.getInternalName() + "/" + cur.getValue(); // NOI18N
   45.92 -                OffsetRange range = PythonAstUtils.getNameRange(info, curClass);
   45.93 -                // range = PythonLexerUtils.getLexerOffsets(info, range);
   45.94 -                if (range != OffsetRange.NONE) {
   45.95 -                    List<HintFix> fixList = Collections.emptyList();
   45.96 -                    String message = NbBundle.getMessage(NameRule.class, CLASS_CIRCULAR_REDUNDANCY_VAR, curCyclingMsg);
   45.97 -                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
   45.98 -                    result.add(desc);
   45.99 -                }
  45.100 -            }
  45.101 -        }
  45.102 -    }
  45.103 -
  45.104 -    @Override
  45.105 -    public String getId() {
  45.106 -        return CLASS_CIRCULAR_REDUNDANCY;
  45.107 -    }
  45.108 -
  45.109 -    @Override
  45.110 -    public String getDescription() {
  45.111 -        return NbBundle.getMessage(RelativeImports.class, CLASS_CIRCULAR_REDUNDANCY_DESC);
  45.112 -    }
  45.113 -
  45.114 -    @Override
  45.115 -    public boolean getDefaultEnabled() {
  45.116 -        return false;
  45.117 -    }
  45.118 -
  45.119 -    @Override
  45.120 -    public JComponent getCustomizer(Preferences node) {
  45.121 -        return null;
  45.122 -    }
  45.123 -
  45.124 -    @Override
  45.125 -    public boolean appliesTo(RuleContext context) {
  45.126 -        return true;
  45.127 -    }
  45.128 -
  45.129 -    @Override
  45.130 -    public String getDisplayName() {
  45.131 -        return NbBundle.getMessage(AccessToProtected.class, CLASS_CIRCULAR_REDUNDANCY);
  45.132 -    }
  45.133 -
  45.134 -    @Override
  45.135 -    public boolean showInTasklist() {
  45.136 -        return true;
  45.137 -    }
  45.138 -
  45.139 -    @Override
  45.140 -    public HintSeverity getDefaultSeverity() {
  45.141 -        return HintSeverity.ERROR;
  45.142 -    }
  45.143 -}
    46.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/CreateDocString.java	Sat Sep 12 23:03:15 2015 -0700
    46.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.3 @@ -1,241 +0,0 @@
    46.4 -/*
    46.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    46.6 - *
    46.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    46.8 - *
    46.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   46.10 - * Other names may be trademarks of their respective owners.
   46.11 - *
   46.12 - * The contents of this file are subject to the terms of either the GNU
   46.13 - * General Public License Version 2 only ("GPL") or the Common
   46.14 - * Development and Distribution License("CDDL") (collectively, the
   46.15 - * "License"). You may not use this file except in compliance with the
   46.16 - * License. You can obtain a copy of the License at
   46.17 - * http://www.netbeans.org/cddl-gplv2.html
   46.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   46.19 - * specific language governing permissions and limitations under the
   46.20 - * License.  When distributing the software, include this License Header
   46.21 - * Notice in each file and include the License file at
   46.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   46.23 - * particular file as subject to the "Classpath" exception as provided
   46.24 - * by Oracle in the GPL Version 2 section of the License file that
   46.25 - * accompanied this code. If applicable, add the following below the
   46.26 - * License Header, with the fields enclosed by brackets [] replaced by
   46.27 - * your own identifying information:
   46.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   46.29 - *
   46.30 - * Contributor(s):
   46.31 - *
   46.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   46.33 - */
   46.34 -package org.netbeans.modules.python.editor.hints;
   46.35 -
   46.36 -import java.util.ArrayList;
   46.37 -import java.util.Collections;
   46.38 -import java.util.HashSet;
   46.39 -import java.util.List;
   46.40 -import java.util.Set;
   46.41 -import java.util.prefs.Preferences;
   46.42 -import javax.swing.JComponent;
   46.43 -import javax.swing.text.BadLocationException;
   46.44 -import javax.swing.text.JTextComponent;
   46.45 -import javax.swing.text.Position;
   46.46 -import org.netbeans.modules.python.editor.PythonAstUtils;
   46.47 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   46.48 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   46.49 -import org.netbeans.api.lexer.Token;
   46.50 -import org.netbeans.api.lexer.TokenSequence;
   46.51 -import org.netbeans.editor.BaseDocument;
   46.52 -import org.netbeans.editor.Utilities;
   46.53 -import org.netbeans.modules.csl.api.EditList;
   46.54 -import org.netbeans.modules.csl.api.Hint;
   46.55 -import org.netbeans.modules.csl.api.HintFix;
   46.56 -import org.netbeans.modules.csl.api.HintSeverity;
   46.57 -import org.netbeans.modules.csl.api.OffsetRange;
   46.58 -import org.netbeans.modules.csl.api.PreviewableFix;
   46.59 -import org.netbeans.modules.csl.api.RuleContext;
   46.60 -import org.netbeans.modules.csl.spi.GsfUtilities;
   46.61 -import org.netbeans.modules.editor.indent.api.IndentUtils;
   46.62 -import org.netbeans.modules.python.editor.PythonParserResult;
   46.63 -import org.openide.util.Exceptions;
   46.64 -import org.openide.util.NbBundle;
   46.65 -import org.python.antlr.PythonTree;
   46.66 -import org.python.antlr.ast.ClassDef;
   46.67 -import org.python.antlr.ast.FunctionDef;
   46.68 -
   46.69 -/**
   46.70 - * Offer to create docstrings.
   46.71 - * @todo Handle modules?
   46.72 - * @todo Handle parameter tags (for epydoc etc)
   46.73 - *
   46.74 - * @author Tor Norbye
   46.75 - */
   46.76 -public class CreateDocString extends PythonAstRule {
   46.77 -    @Override
   46.78 -    public Set<Class> getKinds() {
   46.79 -        Set<Class> classes = new HashSet<>();
   46.80 -        classes.add(FunctionDef.class);
   46.81 -        classes.add(ClassDef.class);
   46.82 -
   46.83 -        return classes;
   46.84 -    }
   46.85 -
   46.86 -    @Override
   46.87 -    public void run(PythonRuleContext context, List<Hint> result) {
   46.88 -
   46.89 -        PythonTree node = context.node;
   46.90 -        if (PythonAstUtils.getDocumentationNode(node) != null) {
   46.91 -            return;
   46.92 -        }
   46.93 -
   46.94 -        // Create new fix
   46.95 -        PythonParserResult info = (PythonParserResult) context.parserResult;
   46.96 -        OffsetRange astOffsets = PythonAstUtils.getNameRange(info, node);
   46.97 -        OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
   46.98 -        BaseDocument doc = context.doc;
   46.99 -        try {
  46.100 -            if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
  46.101 -                    (context.caretOffset == -1 ||
  46.102 -                    Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
  46.103 -                List<HintFix> fixList = new ArrayList<>();
  46.104 -                boolean singleIsDefault = node.getClass() == FunctionDef.class;
  46.105 -                fixList.add(new CreateDocStringFix(context, node, !singleIsDefault));
  46.106 -                fixList.add(new CreateDocStringFix(context, node, singleIsDefault));
  46.107 -                String displayName = getDisplayName();
  46.108 -                Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
  46.109 -                result.add(desc);
  46.110 -            }
  46.111 -        } catch (BadLocationException ex) {
  46.112 -            Exceptions.printStackTrace(ex);
  46.113 -        }
  46.114 -    }
  46.115 -
  46.116 -    @Override
  46.117 -    public String getId() {
  46.118 -        return "CreateDocString"; // NOI18N
  46.119 -    }
  46.120 -
  46.121 -    @Override
  46.122 -    public String getDisplayName() {
  46.123 -        return NbBundle.getMessage(CreateDocString.class, "CreateDocString");
  46.124 -    }
  46.125 -
  46.126 -    @Override
  46.127 -    public String getDescription() {
  46.128 -        return NbBundle.getMessage(CreateDocString.class, "CreateDocStringDesc");
  46.129 -    }
  46.130 -
  46.131 -    @Override
  46.132 -    public boolean getDefaultEnabled() {
  46.133 -        return true;
  46.134 -    }
  46.135 -
  46.136 -    @Override
  46.137 -    public JComponent getCustomizer(Preferences node) {
  46.138 -        return null;
  46.139 -    }
  46.140 -
  46.141 -    @Override
  46.142 -    public boolean appliesTo(RuleContext context) {
  46.143 -        return true;
  46.144 -    }
  46.145 -
  46.146 -    @Override
  46.147 -    public boolean showInTasklist() {
  46.148 -        return false;
  46.149 -    }
  46.150 -
  46.151 -    @Override
  46.152 -    public HintSeverity getDefaultSeverity() {
  46.153 -        return HintSeverity.CURRENT_LINE_WARNING;
  46.154 -    }
  46.155 -
  46.156 -    private static class CreateDocStringFix implements PreviewableFix {
  46.157 -        private final PythonRuleContext context;
  46.158 -        private final PythonTree node;
  46.159 -        private final boolean multiLine;
  46.160 -        private int editListPosition;
  46.161 -
  46.162 -        private CreateDocStringFix(PythonRuleContext context, PythonTree node, boolean multiLine) {
  46.163 -            this.context = context;
  46.164 -            this.node = node;
  46.165 -            this.multiLine = multiLine;
  46.166 -        }
  46.167 -
  46.168 -        @Override
  46.169 -        public String getDescription() {
  46.170 -            return multiLine ? NbBundle.getMessage(CreateDocString.class, "CreateDocStringFixMulti") : NbBundle.getMessage(CreateDocString.class, "CreateDocStringFix");
  46.171 -        }
  46.172 -
  46.173 -        @Override
  46.174 -        public boolean canPreview() {
  46.175 -            return true;
  46.176 -        }
  46.177 -
  46.178 -        @Override
  46.179 -        public EditList getEditList() throws Exception {
  46.180 -            BaseDocument doc = context.doc;
  46.181 -            EditList edits = new EditList(doc);
  46.182 -
  46.183 -            OffsetRange astRange = PythonAstUtils.getRange(node);
  46.184 -            if (astRange != OffsetRange.NONE) {
  46.185 -                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets((PythonParserResult) context.parserResult, astRange);
  46.186 -                if (lexRange != OffsetRange.NONE) {
  46.187 -                    // Find the colon
  46.188 -                    TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPositionedSequence(doc, lexRange.getStart());
  46.189 -                    if (ts != null) {
  46.190 -                        Token<? extends PythonTokenId> token = PythonLexerUtils.findNextIncluding(ts, Collections.singletonList(PythonTokenId.COLON));
  46.191 -                        if (token != null) {
  46.192 -                            int offset = ts.offset();
  46.193 -                            if (offset < lexRange.getEnd()) {
  46.194 -                                int indent = GsfUtilities.getLineIndent(doc, lexRange.getStart()) +
  46.195 -                                        IndentUtils.indentLevelSize(doc);
  46.196 -                                StringBuilder sb = new StringBuilder();
  46.197 -                                sb.append(IndentUtils.createIndentString(doc, indent));
  46.198 -                                int rowEnd = Utilities.getRowEnd(doc, offset) + 1;
  46.199 -                                sb.append("\"\"\""); // NOI18N
  46.200 -                                if (multiLine) {
  46.201 -                                    sb.append("\n"); // NOI18N
  46.202 -                                    sb.append(IndentUtils.createIndentString(doc, indent));
  46.203 -                                }
  46.204 -                                editListPosition = rowEnd + sb.length();
  46.205 -                                if (multiLine) {
  46.206 -                                    sb.append("\n"); // NOI18N
  46.207 -                                    sb.append(IndentUtils.createIndentString(doc, indent));
  46.208 -                                }
  46.209 -                                sb.append("\"\"\"\n"); // NOI18N
  46.210 -                                edits.replace(rowEnd, 0, sb.toString(), false, 0);
  46.211 -                            }
  46.212 -                        }
  46.213 -                    }
  46.214 -                }
  46.215 -            }
  46.216 -
  46.217 -            return edits;
  46.218 -        }
  46.219 -
  46.220 -        @Override
  46.221 -        public void implement() throws Exception {
  46.222 -            EditList edits = getEditList();
  46.223 -
  46.224 -            Position pos = edits.createPosition(editListPosition);
  46.225 -            edits.apply();
  46.226 -            if (pos != null && pos.getOffset() != -1) {
  46.227 -                JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
  46.228 -                if (target != null) {
  46.229 -                    target.setCaretPosition(pos.getOffset());
  46.230 -                }
  46.231 -            }
  46.232 -        }
  46.233 -
  46.234 -        @Override
  46.235 -        public boolean isSafe() {
  46.236 -            return true;
  46.237 -        }
  46.238 -
  46.239 -        @Override
  46.240 -        public boolean isInteractive() {
  46.241 -            return false;
  46.242 -        }
  46.243 -    }
  46.244 -}
    47.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/Deprecations.java	Sat Sep 12 23:03:15 2015 -0700
    47.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.3 @@ -1,293 +0,0 @@
    47.4 -/*
    47.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    47.6 - *
    47.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    47.8 - *
    47.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   47.10 - * Other names may be trademarks of their respective owners.
   47.11 - *
   47.12 - * The contents of this file are subject to the terms of either the GNU
   47.13 - * General Public License Version 2 only ("GPL") or the Common
   47.14 - * Development and Distribution License("CDDL") (collectively, the
   47.15 - * "License"). You may not use this file except in compliance with the
   47.16 - * License. You can obtain a copy of the License at
   47.17 - * http://www.netbeans.org/cddl-gplv2.html
   47.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   47.19 - * specific language governing permissions and limitations under the
   47.20 - * License.  When distributing the software, include this License Header
   47.21 - * Notice in each file and include the License file at
   47.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   47.23 - * particular file as subject to the "Classpath" exception as provided
   47.24 - * by Oracle in the GPL Version 2 section of the License file that
   47.25 - * accompanied this code. If applicable, add the following below the
   47.26 - * License Header, with the fields enclosed by brackets [] replaced by
   47.27 - * your own identifying information:
   47.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   47.29 - *
   47.30 - * If you wish your version of this file to be governed by only the CDDL
   47.31 - * or only the GPL Version 2, indicate your decision by adding
   47.32 - * "[Contributor] elects to include this software in this distribution
   47.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   47.34 - * single choice of license, a recipient has the option to distribute
   47.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   47.36 - * to extend the choice of license to its licensees as provided above.
   47.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   47.38 - * Version 2 license, then the option applies only if the new code is
   47.39 - * made subject to such option by the copyright holder.
   47.40 - *
   47.41 - * Contributor(s):
   47.42 - *
   47.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   47.44 - */
   47.45 -package org.netbeans.modules.python.editor.hints;
   47.46 -
   47.47 -import java.util.Collections;
   47.48 -import java.util.HashMap;
   47.49 -import java.util.HashSet;
   47.50 -import java.util.List;
   47.51 -import java.util.Map;
   47.52 -import java.util.Set;
   47.53 -import java.util.prefs.Preferences;
   47.54 -import javax.swing.JComponent;
   47.55 -import javax.swing.text.BadLocationException;
   47.56 -import org.netbeans.modules.python.editor.PythonAstUtils;
   47.57 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   47.58 -import org.netbeans.editor.BaseDocument;
   47.59 -import org.netbeans.editor.Utilities;
   47.60 -import org.netbeans.modules.csl.api.Hint;
   47.61 -import org.netbeans.modules.csl.api.HintFix;
   47.62 -import org.netbeans.modules.csl.api.HintSeverity;
   47.63 -import org.netbeans.modules.csl.api.OffsetRange;
   47.64 -import org.netbeans.modules.csl.api.RuleContext;
   47.65 -import org.netbeans.modules.python.editor.PythonParserResult;
   47.66 -import org.openide.util.Exceptions;
   47.67 -import org.openide.util.NbBundle;
   47.68 -import org.python.antlr.PythonTree;
   47.69 -import org.python.antlr.ast.Import;
   47.70 -import org.python.antlr.ast.ImportFrom;
   47.71 -import org.python.antlr.ast.alias;
   47.72 -
   47.73 -/**
   47.74 - * Handle deprecaton warnings, for modules listed as obsolete or
   47.75 - * deprecated in PEP4:
   47.76 - *   http://www.python.org/dev/peps/pep-0004/
   47.77 - *
   47.78 - * Todo: Add a hint to enforce this from PEP8:
   47.79 -- Comparisons to singletons like None should always be done with
   47.80 -'is' or 'is not', never the equality operators.
   47.81 - *  In general, see the "Programming Recommendations" list from
   47.82 - *    http://www.python.org/dev/peps/pep-0008/ - there are lots
   47.83 - *    of thins to check from there.  Check the PyLint list as well.
   47.84 - *
   47.85 - *
   47.86 - * @author Tor Norbye
   47.87 - */
   47.88 -public class Deprecations extends PythonAstRule {
   47.89 -    private static final Map<String, String> deprecated = new HashMap<>();
   47.90 -
   47.91 -
   47.92 -    static {
   47.93 -        for (String module : new String[]{"cl", "sv", "timing"}) {
   47.94 -            deprecated.put(module, "Listed as obsolete in the library documentation");
   47.95 -        }
   47.96 -
   47.97 -        for (String module : new String[]{
   47.98 -                    "addpack", "cmp", "cmpcache", "codehack", "dircmp", "dump", "find", "fmt",
   47.99 -                    "grep", "lockfile", "newdir", "ni", "packmail", "Para", "poly",
  47.100 -                    "rand", "reconvert", "regex", "regsub", "statcache", "tb", "tzparse",
  47.101 -                    "util", "whatsound", "whrandom", "zmod"}) {
  47.102 -            deprecated.put(module, "Obsolete module, removed in Python 2.5");
  47.103 -
  47.104 -        }
  47.105 -
  47.106 -        for (String module : new String[]{"gopherlib", "rgbimg", "macfs"}) {
  47.107 -            deprecated.put(module, "Obsolete module, removed in Python 2.6");
  47.108 -        }
  47.109 -
  47.110 -        /*
  47.111 -        al.rst:    The :mod:`al` module has been deprecated for removal in Python 3.0.
  47.112 -        al.rst:   The :mod:`AL` module has been deprecated for removal in Python 3.0.
  47.113 -        bsddb.rst:    The :mod:`bsddb` module has been deprecated for removal in Python 3.0.
  47.114 -        cd.rst:    The :mod:`cd` module has been deprecated for removal in Python 3.0.
  47.115 -        dbhash.rst:    The :mod:`dbhash` module has been deprecated for removal in Python 3.0.
  47.116 -        fl.rst:    The :mod:`fl` module has been deprecated for removal in Python 3.0.
  47.117 -        fl.rst:    The :mod:`FL` module has been deprecated for removal in Python 3.0.
  47.118 -        fl.rst:    The :mod:`flp` module has been deprecated for removal in Python 3.0.
  47.119 -        fm.rst:   The :mod:`fm` module has been deprecated for removal in Python 3.0.
  47.120 -        gl.rst:    The :mod:`gl` module has been deprecated for removal in Python 3.0.
  47.121 -        gl.rst:    The :mod:`DEVICE` module has been deprecated for removal in Python 3.0.
  47.122 -        gl.rst:    The :mod:`GL` module has been deprecated for removal in Python 3.0.
  47.123 -        imgfile.rst:   The :mod:`imgfile` module has been deprecated for removal in Python 3.0.
  47.124 -        jpeg.rst:   The :mod:`jpeg` module has been deprecated for removal in Python 3.0.
  47.125 -        statvfs.rst:   The :mod:`statvfs` module has been deprecated for removal in Python 3.0.
  47.126 -        sunaudio.rst:   The :mod:`sunaudiodev` module has been deprecated for removal in Python 3.0.
  47.127 -        sunaudio.rst:   The :mod:`SUNAUDIODEV` module has been deprecated for removal in Python 3.0.
  47.128 -        tarfile.rst:      The :class:`TarFileCompat` class has been deprecated for removal in Python 3.0.
  47.129 -         */
  47.130 -
  47.131 -        deprecated.put("posixfile",
  47.132 -                "Locking is better done by fcntl.lockf().");
  47.133 -
  47.134 -        deprecated.put("gopherlib",
  47.135 -                "The gopher protocol is not in active use anymore.");
  47.136 -
  47.137 -        deprecated.put("rgbimgmodule",
  47.138 -                "");
  47.139 -
  47.140 -        deprecated.put("pre",
  47.141 -                "The underlying PCRE engine doesn't support Unicode, and has been unmaintained since Python 1.5.2.");
  47.142 -
  47.143 -        deprecated.put("whrandom",
  47.144 -                "The module's default seed computation was inherently insecure; the random module should be used instead.");
  47.145 -
  47.146 -        deprecated.put("rfc822",
  47.147 -                "Supplanted by Python 2.2's email package.");
  47.148 -
  47.149 -        deprecated.put("mimetools",
  47.150 -                "Supplanted by Python 2.2's email package.");
  47.151 -
  47.152 -        deprecated.put("MimeWriter",
  47.153 -                "Supplanted by Python 2.2's email package.");
  47.154 -
  47.155 -        deprecated.put("mimify",
  47.156 -                "Supplanted by Python 2.2's email package.");
  47.157 -
  47.158 -        deprecated.put("rotor",
  47.159 -                "Uses insecure algorithm.");
  47.160 -
  47.161 -        deprecated.put("TERMIOS.py",
  47.162 -                "The constants in this file are now in the 'termios' module.");
  47.163 -
  47.164 -        deprecated.put("statcache",
  47.165 -                "Using the cache can be fragile and error-prone; applications should just use os.stat() directly.");
  47.166 -
  47.167 -        deprecated.put("mpz",
  47.168 -                "Third-party packages provide similiar features and wrap more of GMP's API.");
  47.169 -
  47.170 -
  47.171 -        deprecated.put("xreadlines",
  47.172 -                "Using 'for line in file', introduced in 2.3, is preferable.");
  47.173 -
  47.174 -        deprecated.put("multifile",
  47.175 -                "Supplanted by the email package.");
  47.176 -
  47.177 -        deprecated.put("sets",
  47.178 -                "The built-in set/frozenset types, introduced in Python 2.4, supplant the module.");
  47.179 -
  47.180 -        deprecated.put("buildtools",
  47.181 -                "");
  47.182 -
  47.183 -        deprecated.put("cfmfile",
  47.184 -                "");
  47.185 -
  47.186 -        deprecated.put("macfs",
  47.187 -                "");
  47.188 -
  47.189 -        deprecated.put("md5",
  47.190 -                "Replaced by the 'hashlib' module.");
  47.191 -
  47.192 -        deprecated.put("sha",
  47.193 -                "Replaced by the 'hashlib' module.");
  47.194 -    }
  47.195 -
  47.196 -    public static boolean isDeprecatedModule(String module) {
  47.197 -        return deprecated.containsKey(module);
  47.198 -    }
  47.199 -
  47.200 -    @Override
  47.201 -    public Set<Class> getKinds() {
  47.202 -        HashSet<Class> kinds = new HashSet<>();
  47.203 -        kinds.add(Import.class);
  47.204 -        kinds.add(ImportFrom.class);
  47.205 -
  47.206 -        return kinds;
  47.207 -    }
  47.208 -
  47.209 -    @Override
  47.210 -    public void run(PythonRuleContext context, List<Hint> result) {
  47.211 -        PythonTree node = context.node;
  47.212 -        if (node instanceof Import) {
  47.213 -            Import imp = (Import)node;
  47.214 -            List<alias> names = imp.getInternalNames();
  47.215 -            if (names != null) {
  47.216 -                for (alias alias : names) {
  47.217 -                    String name = alias.getInternalName();
  47.218 -                    if (deprecated.containsKey(name)) {
  47.219 -                        addDeprecation(name, deprecated.get(name), context, result);
  47.220 -                    }
  47.221 -                }
  47.222 -            }
  47.223 -        } else {
  47.224 -            assert node instanceof ImportFrom;
  47.225 -            ImportFrom imp = (ImportFrom)node;
  47.226 -            String name = imp.getInternalModule();
  47.227 -            if (deprecated.containsKey(name)) {
  47.228 -                addDeprecation(name, deprecated.get(name), context, result);
  47.229 -            }
  47.230 -        }
  47.231 -    }
  47.232 -
  47.233 -    private void addDeprecation(String module, String rationale, PythonRuleContext context, List<Hint> result) {
  47.234 -        PythonParserResult info = (PythonParserResult) context.parserResult;
  47.235 -        OffsetRange astOffsets = PythonAstUtils.getNameRange(info, context.node);
  47.236 -        OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
  47.237 -        BaseDocument doc = context.doc;
  47.238 -        try {
  47.239 -            if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
  47.240 -                    (context.caretOffset == -1 ||
  47.241 -                    Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
  47.242 -                List<HintFix> fixList = Collections.emptyList();
  47.243 -                String displayName;
  47.244 -                if (rationale.length() > 0) {
  47.245 -                    displayName = NbBundle.getMessage(Deprecations.class, "DeprecationsMsgDetail", module, rationale);
  47.246 -                } else {
  47.247 -                    displayName = NbBundle.getMessage(Deprecations.class, "DeprecationsMsg", module);
  47.248 -                }
  47.249 -                Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
  47.250 -                result.add(desc);
  47.251 -            }
  47.252 -        } catch (BadLocationException ex) {
  47.253 -            Exceptions.printStackTrace(ex);
  47.254 -        }
  47.255 -    }
  47.256 -
  47.257 -    @Override
  47.258 -    public String getId() {
  47.259 -        return "Deprecations"; // NOI18N
  47.260 -    }
  47.261 -
  47.262 -    @Override
  47.263 -    public String getDisplayName() {
  47.264 -        return NbBundle.getMessage(Deprecations.class, "Deprecations");
  47.265 -    }
  47.266 -
  47.267 -    @Override
  47.268 -    public String getDescription() {
  47.269 -        return NbBundle.getMessage(Deprecations.class, "DeprecationsDesc");
  47.270 -    }
  47.271 -
  47.272 -    @Override
  47.273 -    public boolean getDefaultEnabled() {
  47.274 -        return true;
  47.275 -    }
  47.276 -
  47.277 -    @Override
  47.278 -    public JComponent getCustomizer(Preferences node) {
  47.279 -        return null;
  47.280 -    }
  47.281 -
  47.282 -    @Override
  47.283 -    public boolean appliesTo(RuleContext context) {
  47.284 -        return true;
  47.285 -    }
  47.286 -
  47.287 -    @Override
  47.288 -    public boolean showInTasklist() {
  47.289 -        return true;
  47.290 -    }
  47.291 -
  47.292 -    @Override
  47.293 -    public HintSeverity getDefaultSeverity() {
  47.294 -        return HintSeverity.WARNING;
  47.295 -    }
  47.296 -}
    48.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/ExtractCode.java	Sat Sep 12 23:03:15 2015 -0700
    48.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.3 @@ -1,759 +0,0 @@
    48.4 -/*
    48.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    48.6 - *
    48.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    48.8 - *
    48.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   48.10 - * Other names may be trademarks of their respective owners.
   48.11 - *
   48.12 - * The contents of this file are subject to the terms of either the GNU
   48.13 - * General Public License Version 2 only ("GPL") or the Common
   48.14 - * Development and Distribution License("CDDL") (collectively, the
   48.15 - * "License"). You may not use this file except in compliance with the
   48.16 - * License. You can obtain a copy of the License at
   48.17 - * http://www.netbeans.org/cddl-gplv2.html
   48.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   48.19 - * specific language governing permissions and limitations under the
   48.20 - * License.  When distributing the software, include this License Header
   48.21 - * Notice in each file and include the License file at
   48.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   48.23 - * particular file as subject to the "Classpath" exception as provided
   48.24 - * by Oracle in the GPL Version 2 section of the License file that
   48.25 - * accompanied this code. If applicable, add the following below the
   48.26 - * License Header, with the fields enclosed by brackets [] replaced by
   48.27 - * your own identifying information:
   48.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   48.29 - *
   48.30 - * Contributor(s):
   48.31 - *
   48.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   48.33 - */
   48.34 -package org.netbeans.modules.python.editor.hints;
   48.35 -
   48.36 -import java.util.ArrayList;
   48.37 -import java.util.Collections;
   48.38 -import java.util.HashSet;
   48.39 -import java.util.List;
   48.40 -import java.util.Set;
   48.41 -import java.util.prefs.Preferences;
   48.42 -import javax.swing.JComponent;
   48.43 -import javax.swing.text.JTextComponent;
   48.44 -import org.netbeans.editor.BaseDocument;
   48.45 -import org.netbeans.editor.Utilities;
   48.46 -import org.netbeans.modules.csl.api.EditList;
   48.47 -import org.netbeans.modules.csl.api.EditRegions;
   48.48 -import org.netbeans.modules.csl.api.Hint;
   48.49 -import org.netbeans.modules.csl.api.HintFix;
   48.50 -import org.netbeans.modules.csl.api.HintSeverity;
   48.51 -import org.netbeans.modules.csl.api.OffsetRange;
   48.52 -import org.netbeans.modules.csl.api.PreviewableFix;
   48.53 -import org.netbeans.modules.csl.api.RuleContext;
   48.54 -import org.netbeans.modules.csl.spi.GsfUtilities;
   48.55 -import org.netbeans.modules.editor.indent.api.IndentUtils;
   48.56 -import org.netbeans.modules.python.editor.AstPath;
   48.57 -import org.netbeans.modules.python.editor.PythonAstUtils;
   48.58 -import org.netbeans.modules.python.editor.PythonParserResult;
   48.59 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   48.60 -import org.openide.util.Exceptions;
   48.61 -import org.openide.util.NbBundle;
   48.62 -import org.python.antlr.PythonTree;
   48.63 -import org.python.antlr.Visitor;
   48.64 -import org.python.antlr.ast.Assert;
   48.65 -import org.python.antlr.ast.Assign;
   48.66 -import org.python.antlr.ast.AugAssign;
   48.67 -import org.python.antlr.ast.Break;
   48.68 -import org.python.antlr.ast.Call;
   48.69 -import org.python.antlr.ast.ClassDef;
   48.70 -import org.python.antlr.ast.Continue;
   48.71 -import org.python.antlr.ast.Delete;
   48.72 -import org.python.antlr.ast.For;
   48.73 -import org.python.antlr.ast.FunctionDef;
   48.74 -import org.python.antlr.ast.Global;
   48.75 -import org.python.antlr.ast.If;
   48.76 -import org.python.antlr.ast.IfExp;
   48.77 -import org.python.antlr.ast.Import;
   48.78 -import org.python.antlr.ast.ImportFrom;
   48.79 -import org.python.antlr.ast.Module;
   48.80 -import org.python.antlr.ast.Name;
   48.81 -import org.python.antlr.ast.Num;
   48.82 -import org.python.antlr.ast.Pass;
   48.83 -import org.python.antlr.ast.Print;
   48.84 -import org.python.antlr.ast.Raise;
   48.85 -import org.python.antlr.ast.Return;
   48.86 -import org.python.antlr.ast.Str;
   48.87 -import org.python.antlr.ast.Suite;
   48.88 -import org.python.antlr.ast.TryExcept;
   48.89 -import org.python.antlr.ast.TryFinally;
   48.90 -import org.python.antlr.ast.Tuple;
   48.91 -import org.python.antlr.ast.While;
   48.92 -import org.python.antlr.ast.With;
   48.93 -import org.python.antlr.ast.Yield;
   48.94 -
   48.95 -/**
   48.96 - * Offer to introduce method/variable/constant
   48.97 - * @todo There is no need to pass in class or top level constants to code fragments
   48.98 - * @todo Handle flow control: If a code fragment contains an early return, figure out
   48.99 - *   how to pass that information back to the method callsite and do something clever,
  48.100 - *   for example pass back a to-return flag which returns the same value
  48.101 - * @todo Unit tests must check instant rename as well!
  48.102 - *
  48.103 - * @author Tor Norbye
  48.104 - */
  48.105 -public class ExtractCode extends PythonSelectionRule {
  48.106 -    //private static final int NOT_APPLICABLE = 0;
  48.107 -    private static final int INTRODUCE_METHOD = 1;
  48.108 -    private static final int INTRODUCE_VARIABLE = 2;
  48.109 -    private static final int INTRODUCE_CONSTANT = 4;
  48.110 -    private static final int INTRODUCE_FIELD = 8;
  48.111 -    private static final int NON_EXPRESSIONS = INTRODUCE_VARIABLE | INTRODUCE_FIELD | INTRODUCE_CONSTANT;
  48.112 -    private static final int ALL = ~0;
  48.113 -
  48.114 -    @Override
  48.115 -    protected int getApplicability(PythonRuleContext context, PythonTree root, OffsetRange astRange) {
  48.116 -        return ApplicabilityVisitor.getType(root, astRange);
  48.117 -    }
  48.118 -
  48.119 -    @Override
  48.120 -    public void run(PythonRuleContext context, List<Hint> result, OffsetRange range, int applicability) {
  48.121 -        int start = range.getStart();
  48.122 -        int end = range.getEnd();
  48.123 -
  48.124 -// HACK: Only extract method works at this point
  48.125 -        applicability = applicability & INTRODUCE_METHOD;
  48.126 -
  48.127 -
  48.128 -        // Adjust the fix range to be right around the dot so that the light bulb ends up
  48.129 -        // on the same line as the caret and alt-enter works
  48.130 -        JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
  48.131 -        if (target != null) {
  48.132 -            int dot = target.getCaret().getDot();
  48.133 -            range = new OffsetRange(dot, dot);
  48.134 -        }
  48.135 -
  48.136 -        List<HintFix> fixList = new ArrayList<>(3);
  48.137 -        if ((applicability & INTRODUCE_METHOD) != 0) {
  48.138 -            fixList.add(new ExtractCodeFix(context, start, end, INTRODUCE_METHOD));
  48.139 -        }
  48.140 -        if ((applicability & INTRODUCE_VARIABLE) != 0) {
  48.141 -            fixList.add(new ExtractCodeFix(context, start, end, INTRODUCE_VARIABLE));
  48.142 -        }
  48.143 -        if ((applicability & INTRODUCE_CONSTANT) != 0) {
  48.144 -            fixList.add(new ExtractCodeFix(context, start, end, INTRODUCE_CONSTANT));
  48.145 -        }
  48.146 -        if ((applicability & INTRODUCE_FIELD) != 0) {
  48.147 -            fixList.add(new ExtractCodeFix(context, start, end, INTRODUCE_FIELD));
  48.148 -        }
  48.149 -        if (fixList.size() > 0) {
  48.150 -            String displayName = getDisplayName();
  48.151 -            Hint desc = new Hint(this, displayName, context.parserResult.getSnapshot().getSource().getFileObject(),
  48.152 -                    range, fixList, 490);
  48.153 -            result.add(desc);
  48.154 -        }
  48.155 -    }
  48.156 -
  48.157 -    @Override
  48.158 -    public boolean appliesTo(RuleContext context) {
  48.159 -        return true;
  48.160 -    }
  48.161 -
  48.162 -    @Override
  48.163 -    public String getDisplayName() {
  48.164 -        return NbBundle.getMessage(ExtractCode.class, "ExtractCode");
  48.165 -    }
  48.166 -
  48.167 -    @Override
  48.168 -    public String getId() {
  48.169 -        return "ExtractCode"; // NOI18N
  48.170 -    }
  48.171 -
  48.172 -    @Override
  48.173 -    public String getDescription() {
  48.174 -        return "";
  48.175 -    }
  48.176 -
  48.177 -    @Override
  48.178 -    public boolean getDefaultEnabled() {
  48.179 -        return true;
  48.180 -    }
  48.181 -
  48.182 -    @Override
  48.183 -    public JComponent getCustomizer(Preferences node) {
  48.184 -        return null;
  48.185 -    }
  48.186 -
  48.187 -    @Override
  48.188 -    public boolean showInTasklist() {
  48.189 -        return false;
  48.190 -    }
  48.191 -
  48.192 -    @Override
  48.193 -    public HintSeverity getDefaultSeverity() {
  48.194 -        return HintSeverity.CURRENT_LINE_WARNING;
  48.195 -    }
  48.196 -
  48.197 -    private static class ExtractCodeFix implements PreviewableFix {
  48.198 -        private final PythonRuleContext context;
  48.199 -        //private Position callSitePos;
  48.200 -        //private Position extractedPos;
  48.201 -        private int finalCallSiteOffset;
  48.202 -        private int finalExtractedSiteOffset;
  48.203 -        ;
  48.204 -        private final int type;
  48.205 -        private final int start;
  48.206 -        private final int end;
  48.207 -        private String newName;
  48.208 -
  48.209 -        private ExtractCodeFix(PythonRuleContext context,
  48.210 -                int start, int end, int type) {
  48.211 -            this.context = context;
  48.212 -
  48.213 -            OffsetRange range = PythonLexerUtils.narrow(context.doc, new OffsetRange(start, end), false);
  48.214 -            this.start = range.getStart();
  48.215 -            this.end = range.getEnd();
  48.216 -
  48.217 -            this.type = type;
  48.218 -        }
  48.219 -
  48.220 -        @Override
  48.221 -        public String getDescription() {
  48.222 -            switch (type) {
  48.223 -            case INTRODUCE_VARIABLE:
  48.224 -                return NbBundle.getMessage(CreateDocString.class, "IntroduceVariable");
  48.225 -            case INTRODUCE_CONSTANT:
  48.226 -                return NbBundle.getMessage(CreateDocString.class, "IntroduceConstant");
  48.227 -            case INTRODUCE_METHOD:
  48.228 -                return NbBundle.getMessage(CreateDocString.class, "IntroduceMethod");
  48.229 -            case INTRODUCE_FIELD:
  48.230 -                return NbBundle.getMessage(CreateDocString.class, "IntroduceField");
  48.231 -            default:
  48.232 -                throw new IllegalArgumentException();
  48.233 -            }
  48.234 -        }
  48.235 -
  48.236 -        @Override
  48.237 -        public boolean canPreview() {
  48.238 -            return true;
  48.239 -        }
  48.240 -
  48.241 -        @Override
  48.242 -        public EditList getEditList() throws Exception {
  48.243 -            BaseDocument doc = context.doc;
  48.244 -            PythonParserResult info = (PythonParserResult) context.parserResult;
  48.245 -            EditList edits = new EditList(doc);
  48.246 -
  48.247 -            int extractedOffset = doc.getLength();
  48.248 -            int prevFunctionOffset = 0;
  48.249 -            PythonTree root = PythonAstUtils.getRoot(info);
  48.250 -
  48.251 -            OffsetRange narrowed = PythonLexerUtils.narrow(doc, new OffsetRange(start, end), true);
  48.252 -
  48.253 -            int astStart = PythonAstUtils.getAstOffset(info, narrowed != OffsetRange.NONE ? narrowed.getStart() : start);
  48.254 -            int astEnd = PythonAstUtils.getAstOffset(info, narrowed != OffsetRange.NONE ? narrowed.getEnd() : end);
  48.255 -            if (astStart == -1 || astEnd == -1) {
  48.256 -                return edits;
  48.257 -            }
  48.258 -            AstPath startPath = AstPath.get(root, astStart);
  48.259 -            AstPath endPath = AstPath.get(root, astEnd);
  48.260 -            PythonTree localScope = PythonAstUtils.getLocalScope(startPath);
  48.261 -            if (localScope != null) {
  48.262 -                OffsetRange astRange = PythonAstUtils.getRange(localScope);
  48.263 -                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
  48.264 -                if (lexRange != OffsetRange.NONE) {
  48.265 -                    extractedOffset = lexRange.getEnd();
  48.266 -
  48.267 -                    // Function end offsets are a bit sloppy so try to deal with that
  48.268 -                    int firstNonWhite = Utilities.getRowFirstNonWhite(doc, Math.min(extractedOffset, doc.getLength()));
  48.269 -                    if (firstNonWhite == -1 || extractedOffset <= firstNonWhite) {
  48.270 -                        extractedOffset = Utilities.getRowStart(doc, extractedOffset);
  48.271 -                    }
  48.272 -
  48.273 -                    prevFunctionOffset = lexRange.getStart();
  48.274 -                    if (extractedOffset > doc.getLength()) {
  48.275 -                        extractedOffset = doc.getLength();
  48.276 -                    }
  48.277 -                }
  48.278 -            }
  48.279 -            int callSiteOffset = start;
  48.280 -            int callSiteReplaceLength = end - start;
  48.281 -
  48.282 -            int indentSize = IndentUtils.indentLevelSize(doc);
  48.283 -            int lineStart = Utilities.getRowStart(doc, prevFunctionOffset);
  48.284 -            int initialIndent = IndentUtils.lineIndent(doc, lineStart);
  48.285 -            String initialIndentStr = IndentUtils.createIndentString(doc, initialIndent);
  48.286 -
  48.287 -            newName = "new_name"; // TODO - localize!
  48.288 -
  48.289 -            // Compute input/output arguments
  48.290 -            PythonTree startNode = startPath.leaf();
  48.291 -            PythonTree endNode = endPath.leaf();
  48.292 -
  48.293 -            InputOutputFinder finder = new InputOutputFinder(startNode, endNode, Collections.<PythonTree>emptyList());
  48.294 -            finder.traverse(localScope);
  48.295 -            List<String> inParams = new ArrayList<>(finder.getInputVars());
  48.296 -            List<String> outParams = new ArrayList<>(finder.getOutputVars());
  48.297 -            Collections.sort(inParams);
  48.298 -            Collections.sort(outParams);
  48.299 -
  48.300 -            ClassDef cls = PythonAstUtils.getClassDef(startPath);
  48.301 -
  48.302 -            // Adjust the insert location in case we are at the top level
  48.303 -            if (cls == null && PythonAstUtils.getFuncDef(startPath) == null) {
  48.304 -                extractedOffset = -1;
  48.305 -                PythonTree top = startPath.topModuleLevel();
  48.306 -                if (top != null) {
  48.307 -                    OffsetRange astRange = PythonAstUtils.getRange(top);
  48.308 -                    extractedOffset = PythonLexerUtils.getLexerOffset(info, astRange.getStart());
  48.309 -                }
  48.310 -
  48.311 -                // We're at the top level - I can't insert the function -after- the current function
  48.312 -                // because that will result in a runtime error
  48.313 -                if (extractedOffset == -1) {
  48.314 -                    extractedOffset = Utilities.getRowStart(doc, Math.min(doc.getLength(), start));
  48.315 -                }
  48.316 -            }
  48.317 -
  48.318 -            String extractedCode = null;
  48.319 -            int extractedSiteDelta = 0;
  48.320 -            if (type == INTRODUCE_METHOD) {
  48.321 -                StringBuilder sb = new StringBuilder();
  48.322 -                if (Utilities.getRowStart(doc, Math.min(extractedOffset, doc.getLength())) < extractedOffset) {
  48.323 -                    sb.append("\n"); // NOI18N
  48.324 -                }
  48.325 -                sb.append("\n"); // NOI18N
  48.326 -                sb.append(initialIndentStr);
  48.327 -                sb.append("def "); // NOI18N
  48.328 -                extractedSiteDelta = sb.length();
  48.329 -                sb.append(newName);
  48.330 -                sb.append("("); // NOI18N
  48.331 -                if (cls != null) {
  48.332 -                    sb.append("self"); // NOI18N
  48.333 -                    if (inParams.size() > 0) {
  48.334 -                        sb.append(", "); // NOI18N
  48.335 -                    }
  48.336 -                }
  48.337 -                boolean first = true;
  48.338 -                for (String param : inParams) {
  48.339 -                    if (first) {
  48.340 -                        first = false;
  48.341 -                    } else {
  48.342 -                        sb.append(", "); // NOI18N
  48.343 -                    }
  48.344 -                    sb.append(param);
  48.345 -                }
  48.346 -                sb.append("):\n"); // NOI18N
  48.347 -
  48.348 -                // Copy in the extracted code
  48.349 -                int firstIndent = IndentUtils.lineIndent(doc, Utilities.getRowStart(doc, start));
  48.350 -                for (int offset = start; offset < end; offset = Utilities.getRowEnd(doc, offset) + 1) {
  48.351 -                    // TODO - handle multiline literal strings correctly!!!
  48.352 -                    if (!(Utilities.isRowEmpty(doc, offset) || Utilities.isRowWhite(doc, offset))) {
  48.353 -                        int lineIndent = IndentUtils.lineIndent(doc, Utilities.getRowStart(doc, offset));
  48.354 -                        int newIndent = (lineIndent - firstIndent) + initialIndent + indentSize;
  48.355 -                        if (newIndent > 0) {
  48.356 -                            sb.append(IndentUtils.createIndentString(doc, newIndent));
  48.357 -                        }
  48.358 -                        int rowFirstNonWhite = Utilities.getRowFirstNonWhite(doc, offset);
  48.359 -                        int rowLastNonWhite = Utilities.getRowLastNonWhite(doc, offset) + 1; // +1: doesn't include last char
  48.360 -                        sb.append(doc.getText(rowFirstNonWhite, rowLastNonWhite - rowFirstNonWhite));
  48.361 -                    }
  48.362 -                    sb.append("\n"); // NOI18N
  48.363 -                }
  48.364 -                sb.append("\n");
  48.365 -
  48.366 -                if (outParams.size() > 0) {
  48.367 -                    sb.append(IndentUtils.createIndentString(doc, initialIndent + indentSize));
  48.368 -                    sb.append("return "); // NOI18N
  48.369 -                    first = true;
  48.370 -                    for (String param : outParams) {
  48.371 -                        if (first) {
  48.372 -                            first = false;
  48.373 -                        } else {
  48.374 -                            // No spaces in the comma list for return tuples
  48.375 -                            sb.append(","); // NOI18N
  48.376 -                        }
  48.377 -                        sb.append(param);
  48.378 -                    }
  48.379 -                    sb.append("\n\n"); // NOI18N
  48.380 -                }
  48.381 -
  48.382 -                // Insert the extracted code at the end
  48.383 -                extractedCode = sb.toString();
  48.384 -            } else {
  48.385 -                assert (type == INTRODUCE_FIELD || type == INTRODUCE_CONSTANT || type == INTRODUCE_VARIABLE);
  48.386 -                throw new RuntimeException("Not yet implemented");
  48.387 -            }
  48.388 -
  48.389 -            // Replace the code at the extract site with just the call
  48.390 -            StringBuilder sb = new StringBuilder();
  48.391 -            if (type == INTRODUCE_METHOD) {
  48.392 -                // Assign to the output variables if any
  48.393 -                if (outParams.size() > 0) {
  48.394 -                    boolean first = true;
  48.395 -                    for (String param : outParams) {
  48.396 -                        if (first) {
  48.397 -                            first = false;
  48.398 -                        } else {
  48.399 -                            // No spaces in the comma list for return tuples
  48.400 -                            sb.append(","); // NOI18N
  48.401 -                        }
  48.402 -                        sb.append(param);
  48.403 -                    }
  48.404 -
  48.405 -                    sb.append(" = ");
  48.406 -                }
  48.407 -            } else {
  48.408 -                assert (type == INTRODUCE_FIELD || type == INTRODUCE_CONSTANT || type == INTRODUCE_VARIABLE);
  48.409 -            }
  48.410 -
  48.411 -            int callSiteDelta = sb.length();
  48.412 -            sb.append(newName);
  48.413 -            if (type == INTRODUCE_METHOD) {
  48.414 -                sb.append('(');
  48.415 -                if (cls != null) {
  48.416 -                    sb.append("self"); // NOI18N
  48.417 -                    if (inParams.size() > 0) {
  48.418 -                        sb.append(", "); // NOI18N
  48.419 -                    }
  48.420 -                }
  48.421 -                boolean first = true;
  48.422 -                for (String param : inParams) {
  48.423 -                    if (first) {
  48.424 -                        first = false;
  48.425 -                    } else {
  48.426 -                        sb.append(", "); // NOI18N
  48.427 -                    }
  48.428 -                    sb.append(param);
  48.429 -                }
  48.430 -                sb.append(')');
  48.431 -            }
  48.432 -            String callSiteCode = sb.toString();
  48.433 -
  48.434 -
  48.435 -            // Apply changes
  48.436 -            if (extractedOffset >= callSiteOffset && extractedOffset <= callSiteOffset + callSiteReplaceLength) {
  48.437 -                if (extractedOffset > callSiteOffset) {
  48.438 -                    // We're trying to insert the extracted code segment after the call - that must mean we're
  48.439 -                    // in something like a function
  48.440 -                    edits.replace(callSiteOffset, callSiteReplaceLength, callSiteCode + extractedCode, false, 0);
  48.441 -
  48.442 -                    // Work around bug in Document.Position
  48.443 -                    //extractedPos = edits.createPosition(callSiteOffset+callSiteCode.length()+extractedSiteDelta, Bias.Forward);
  48.444 -                    //callSitePos = edits.createPosition(callSiteOffset+callSiteDelta, Bias.Forward);
  48.445 -                    finalCallSiteOffset = callSiteOffset + callSiteDelta;
  48.446 -                    finalExtractedSiteOffset = callSiteOffset + callSiteCode.length() + extractedSiteDelta;
  48.447 -                } else {
  48.448 -                    edits.replace(callSiteOffset, callSiteReplaceLength, extractedCode + callSiteCode, false, 0);
  48.449 -
  48.450 -                    // Work around bug in Document.Position
  48.451 -                    //extractedPos = edits.createPosition(callSiteOffset+extractedSiteDelta, Bias.Forward);
  48.452 -                    //callSitePos = edits.createPosition(callSiteOffset+extractedCode.length()+callSiteDelta, Bias.Forward);
  48.453 -                    finalCallSiteOffset = callSiteOffset + extractedCode.length() + callSiteDelta;
  48.454 -                    finalExtractedSiteOffset = callSiteOffset + extractedSiteDelta;
  48.455 -                }
  48.456 -            } else {
  48.457 -                edits.replace(extractedOffset, 0, extractedCode, false, 1);
  48.458 -                edits.replace(callSiteOffset, callSiteReplaceLength, callSiteCode, false, 0);
  48.459 -
  48.460 -                // There's a bug document/editlist position code - the offsets aren't updated on my
  48.461 -                // edits! For now just compute the offsets directly since we know the exact edits applied
  48.462 -                //extractedPos = edits.createPosition(extractedOffset+extractedSiteDelta, Bias.Backward);
  48.463 -                //callSitePos = edits.createPosition(callSiteOffset+callSiteDelta, Bias.Backward);
  48.464 -                if (extractedOffset < callSiteOffset) {
  48.465 -                    finalCallSiteOffset = callSiteOffset + callSiteDelta + extractedCode.length();
  48.466 -                    finalExtractedSiteOffset = extractedOffset + extractedSiteDelta;
  48.467 -                } else {
  48.468 -                    finalCallSiteOffset = callSiteOffset + callSiteDelta;
  48.469 -                    finalExtractedSiteOffset = extractedOffset + extractedSiteDelta + callSiteCode.length() - callSiteReplaceLength;
  48.470 -                }
  48.471 -            }
  48.472 -
  48.473 -            return edits;
  48.474 -        }
  48.475 -
  48.476 -        @Override
  48.477 -        public void implement() throws Exception {
  48.478 -            EditList edits = getEditList();
  48.479 -
  48.480 -            edits.apply();
  48.481 -
  48.482 -            // Refactoring isn't necessary here since local variables and block
  48.483 -            // variables are limited to the local scope, so we can accurately just
  48.484 -            // find their positions using the AST and let the user edit them synchronously.
  48.485 -            Set<OffsetRange> ranges = new HashSet<>();
  48.486 -            int length = newName.length();
  48.487 -            ranges.add(new OffsetRange(finalCallSiteOffset, finalCallSiteOffset + length));
  48.488 -            ranges.add(new OffsetRange(finalExtractedSiteOffset, finalExtractedSiteOffset + length));
  48.489 -
  48.490 -            // Initiate synchronous editing:
  48.491 -            EditRegions.getInstance().edit(context.parserResult.getSnapshot().getSource().getFileObject(), ranges, finalExtractedSiteOffset);
  48.492 -        }
  48.493 -
  48.494 -        @Override
  48.495 -        public boolean isSafe() {
  48.496 -            return true;
  48.497 -        }
  48.498 -
  48.499 -        @Override
  48.500 -        public boolean isInteractive() {
  48.501 -            return false;
  48.502 -        }
  48.503 -    }
  48.504 -
  48.505 -    /** @todo Prune search in traverse, ala AstPath.
  48.506 -     *  @todo Build up start and end AstPaths.
  48.507 -     */
  48.508 -    private static class ApplicabilityVisitor extends Visitor {
  48.509 -        private boolean applies = true;
  48.510 -        private int disabled;
  48.511 -        private int enabled;
  48.512 -        private final int start;
  48.513 -        private final int end;
  48.514 -
  48.515 -        static int getType(PythonTree root, OffsetRange astRange) {
  48.516 -            ApplicabilityVisitor visitor = new ApplicabilityVisitor(astRange);
  48.517 -            try {
  48.518 -                visitor.visit(root);
  48.519 -            } catch (Exception ex) {
  48.520 -                Exceptions.printStackTrace(ex);
  48.521 -                return 0;
  48.522 -            }
  48.523 -            return visitor.getType();
  48.524 -        }
  48.525 -
  48.526 -        ApplicabilityVisitor(OffsetRange astRange) {
  48.527 -            this.start = astRange.getStart();
  48.528 -            this.end = astRange.getEnd();
  48.529 -        }
  48.530 -
  48.531 -        private void enable(PythonTree node, int mask) {
  48.532 -            if (node.getCharStartIndex() >= start && node.getCharStopIndex() <= end) {
  48.533 -                enabled |= mask;
  48.534 -            }
  48.535 -        }
  48.536 -
  48.537 -        private void disable(PythonTree node, int mask) {
  48.538 -            if (node.getCharStartIndex() >= start && node.getCharStopIndex() <= end) {
  48.539 -                disabled |= mask;
  48.540 -            }
  48.541 -        }
  48.542 -
  48.543 -        public int getType() {
  48.544 -            return enabled & ~disabled;
  48.545 -        }
  48.546 -
  48.547 -        private void maybeBail(PythonTree node) {
  48.548 -            int nodeStart = node.getCharStartIndex();
  48.549 -            int nodeEnd = node.getCharStopIndex();
  48.550 -            if (nodeStart >= start && nodeStart < end) {
  48.551 -                applies = false;
  48.552 -                disable(node, ALL);
  48.553 -            }
  48.554 -            if (nodeEnd > start && nodeEnd < end) {
  48.555 -                applies = false;
  48.556 -                disable(node, ALL);
  48.557 -            }
  48.558 -        }
  48.559 -
  48.560 -        @Override
  48.561 -        public void traverse(PythonTree node) throws Exception {
  48.562 -            if (!applies) {
  48.563 -                return;
  48.564 -            }
  48.565 -
  48.566 -            int nodeStart = node.getCharStartIndex();
  48.567 -            int nodeStop = node.getCharStopIndex();
  48.568 -            //if (!(nodeStop < start || nodeStart > end)) {
  48.569 -            if (nodeStop >= start && nodeStart <= end) {
  48.570 -                super.traverse(node);
  48.571 -            }
  48.572 -        }
  48.573 -
  48.574 -        @Override
  48.575 -        public Object visitClassDef(ClassDef node) throws Exception {
  48.576 -            maybeBail(node);
  48.577 -            return super.visitClassDef(node);
  48.578 -        }
  48.579 -
  48.580 -        @Override
  48.581 -        public Object visitFunctionDef(FunctionDef node) throws Exception {
  48.582 -            maybeBail(node);
  48.583 -            return super.visitFunctionDef(node);
  48.584 -        }
  48.585 -
  48.586 -        @Override
  48.587 -        public Object visitImport(Import node) throws Exception {
  48.588 -            disable(node, ALL);
  48.589 -            return super.visitImport(node);
  48.590 -        }
  48.591 -
  48.592 -        @Override
  48.593 -        public Object visitImportFrom(ImportFrom node) throws Exception {
  48.594 -            disable(node, ALL);
  48.595 -            return super.visitImportFrom(node);
  48.596 -        }
  48.597 -
  48.598 -        @Override
  48.599 -        public Object visitAssign(Assign node) throws Exception {
  48.600 -            disable(node, NON_EXPRESSIONS);
  48.601 -            disable(node, NON_EXPRESSIONS);
  48.602 -            return super.visitAssign(node);
  48.603 -        }
  48.604 -
  48.605 -        @Override
  48.606 -        public Object visitCall(Call node) throws Exception {
  48.607 -            enable(node, ALL);
  48.608 -            disable(node, INTRODUCE_CONSTANT);
  48.609 -            return super.visitCall(node);
  48.610 -        }
  48.611 -
  48.612 -        @Override
  48.613 -        public Object visitAugAssign(AugAssign node) throws Exception {
  48.614 -            disable(node, NON_EXPRESSIONS);
  48.615 -            return super.visitAugAssign(node);
  48.616 -        }
  48.617 -
  48.618 -        @Override
  48.619 -        public Object visitBreak(Break node) throws Exception {
  48.620 -            disable(node, NON_EXPRESSIONS);
  48.621 -            return super.visitBreak(node);
  48.622 -        }
  48.623 -
  48.624 -        @Override
  48.625 -        public Object visitContinue(Continue node) throws Exception {
  48.626 -            disable(node, NON_EXPRESSIONS);
  48.627 -            return super.visitContinue(node);
  48.628 -        }
  48.629 -
  48.630 -        @Override
  48.631 -        public Object visitDelete(Delete node) throws Exception {
  48.632 -            disable(node, NON_EXPRESSIONS);
  48.633 -            return super.visitDelete(node);
  48.634 -        }
  48.635 -
  48.636 -        @Override
  48.637 -        public Object visitFor(For node) throws Exception {
  48.638 -            disable(node, NON_EXPRESSIONS);
  48.639 -            return super.visitFor(node);
  48.640 -        }
  48.641 -
  48.642 -        @Override
  48.643 -        public Object visitIf(If node) throws Exception {
  48.644 -            disable(node, NON_EXPRESSIONS);
  48.645 -            return super.visitIf(node);
  48.646 -        }
  48.647 -
  48.648 -        @Override
  48.649 -        public Object visitIfExp(IfExp node) throws Exception {
  48.650 -            disable(node, NON_EXPRESSIONS);
  48.651 -            return super.visitIfExp(node);
  48.652 -        }
  48.653 -
  48.654 -        @Override
  48.655 -        public Object visitPrint(Print node) throws Exception {
  48.656 -            disable(node, NON_EXPRESSIONS);
  48.657 -            return super.visitPrint(node);
  48.658 -        }
  48.659 -
  48.660 -        @Override
  48.661 -        public Object visitYield(Yield node) throws Exception {
  48.662 -            disable(node, NON_EXPRESSIONS);
  48.663 -            return super.visitYield(node);
  48.664 -        }
  48.665 -
  48.666 -        @Override
  48.667 -        public Object visitWith(With node) throws Exception {
  48.668 -            disable(node, NON_EXPRESSIONS);
  48.669 -            return super.visitWith(node);
  48.670 -        }
  48.671 -
  48.672 -        @Override
  48.673 -        public Object visitWhile(While node) throws Exception {
  48.674 -            disable(node, NON_EXPRESSIONS);
  48.675 -            return super.visitWhile(node);
  48.676 -        }
  48.677 -
  48.678 -        @Override
  48.679 -        public Object visitTryFinally(TryFinally node) throws Exception {
  48.680 -            disable(node, NON_EXPRESSIONS);
  48.681 -            return super.visitTryFinally(node);
  48.682 -        }
  48.683 -
  48.684 -        @Override
  48.685 -        public Object visitTryExcept(TryExcept node) throws Exception {
  48.686 -            disable(node, NON_EXPRESSIONS);
  48.687 -            return super.visitTryExcept(node);
  48.688 -        }
  48.689 -
  48.690 -        @Override
  48.691 -        public Object visitSuite(Suite node) throws Exception {
  48.692 -            disable(node, NON_EXPRESSIONS);
  48.693 -            return super.visitSuite(node);
  48.694 -        }
  48.695 -
  48.696 -        @Override
  48.697 -        public Object visitReturn(Return node) throws Exception {
  48.698 -//            disable(node, NON_EXPRESSIONS);
  48.699 -            // TODO - handle flow control!!
  48.700 -            disable(node, ALL);
  48.701 -            return super.visitReturn(node);
  48.702 -        }
  48.703 -
  48.704 -        @Override
  48.705 -        public Object visitModule(Module node) throws Exception {
  48.706 -            if (node.getCharStartIndex() > start && node.getCharStopIndex() < end) {
  48.707 -//                disable(node, NON_EXPRESSIONS);
  48.708 -                disable(node, ALL);
  48.709 -            }
  48.710 -            return super.visitModule(node);
  48.711 -        }
  48.712 -
  48.713 -        @Override
  48.714 -        public Object visitPass(Pass node) throws Exception {
  48.715 -            disable(node, NON_EXPRESSIONS);
  48.716 -            return super.visitPass(node);
  48.717 -        }
  48.718 -
  48.719 -        @Override
  48.720 -        public Object visitRaise(Raise node) throws Exception {
  48.721 -            disable(node, NON_EXPRESSIONS);
  48.722 -            return super.visitRaise(node);
  48.723 -        }
  48.724 -
  48.725 -        @Override
  48.726 -        public Object visitAssert(Assert node) throws Exception {
  48.727 -            disable(node, NON_EXPRESSIONS);
  48.728 -            return super.visitAssert(node);
  48.729 -        }
  48.730 -
  48.731 -        @Override
  48.732 -        public Object visitNum(Num node) throws Exception {
  48.733 -            enable(node, ALL);
  48.734 -            return super.visitNum(node);
  48.735 -        }
  48.736 -
  48.737 -        @Override
  48.738 -        public Object visitName(Name node) throws Exception {
  48.739 -            enable(node, ALL);
  48.740 -            return super.visitName(node);
  48.741 -        }
  48.742 -
  48.743 -        @Override
  48.744 -        public Object visitGlobal(Global node) throws Exception {
  48.745 -            enable(node, ALL);
  48.746 -            disable(node, INTRODUCE_CONSTANT);
  48.747 -            return super.visitGlobal(node);
  48.748 -        }
  48.749 -
  48.750 -        @Override
  48.751 -        public Object visitTuple(Tuple node) throws Exception {
  48.752 -            enable(node, ALL);
  48.753 -            return super.visitTuple(node);
  48.754 -        }
  48.755 -
  48.756 -        @Override
  48.757 -        public Object visitStr(Str node) throws Exception {
  48.758 -            enable(node, ALL);
  48.759 -            return super.visitStr(node);
  48.760 -        }
  48.761 -    }
  48.762 -}
    49.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/InputOutputFinder.java	Sat Sep 12 23:03:15 2015 -0700
    49.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.3 @@ -1,304 +0,0 @@
    49.4 -/*
    49.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    49.6 - *
    49.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    49.8 - *
    49.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   49.10 - * Other names may be trademarks of their respective owners.
   49.11 - *
   49.12 - * The contents of this file are subject to the terms of either the GNU
   49.13 - * General Public License Version 2 only ("GPL") or the Common
   49.14 - * Development and Distribution License("CDDL") (collectively, the
   49.15 - * "License"). You may not use this file except in compliance with the
   49.16 - * License. You can obtain a copy of the License at
   49.17 - * http://www.netbeans.org/cddl-gplv2.html
   49.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   49.19 - * specific language governing permissions and limitations under the
   49.20 - * License.  When distributing the software, include this License Header
   49.21 - * Notice in each file and include the License file at
   49.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   49.23 - * particular file as subject to the "Classpath" exception as provided
   49.24 - * by Oracle in the GPL Version 2 section of the License file that
   49.25 - * accompanied this code. If applicable, add the following below the
   49.26 - * License Header, with the fields enclosed by brackets [] replaced by
   49.27 - * your own identifying information:
   49.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   49.29 - * 
   49.30 - * If you wish your version of this file to be governed by only the CDDL
   49.31 - * or only the GPL Version 2, indicate your decision by adding
   49.32 - * "[Contributor] elects to include this software in this distribution
   49.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   49.34 - * single choice of license, a recipient has the option to distribute
   49.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   49.36 - * to extend the choice of license to its licensees as provided above.
   49.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   49.38 - * Version 2 license, then the option applies only if the new code is
   49.39 - * made subject to such option by the copyright holder.
   49.40 - * 
   49.41 - * Contributor(s):
   49.42 - * 
   49.43 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   49.44 - */
   49.45 -package org.netbeans.modules.python.editor.hints;
   49.46 -
   49.47 -import java.util.HashMap;
   49.48 -import java.util.HashSet;
   49.49 -import java.util.List;
   49.50 -import java.util.Map;
   49.51 -import java.util.Set;
   49.52 -import org.netbeans.modules.python.editor.PythonAstUtils;
   49.53 -import org.python.antlr.PythonTree;
   49.54 -import org.python.antlr.Visitor;
   49.55 -import org.python.antlr.ast.Assign;
   49.56 -import org.python.antlr.ast.Call;
   49.57 -import org.python.antlr.ast.FunctionDef;
   49.58 -import org.python.antlr.ast.Name;
   49.59 -import org.python.antlr.base.expr;
   49.60 -
   49.61 -/** 
   49.62 - * This visitor computes the set of input and output variables required by
   49.63 - * a code block for extract method.
   49.64 - * In particular, it tracks the local variable assignments inside the method,
   49.65 - * and checks which are used outside of the method (which would make it an
   49.66 - * output variable) and similarly, which variables are used inside the method
   49.67 - * before getting assigned (which would make it an input variable).
   49.68 - * 
   49.69 - * @author Tor Norbye
   49.70 - */
   49.71 -class InputOutputFinder extends Visitor {
   49.72 -    //private enum When { BEFORE, DURING, AFTER };
   49.73 -    private static final int WHEN_BEFORE = 0;
   49.74 -    private static final int WHEN_DURING = 1;
   49.75 -    private static final int WHEN_AFTER = 2;
   49.76 -    private final PythonTree startNode;
   49.77 -    private final PythonTree endNode;
   49.78 -    private final int startPos;
   49.79 -    private final int endPos;
   49.80 -    private final List<PythonTree> applicableBlocks;
   49.81 -    private int when = WHEN_BEFORE;
   49.82 -    private int ifs;
   49.83 -    //private PythonTree currentBlock;
   49.84 -    //private final List<PythonTree> blockStack = new ArrayList<PythonTree>(); // JDK16: Use Deque
   49.85 -    private Map<PythonTree, UsageScope> blockScopes = new HashMap<>();
   49.86 -    private UsageScope methodScope = new UsageScope(null);
   49.87 -    //private UsageScope blockScope;
   49.88 -    private PythonTree parent;
   49.89 -    private boolean isWriting;
   49.90 -
   49.91 -    /** The node ranges are inclusive */
   49.92 -    InputOutputFinder(PythonTree startNode, PythonTree endNode, List<PythonTree> applicableBlocks) {
   49.93 -        this.startNode = startNode;
   49.94 -        this.endNode = endNode;
   49.95 -        this.applicableBlocks = applicableBlocks;
   49.96 -
   49.97 -        startPos = startNode.getCharStartIndex();
   49.98 -        endPos = endNode.getCharStopIndex();
   49.99 -    }
  49.100 -
  49.101 -    public Set<String> getInputVars() {
  49.102 -        UsageScope scope = methodScope;
  49.103 -        for (UsageScope s : blockScopes.values()) {
  49.104 -            if (s.block != null && !applicableBlocks.contains(s.block)) {
  49.105 -                continue;
  49.106 -            }
  49.107 -            scope.merge(s);
  49.108 -        }
  49.109 -
  49.110 -        Set<String> inputs = new HashSet<>(scope.readDuring);
  49.111 -        // But not read before
  49.112 -        inputs.removeAll(scope.writtenBeforeReadDuring);
  49.113 -
  49.114 -        // Also need to pass in any variables I'm modifying that are read after
  49.115 -        Set<String> outputs = new HashSet<>(scope.writtenDuring);
  49.116 -        outputs.retainAll(scope.readAfter);
  49.117 -        Set<String> extraOutputs = new HashSet<>(scope.writtenBefore);
  49.118 -        extraOutputs.retainAll(outputs);
  49.119 -        // unless they are written before read
  49.120 -        extraOutputs.removeAll(scope.writtenBeforeReadDuring);
  49.121 -        inputs.addAll(extraOutputs);
  49.122 -
  49.123 -        return inputs;
  49.124 -    }
  49.125 -
  49.126 -    public Set<String> getOutputVars() {
  49.127 -        UsageScope scope = methodScope;
  49.128 -        for (UsageScope s : blockScopes.values()) {
  49.129 -            if (s.block != null && !applicableBlocks.contains(s.block)) {
  49.130 -                continue;
  49.131 -            }
  49.132 -            scope.merge(s);
  49.133 -        }
  49.134 -
  49.135 -        Set<String> outputs = new HashSet<>(scope.writtenDuring);
  49.136 -        outputs.retainAll(scope.readAfter);
  49.137 -
  49.138 -        return outputs;
  49.139 -    }
  49.140 -
  49.141 -    @Override
  49.142 -    public Object visitFunctionDef(FunctionDef node) throws Exception {
  49.143 -        // Record the parameters
  49.144 -//        assert when == WHEN_BEFORE; // Is this true when I extract a whole method? I can't do that, right?
  49.145 -        boolean x = true;
  49.146 -        assert x;
  49.147 -
  49.148 -        for (String param : PythonAstUtils.getParameters(node)) {
  49.149 -            methodScope.write(param);
  49.150 -        }
  49.151 -
  49.152 -        return super.visitFunctionDef(node);
  49.153 -    }
  49.154 -
  49.155 -    @SuppressWarnings("unchecked")
  49.156 -    @Override
  49.157 -    public Object visitAssign(Assign node) throws Exception {
  49.158 -        // Visit the right hand side of the assignment first, such
  49.159 -        // that with for example
  49.160 -        //    x = x + 1
  49.161 -        // we treat this as a read of x, before a write of x.
  49.162 -        // The Assign.traverse() implementation will do the targets first,
  49.163 -        // so we explicitly do it here in the opposite order instead...
  49.164 -
  49.165 -        if (when == WHEN_BEFORE && node.getCharStartIndex() >= startPos) {
  49.166 -            when = WHEN_DURING;
  49.167 -        }
  49.168 -        int oldWhen = when;
  49.169 -        
  49.170 -        expr nodeValue = node.getInternalValue();
  49.171 -        if (nodeValue != null) {
  49.172 -            nodeValue.accept(this);
  49.173 -        }
  49.174 -        int newWhen = when;
  49.175 -        when = oldWhen;
  49.176 -
  49.177 -        boolean oldWriting = isWriting;
  49.178 -        try {
  49.179 -            isWriting = true;
  49.180 -            List<expr> targets = node.getInternalTargets();
  49.181 -            if (targets != null) {
  49.182 -                for (expr expr : targets) {
  49.183 -                    if (expr != null) {
  49.184 -                        expr.accept(this);
  49.185 -                    }
  49.186 -                }
  49.187 -            }
  49.188 -        } finally {
  49.189 -            isWriting = oldWriting;
  49.190 -        }
  49.191 -
  49.192 -        when = newWhen;
  49.193 -
  49.194 -        return node;
  49.195 -    }
  49.196 -
  49.197 -    @Override
  49.198 -    public Object visitName(Name node) throws Exception {
  49.199 -        if (parent instanceof Call && ((Call)parent).getInternalFunc() == node) { // Name in a call is the call name, not a variable
  49.200 -            return super.visitName(node);
  49.201 -        }
  49.202 -
  49.203 -        methodScope.read(node.getInternalId());
  49.204 -
  49.205 -        return super.visitName(node);
  49.206 -    }
  49.207 -
  49.208 -    @Override
  49.209 -    public void traverse(PythonTree node) throws Exception {
  49.210 -        if (node == startNode) {
  49.211 -            when = WHEN_DURING;
  49.212 -        }
  49.213 -
  49.214 -        PythonTree oldParent = parent;
  49.215 -        parent = node;
  49.216 -        super.traverse(node);
  49.217 -        parent = oldParent;
  49.218 -
  49.219 -        if (node == endNode) {
  49.220 -            when = WHEN_AFTER;
  49.221 -        }
  49.222 -
  49.223 -    }
  49.224 -
  49.225 -    private class UsageScope {
  49.226 -        UsageScope(PythonTree block) {
  49.227 -            this.block = block;
  49.228 -        }
  49.229 -
  49.230 -        private void read(String name) {
  49.231 -            // No need to pass class references or constants in/out
  49.232 -            // TODO: Make this smarter such that what it really does
  49.233 -            // is ignore any variables that aren't defined locally - so
  49.234 -            // global variables for example aren't passed in since they
  49.235 -            // can -also- be accessed from the extracted method.
  49.236 -            if (Character.isUpperCase(name.charAt(0))) {
  49.237 -                return;
  49.238 -            }
  49.239 -
  49.240 -            if (isWriting) {
  49.241 -                // A read in the AST for example on the left hand side of an
  49.242 -                // assignment is really a write
  49.243 -                write(name);
  49.244 -                return;
  49.245 -            }
  49.246 -
  49.247 -            if (when == WHEN_DURING) {
  49.248 -                if (!writtenBeforeReadDuring.contains(name)) {
  49.249 -                    readDuring.add(name);
  49.250 -                }
  49.251 -            } else if (when == WHEN_AFTER) {
  49.252 -                // I don't want a reassignment of the variable before it's been
  49.253 -                // read to count as a usage of the result from the fragment
  49.254 -                if (!writtenAfter.contains(name)) {
  49.255 -                    readAfter.add(name);
  49.256 -                }
  49.257 -            }
  49.258 -        }
  49.259 -
  49.260 -        private void write(String name) {
  49.261 -            // No need to pass class references or constants in/out
  49.262 -            // TODO: Make this smarter such that what it really does
  49.263 -            // is ignore any variables that aren't defined locally - so
  49.264 -            // global variables for example aren't passed in since they
  49.265 -            // can -also- be accessed from the extracted method.
  49.266 -            if (Character.isUpperCase(name.charAt(0))) {
  49.267 -                return;
  49.268 -            }
  49.269 -
  49.270 -            if (when == WHEN_BEFORE) {
  49.271 -                writtenBefore.add(name);
  49.272 -            } else if (when == WHEN_DURING) {
  49.273 -                writtenDuring.add(name);
  49.274 -                if (ifs == 0 && !readDuring.contains(name)) {
  49.275 -                    writtenBeforeReadDuring.add(name);
  49.276 -                }
  49.277 -            } else if (when == WHEN_AFTER) {
  49.278 -                if (ifs == 0 && !readAfter.contains(name)) {
  49.279 -                    writtenAfter.add(name);
  49.280 -                }
  49.281 -            }
  49.282 -        }
  49.283 -
  49.284 -        private void merge(UsageScope other) {
  49.285 -            writtenBefore.addAll(other.writtenBefore);
  49.286 -            readDuring.addAll(other.readDuring);
  49.287 -            writtenDuring.addAll(other.writtenDuring);
  49.288 -            writtenBeforeReadDuring.addAll(other.writtenBeforeReadDuring);
  49.289 -            writtenAfter.addAll(other.writtenAfter);
  49.290 -            readAfter.addAll(other.readAfter);
  49.291 -        }
  49.292 -        /** Block, or null if it's the local method */
  49.293 -        private PythonTree block;
  49.294 -        /** Variables that exist in scope before the code fragment */
  49.295 -        private final Set<String> writtenBefore = new HashSet<>();
  49.296 -        /** Variables that are read during the code fragment */
  49.297 -        private final Set<String> readDuring = new HashSet<>(); // rename readBeforeWrittenDuring
  49.298 -        /** Variables that are written to during the code fragment */
  49.299 -        private final Set<String> writtenDuring = new HashSet<>();
  49.300 -        /** Variables that are written to during the code fragment */
  49.301 -        private final Set<String> writtenBeforeReadDuring = new HashSet<>();
  49.302 -        /** Variables that are written PRIOR TO A READ OF THE SAME VAR after the code fragment */
  49.303 -        private final Set<String> writtenAfter = new HashSet<>(); // rename writtenBeforeReadAfter
  49.304 -        /** Variables that are read (prior to a write) after the code fragment */
  49.305 -        private final Set<String> readAfter = new HashSet<>(); // rename readBeforeWrittenAfter
  49.306 -    }
  49.307 -}
    50.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/NameRule.java	Sat Sep 12 23:03:15 2015 -0700
    50.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.3 @@ -1,523 +0,0 @@
    50.4 -/*
    50.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    50.6 - *
    50.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    50.8 - *
    50.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   50.10 - * Other names may be trademarks of their respective owners.
   50.11 - *
   50.12 - * The contents of this file are subject to the terms of either the GNU
   50.13 - * General Public License Version 2 only ("GPL") or the Common
   50.14 - * Development and Distribution License("CDDL") (collectively, the
   50.15 - * "License"). You may not use this file except in compliance with the
   50.16 - * License. You can obtain a copy of the License at
   50.17 - * http://www.netbeans.org/cddl-gplv2.html
   50.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   50.19 - * specific language governing permissions and limitations under the
   50.20 - * License.  When distributing the software, include this License Header
   50.21 - * Notice in each file and include the License file at
   50.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   50.23 - * particular file as subject to the "Classpath" exception as provided
   50.24 - * by Oracle in the GPL Version 2 section of the License file that
   50.25 - * accompanied this code. If applicable, add the following below the
   50.26 - * License Header, with the fields enclosed by brackets [] replaced by
   50.27 - * your own identifying information:
   50.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   50.29 - *
   50.30 - * Contributor(s):
   50.31 - *
   50.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   50.33 - */
   50.34 -package org.netbeans.modules.python.editor.hints;
   50.35 -
   50.36 -import java.util.ArrayList;
   50.37 -import java.util.Collections;
   50.38 -import java.util.HashSet;
   50.39 -import java.util.List;
   50.40 -import java.util.Set;
   50.41 -import java.util.prefs.Preferences;
   50.42 -import javax.swing.JComponent;
   50.43 -import org.netbeans.editor.BaseDocument;
   50.44 -import org.netbeans.editor.Utilities;
   50.45 -import org.netbeans.modules.csl.api.EditList;
   50.46 -import org.netbeans.modules.csl.api.Hint;
   50.47 -import org.netbeans.modules.csl.api.HintFix;
   50.48 -import org.netbeans.modules.csl.api.HintSeverity;
   50.49 -import org.netbeans.modules.csl.api.OffsetRange;
   50.50 -import org.netbeans.modules.csl.api.PreviewableFix;
   50.51 -import org.netbeans.modules.csl.api.RuleContext;
   50.52 -import org.netbeans.modules.python.editor.PythonAstUtils;
   50.53 -import org.netbeans.modules.python.editor.PythonParserResult;
   50.54 -import org.netbeans.modules.python.editor.PythonUtils;
   50.55 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   50.56 -import org.openide.util.NbBundle;
   50.57 -import org.python.antlr.PythonTree;
   50.58 -import org.python.antlr.ast.ClassDef;
   50.59 -import org.python.antlr.ast.FunctionDef;
   50.60 -import org.python.antlr.ast.Module;
   50.61 -import org.python.antlr.ast.arguments;
   50.62 -
   50.63 -import static org.netbeans.modules.python.editor.hints.NameStyle.*;
   50.64 -
   50.65 -/**
   50.66 - * Check names to see if they conform to standard Python conventions.
   50.67 - * These are documented here:
   50.68 - *   http://www.python.org/dev/peps/pep-0008/
   50.69 - * 
   50.70 - * @todo Add fix to rename!
   50.71 - * @todo Implement variable name checking!
   50.72 - * 
   50.73 - * 
   50.74 - * @author Tor Norbye
   50.75 - */
   50.76 -public class NameRule extends PythonAstRule {
   50.77 -    private static final String CLASS_STYLE_NAME = "classStyle"; // NOI18N
   50.78 -    private static final String IGNORED_NAMES = "ignoredNames"; // NOI18N
   50.79 -    private static final String MODULE_STYLE_NAME = "moduleStyle"; // NOI18N
   50.80 -    private static final String FUNCTION_STYLE_NAME = "functionStyle"; // NOI18N
   50.81 -    private static final String SELF_REQUIRED_NAME = "selfRequired"; // NOI18N
   50.82 -    private static final String VARIABLE_STYLE_NAME = "variableStyle"; // NOI18N
   50.83 -    private static NameStyle moduleStyle;
   50.84 -    private static NameStyle functionStyle;
   50.85 -    private static NameStyle classStyle;
   50.86 -    private static NameStyle variableStyle;
   50.87 -    private static String ignoredNames;
   50.88 -    private static boolean selfRequired;
   50.89 -
   50.90 -    public NameRule() {
   50.91 -    }
   50.92 -
   50.93 -    @Override
   50.94 -    public boolean appliesTo(RuleContext context) {
   50.95 -        moduleStyle = null; // Ensure lazy init
   50.96 -
   50.97 -        return true;
   50.98 -    }
   50.99 -
  50.100 -    private static void initializeFromPrefs(PythonRuleContext context, NameRule rule) {
  50.101 -        Preferences pref = context.manager.getPreferences(rule);
  50.102 -        moduleStyle = getModuleNameStyle(pref);
  50.103 -        classStyle = getClassNameStyle(pref);
  50.104 -        functionStyle = getFunctionNameStyle(pref);
  50.105 -        variableStyle = getVariableNameStyle(pref);
  50.106 -        ignoredNames = getIgnoredNames(pref);
  50.107 -        selfRequired = isSelfRequired(pref);
  50.108 -    }
  50.109 -
  50.110 -    @Override
  50.111 -    public Set<Class> getKinds() {
  50.112 -        Set<Class> classes = new HashSet<>();
  50.113 -        classes.add(Module.class);
  50.114 -        classes.add(FunctionDef.class);
  50.115 -        classes.add(ClassDef.class);
  50.116 -
  50.117 -        return classes;
  50.118 -    }
  50.119 -
  50.120 -    @Override
  50.121 -    public void run(PythonRuleContext context, List<Hint> result) {
  50.122 -        if (moduleStyle == null) {
  50.123 -            initializeFromPrefs(context, this);
  50.124 -        }
  50.125 -
  50.126 -        // TODO - check module name!!
  50.127 -
  50.128 -        PythonTree node = context.node;
  50.129 -        if (node instanceof Module) {
  50.130 -            if (moduleStyle != NO_PREFERENCE) {
  50.131 -                String moduleName = PythonUtils.getModuleName(context.parserResult.getSnapshot().getSource().getFileObject());
  50.132 -                if (!moduleStyle.complies(moduleName) && !moduleStyle.complies(moduleName.substring(moduleName.lastIndexOf('.') + 1))) {
  50.133 -                    String typeKey = "Module"; // NOI18N
  50.134 -                    String message = NbBundle.getMessage(NameRule.class, "WrongStyle", moduleName,
  50.135 -                            NbBundle.getMessage(NameRule.class, typeKey),
  50.136 -                            moduleStyle.getDisplayName());
  50.137 -                    List<HintFix> hintFixes = getNameStyleFixes(moduleName, context, moduleStyle, MODULE_STYLE_NAME, typeKey);
  50.138 -                    addError(moduleName, context, message, node, result, hintFixes);
  50.139 -                }
  50.140 -            }
  50.141 -        } else if (node instanceof FunctionDef) {
  50.142 -            FunctionDef def = (FunctionDef)node;
  50.143 -            if (functionStyle != NO_PREFERENCE) {
  50.144 -                if (!functionStyle.complies(def.getInternalName())) {
  50.145 -                    String typeKey = "Function"; // NOI18N
  50.146 -                    String message = NbBundle.getMessage(NameRule.class, "WrongStyle", def.getInternalName(),
  50.147 -                            NbBundle.getMessage(NameRule.class, typeKey),
  50.148 -                            functionStyle.getDisplayName());
  50.149 -                    List<HintFix> hintFixes = getNameStyleFixes(def.getInternalName(), context, functionStyle, FUNCTION_STYLE_NAME, typeKey);
  50.150 -                    addError(def.getInternalName(), context, message, def, result, hintFixes);
  50.151 -                }
  50.152 -            }
  50.153 -
  50.154 -            // Functions should have a first argument of name "self"
  50.155 -            if (selfRequired && !PythonAstUtils.isStaticMethod(def)) {
  50.156 -                arguments args = def.getInternalArgs();
  50.157 -                if (args.getInternalArgs().size() > 0) {
  50.158 -                    String name = PythonAstUtils.getName(args.getInternalArgs().get(0));
  50.159 -                    if (!("self".equals(name) || "cls".equals(name))) { // NOI18N
  50.160 -                        // Make sure it's a class; other methods don't have to
  50.161 -                        if (PythonAstUtils.isClassMethod(context.path, def)) {
  50.162 -                            String message = NbBundle.getMessage(NameRule.class,
  50.163 -                                    // TODO - determine if it should be cls or def
  50.164 -                                    "NameRuleWrongArg", // NOI18N
  50.165 -                                    name);
  50.166 -                            List<HintFix> fixList = new ArrayList<>(2);
  50.167 -                            fixList.add(new SelfParamFix(context, true, def, null));
  50.168 -                            List<String> parameters = PythonAstUtils.getParameters(def);
  50.169 -                            if (parameters.size() > 0) {
  50.170 -                                fixList.add(new SelfParamFix(context, false, def, parameters.get(0)));
  50.171 -                            }
  50.172 -                            addError(null, context, message, args, result, fixList);
  50.173 -                        }
  50.174 -                    }
  50.175 -                } else if (PythonAstUtils.isClassMethod(context.path, def)) {
  50.176 -                    String message = NbBundle.getMessage(NameRule.class,
  50.177 -                            // TODO - determine if it should be cls or def
  50.178 -                            "NameRuleWrongNoArg"); // NOI18N
  50.179 -                    List<HintFix> fixList = Collections.<HintFix>singletonList(new SelfParamFix(context, true, def, null));
  50.180 -                    addError(null, context, message, args, result, fixList);
  50.181 -                }
  50.182 -            }
  50.183 -        } else if (node instanceof ClassDef) {
  50.184 -            if (functionStyle != NO_PREFERENCE) {
  50.185 -                ClassDef def = (ClassDef)node;
  50.186 -                if (!classStyle.complies(def.getInternalName())) {
  50.187 -                    String typeKey = "Class"; // NOI18N
  50.188 -                    String message = NbBundle.getMessage(NameRule.class, "WrongStyle", def.getInternalName(),
  50.189 -                            NbBundle.getMessage(NameRule.class, typeKey),
  50.190 -                            classStyle.getDisplayName());
  50.191 -                    List<HintFix> hintFixes = getNameStyleFixes(def.getInternalName(), context, classStyle, CLASS_STYLE_NAME, typeKey);
  50.192 -                    addError(def.getInternalName(), context, message, def, result, hintFixes);
  50.193 -                }
  50.194 -            }
  50.195 -        }
  50.196 -    }
  50.197 -
  50.198 -    private List<HintFix> getNameStyleFixes(String name, PythonRuleContext context, NameStyle currentStyle, String key, String type) {
  50.199 -        List<HintFix> fixes = new ArrayList<>(5);
  50.200 -
  50.201 -        fixes.add(new IgnoreWordFix(name, this, context));
  50.202 -
  50.203 -        for (NameStyle style : NameStyle.values()) {
  50.204 -            if (style == currentStyle || style == NO_PREFERENCE) {
  50.205 -                continue;
  50.206 -            }
  50.207 -
  50.208 -            if (style.complies(name)) {
  50.209 -                ChangeStyleFix cs = new ChangeStyleFix(this, context, style, key, type);
  50.210 -                fixes.add(cs);
  50.211 -            }
  50.212 -        }
  50.213 -
  50.214 -        // No preference always last
  50.215 -        fixes.add(new ChangeStyleFix(this, context, NO_PREFERENCE, key, type));
  50.216 -
  50.217 -        return fixes;
  50.218 -    }
  50.219 -
  50.220 -    private void addError(String name, PythonRuleContext context, String message, PythonTree node, List<Hint> result, List<HintFix> fixList) {
  50.221 -        if (name != null && ignoredNames.length() > 0) {
  50.222 -            for (String ignoredName : ignoredNames.split(",")) { // NOI18N
  50.223 -                ignoredName = ignoredName.trim();
  50.224 -                if (name.equals(ignoredName)) {
  50.225 -                    return;
  50.226 -                }
  50.227 -            }
  50.228 -        }
  50.229 -        
  50.230 -        PythonParserResult info = (PythonParserResult)context.parserResult;
  50.231 -        OffsetRange range;
  50.232 -        if (node instanceof Module) {
  50.233 -            range = new OffsetRange(0, 0);
  50.234 -        } else {
  50.235 -            
  50.236 -            range = PythonAstUtils.getNameRange(info, node);
  50.237 -        }
  50.238 -        range = PythonLexerUtils.getLexerOffsets(info, range);
  50.239 -        if (range != OffsetRange.NONE) {
  50.240 -            if (fixList == null) {
  50.241 -                fixList = Collections.emptyList();
  50.242 -            }
  50.243 -            Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 1500);
  50.244 -            result.add(desc);
  50.245 -        }
  50.246 -    }
  50.247 -
  50.248 -    @Override
  50.249 -    public String getId() {
  50.250 -        return "NameRule"; // NOI18N
  50.251 -    }
  50.252 -
  50.253 -    @Override
  50.254 -    public String getDisplayName() {
  50.255 -        return NbBundle.getMessage(NameRule.class, "NameRule");
  50.256 -    }
  50.257 -
  50.258 -    @Override
  50.259 -    public String getDescription() {
  50.260 -        return NbBundle.getMessage(NameRule.class, "NameRuleDesc");
  50.261 -    }
  50.262 -
  50.263 -    @Override
  50.264 -    public boolean getDefaultEnabled() {
  50.265 -        return true;
  50.266 -    }
  50.267 -
  50.268 -    @Override
  50.269 -    public boolean showInTasklist() {
  50.270 -        return true;
  50.271 -    }
  50.272 -
  50.273 -    @Override
  50.274 -    public HintSeverity getDefaultSeverity() {
  50.275 -        return HintSeverity.WARNING;
  50.276 -    }
  50.277 -
  50.278 -    @Override
  50.279 -    public JComponent getCustomizer(Preferences node) {
  50.280 -        moduleStyle = null; // Ensure lazy init after this
  50.281 -        return new NameRulePrefs(this, node);
  50.282 -    }
  50.283 -
  50.284 -    static NameStyle getNameStyle(String key, NameStyle deflt, Preferences pref) {
  50.285 -        String value = pref.get(key, deflt.name());
  50.286 -
  50.287 -        return NameStyle.valueOf(value);
  50.288 -    }
  50.289 -
  50.290 -    static NameStyle getModuleNameStyle(Preferences pref) {
  50.291 -        return getNameStyle(MODULE_STYLE_NAME, NameStyle.NO_PREFERENCE, pref);
  50.292 -    }
  50.293 -
  50.294 -    static NameStyle getClassNameStyle(Preferences pref) {
  50.295 -        return getNameStyle(CLASS_STYLE_NAME, NameStyle.CAPITALIZED_WORDS, pref);
  50.296 -    }
  50.297 -
  50.298 -    static NameStyle getVariableNameStyle(Preferences pref) {
  50.299 -        return getNameStyle(VARIABLE_STYLE_NAME, NameStyle.LOWERCASE_WITH_UNDERSCORES, pref);
  50.300 -    }
  50.301 -
  50.302 -    static NameStyle getFunctionNameStyle(Preferences pref) {
  50.303 -        return getNameStyle(FUNCTION_STYLE_NAME, NameStyle.LOWERCASE_WITH_UNDERSCORES, pref);
  50.304 -    }
  50.305 -
  50.306 -    static boolean isSelfRequired(Preferences pref) {
  50.307 -        return pref.getBoolean(SELF_REQUIRED_NAME, true);
  50.308 -    }
  50.309 -
  50.310 -    static String getIgnoredNames(Preferences pref) {
  50.311 -        return pref.get(IGNORED_NAMES, "");
  50.312 -    }
  50.313 -
  50.314 -    void setModuleNameStyle(Preferences pref, NameStyle style) {
  50.315 -        pref.put(MODULE_STYLE_NAME, style.name());
  50.316 -    }
  50.317 -
  50.318 -    void setClassNameStyle(Preferences pref, NameStyle style) {
  50.319 -        pref.put(CLASS_STYLE_NAME, style.name());
  50.320 -    }
  50.321 -
  50.322 -    void setFunctionNameStyle(Preferences pref, NameStyle style) {
  50.323 -        pref.put(FUNCTION_STYLE_NAME, style.name());
  50.324 -    }
  50.325 -
  50.326 -    void setVariableNameStyle(Preferences pref, NameStyle style) {
  50.327 -        pref.put(VARIABLE_STYLE_NAME, style.name());
  50.328 -    }
  50.329 -
  50.330 -    void setIgnoredNames(Preferences pref, String ignoredNames) {
  50.331 -        pref.put(IGNORED_NAMES, ignoredNames);
  50.332 -    }
  50.333 -
  50.334 -    void setSelfRequired(Preferences pref, boolean requireSelf) {
  50.335 -        pref.putBoolean(SELF_REQUIRED_NAME, requireSelf);
  50.336 -    }
  50.337 -
  50.338 -    private static class IgnoreWordFix implements HintFix {
  50.339 -        private String name;
  50.340 -        private NameRule rule;
  50.341 -        private PythonRuleContext context;
  50.342 -
  50.343 -        public IgnoreWordFix(String name, NameRule rule, PythonRuleContext context) {
  50.344 -            this.name = name;
  50.345 -            this.rule = rule;
  50.346 -            this.context = context;
  50.347 -        }
  50.348 -
  50.349 -        @Override
  50.350 -        public String getDescription() {
  50.351 -            return NbBundle.getMessage(NameRule.class, "IgnoreWord", name);
  50.352 -        }
  50.353 -
  50.354 -        @Override
  50.355 -        public void implement() throws Exception {
  50.356 -            Preferences pref = context.manager.getPreferences(rule);
  50.357 -            String ignored = getIgnoredNames(pref);
  50.358 -            if (ignored.length() > 0) {
  50.359 -                ignored = ignored + "," + name; // NOI18N
  50.360 -            } else {
  50.361 -                ignored = name;
  50.362 -            }
  50.363 -            pref.put(IGNORED_NAMES, ignored);
  50.364 -
  50.365 -            context.manager.refreshHints(context);
  50.366 -        }
  50.367 -
  50.368 -        @Override
  50.369 -        public boolean isSafe() {
  50.370 -            return true;
  50.371 -        }
  50.372 -
  50.373 -        @Override
  50.374 -        public boolean isInteractive() {
  50.375 -            return true;
  50.376 -        }
  50.377 -    }
  50.378 -
  50.379 -    private static class ChangeStyleFix implements HintFix {
  50.380 -        private NameRule rule;
  50.381 -        private PythonRuleContext context;
  50.382 -        private NameStyle style;
  50.383 -        private String key;
  50.384 -        private String typeKey;
  50.385 -
  50.386 -        public ChangeStyleFix(NameRule rule, PythonRuleContext context, NameStyle style, String key, String type) {
  50.387 -            this.rule = rule;
  50.388 -            this.context = context;
  50.389 -            this.style = style;
  50.390 -            this.key = key;
  50.391 -            this.typeKey = type;
  50.392 -        }
  50.393 -
  50.394 -        @Override
  50.395 -        public String getDescription() {
  50.396 -            if (style == NO_PREFERENCE) {
  50.397 -                return NbBundle.getMessage(NameRule.class, "ChangeNoStyle", NbBundle.getMessage(NameRule.class, typeKey));
  50.398 -            } else {
  50.399 -                return NbBundle.getMessage(NameRule.class, "ChangeStyle", NbBundle.getMessage(NameRule.class, typeKey), style.getDisplayName());
  50.400 -            }
  50.401 -        }
  50.402 -
  50.403 -        @Override
  50.404 -        public void implement() throws Exception {
  50.405 -            Preferences pref = context.manager.getPreferences(rule);
  50.406 -            pref.put(key, style.name());
  50.407 -
  50.408 -            context.manager.refreshHints(context);
  50.409 -        }
  50.410 -
  50.411 -        @Override
  50.412 -        public boolean isSafe() {
  50.413 -            return true;
  50.414 -        }
  50.415 -
  50.416 -        @Override
  50.417 -        public boolean isInteractive() {
  50.418 -            return true;
  50.419 -        }
  50.420 -    }
  50.421 -
  50.422 -    /**
  50.423 -     * Fix to insert self argument or rename first argument to self
  50.424 -     */
  50.425 -    private static class SelfParamFix implements PreviewableFix {
  50.426 -        private final PythonRuleContext context;
  50.427 -        private final FunctionDef func;
  50.428 -        private final boolean insert;
  50.429 -        private final String first;
  50.430 -
  50.431 -        private SelfParamFix(PythonRuleContext context, boolean insert, FunctionDef func, String first) {
  50.432 -            this.context = context;
  50.433 -            this.insert = insert;
  50.434 -            this.func = func;
  50.435 -            this.first = first;
  50.436 -
  50.437 -            assert insert || first != null;
  50.438 -        }
  50.439 -
  50.440 -        @Override
  50.441 -        public String getDescription() {
  50.442 -            if (insert) {
  50.443 -                return NbBundle.getMessage(CreateDocString.class, "InsertSelf");
  50.444 -            } else {
  50.445 -                return NbBundle.getMessage(CreateDocString.class, "RenameSelf", first);
  50.446 -            }
  50.447 -        }
  50.448 -
  50.449 -        @Override
  50.450 -        public boolean canPreview() {
  50.451 -            return true;
  50.452 -        }
  50.453 -
  50.454 -        @Override
  50.455 -        public EditList getEditList() throws Exception {
  50.456 -            return getEditList(true);
  50.457 -        }
  50.458 -
  50.459 -        private EditList getEditList(boolean previewOnly) throws Exception {
  50.460 -            BaseDocument doc = context.doc;
  50.461 -            EditList edits = new EditList(doc);
  50.462 -
  50.463 -            OffsetRange astRange = PythonAstUtils.getNameRange((PythonParserResult) context.parserResult, func);
  50.464 -            OffsetRange lexRange = PythonLexerUtils.getLexerOffsets((PythonParserResult) context.parserResult, astRange);
  50.465 -            if (lexRange == OffsetRange.NONE) {
  50.466 -                return edits;
  50.467 -            }
  50.468 -            int paramStart = lexRange.getEnd();
  50.469 -            if (insert) {
  50.470 -                String missing;
  50.471 -                int lineEnd = Utilities.getRowEnd(doc, paramStart);
  50.472 -                int offset = paramStart;
  50.473 -                if (lineEnd > paramStart) {
  50.474 -                    String line = doc.getText(paramStart, lineEnd - paramStart);
  50.475 -                    int paren = line.indexOf('(');
  50.476 -                    int colon = line.indexOf(':');
  50.477 -                    if (paren != -1) {
  50.478 -                        offset = paramStart + paren + 1;
  50.479 -                        missing = "self"; // NOI18N
  50.480 -                        List<String> parameters = PythonAstUtils.getParameters(func);
  50.481 -                        if (parameters.size() > 0) {
  50.482 -                            missing = "self, "; // NOI18N
  50.483 -                        } else {
  50.484 -                            missing = "self"; // NOI18N
  50.485 -                        }
  50.486 -                    } else if (colon != -1) {
  50.487 -                        offset = paramStart + colon;
  50.488 -                        missing = "(self)"; // NOI18N
  50.489 -                    } else {
  50.490 -                        return edits;
  50.491 -                    }
  50.492 -                } else {
  50.493 -                    missing = "(self)"; // NOI18N
  50.494 -                }
  50.495 -                edits.replace(offset, 0, missing, false, 0);
  50.496 -            } else {
  50.497 -                String text = doc.getText(paramStart, doc.getLength() - paramStart);
  50.498 -                int offset = text.indexOf(first);
  50.499 -                if (offset != -1) {
  50.500 -                    offset += paramStart;
  50.501 -                    edits.replace(offset, first.length(), "self", false, 0); // NOI18N
  50.502 -                }
  50.503 -            }
  50.504 -
  50.505 -
  50.506 -            return edits;
  50.507 -        }
  50.508 -
  50.509 -        @Override
  50.510 -        public void implement() throws Exception {
  50.511 -            EditList edits = getEditList(true);
  50.512 -
  50.513 -            edits.apply();
  50.514 -        }
  50.515 -
  50.516 -        @Override
  50.517 -        public boolean isSafe() {
  50.518 -            return true;
  50.519 -        }
  50.520 -
  50.521 -        @Override
  50.522 -        public boolean isInteractive() {
  50.523 -            return false;
  50.524 -        }
  50.525 -    }
  50.526 -}
    51.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/NameRulePrefs.form	Sat Sep 12 23:03:15 2015 -0700
    51.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.3 @@ -1,182 +0,0 @@
    51.4 -<?xml version="1.0" encoding="UTF-8" ?>
    51.5 -
    51.6 -<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    51.7 -  <AuxValues>
    51.8 -    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
    51.9 -    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   51.10 -    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   51.11 -    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
   51.12 -    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   51.13 -    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
   51.14 -    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
   51.15 -    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   51.16 -    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   51.17 -  </AuxValues>
   51.18 -
   51.19 -  <Layout>
   51.20 -    <DimensionLayout dim="0">
   51.21 -      <Group type="103" groupAlignment="0" attributes="0">
   51.22 -          <Group type="102" attributes="0">
   51.23 -              <Group type="103" groupAlignment="0" attributes="0">
   51.24 -                  <Group type="102" alignment="0" attributes="0">
   51.25 -                      <Group type="103" groupAlignment="0" attributes="0">
   51.26 -                          <Component id="moduleLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   51.27 -                          <Component id="classLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   51.28 -                          <Component id="functionLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   51.29 -                          <Component id="variableLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   51.30 -                      </Group>
   51.31 -                      <EmptySpace max="-2" attributes="0"/>
   51.32 -                      <Group type="103" groupAlignment="1" max="-2" attributes="0">
   51.33 -                          <Component id="variableCombo" alignment="0" max="32767" attributes="1"/>
   51.34 -                          <Component id="classCombo" alignment="0" max="32767" attributes="1"/>
   51.35 -                          <Component id="moduleCombo" alignment="0" pref="234" max="32767" attributes="1"/>
   51.36 -                          <Component id="functionCombo" alignment="1" max="32767" attributes="1"/>
   51.37 -                      </Group>
   51.38 -                  </Group>
   51.39 -                  <Component id="parameterLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   51.40 -                  <Component id="selfCb" alignment="0" min="-2" max="-2" attributes="0"/>
   51.41 -                  <Group type="102" alignment="0" attributes="0">
   51.42 -                      <Component id="ignoreLabel" min="-2" max="-2" attributes="0"/>
   51.43 -                      <EmptySpace max="-2" attributes="0"/>
   51.44 -                      <Component id="ignoredText" max="32767" attributes="0"/>
   51.45 -                  </Group>
   51.46 -              </Group>
   51.47 -              <EmptySpace max="-2" attributes="0"/>
   51.48 -          </Group>
   51.49 -      </Group>
   51.50 -    </DimensionLayout>
   51.51 -    <DimensionLayout dim="1">
   51.52 -      <Group type="103" groupAlignment="0" attributes="0">
   51.53 -          <Group type="102" alignment="0" attributes="0">
   51.54 -              <Group type="103" groupAlignment="3" attributes="0">
   51.55 -                  <Component id="moduleLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   51.56 -                  <Component id="moduleCombo" alignment="3" min="-2" max="-2" attributes="0"/>
   51.57 -              </Group>
   51.58 -              <EmptySpace max="-2" attributes="0"/>
   51.59 -              <Group type="103" groupAlignment="3" attributes="0">
   51.60 -                  <Component id="classLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   51.61 -                  <Component id="classCombo" alignment="3" min="-2" max="-2" attributes="0"/>
   51.62 -              </Group>
   51.63 -              <EmptySpace max="-2" attributes="0"/>
   51.64 -              <Group type="103" groupAlignment="3" attributes="0">
   51.65 -                  <Component id="functionLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   51.66 -                  <Component id="functionCombo" alignment="3" min="-2" max="-2" attributes="0"/>
   51.67 -              </Group>
   51.68 -              <EmptySpace max="-2" attributes="0"/>
   51.69 -              <Group type="103" groupAlignment="3" attributes="0">
   51.70 -                  <Component id="variableLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   51.71 -                  <Component id="variableCombo" alignment="3" min="-2" max="-2" attributes="0"/>
   51.72 -              </Group>
   51.73 -              <EmptySpace type="separate" max="-2" attributes="0"/>
   51.74 -              <Component id="parameterLabel" min="-2" max="-2" attributes="0"/>
   51.75 -              <EmptySpace max="-2" attributes="0"/>
   51.76 -              <Component id="selfCb" min="-2" max="-2" attributes="0"/>
   51.77 -              <EmptySpace type="separate" max="-2" attributes="0"/>
   51.78 -              <Group type="103" groupAlignment="3" attributes="0">
   51.79 -                  <Component id="ignoreLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   51.80 -                  <Component id="ignoredText" alignment="3" min="-2" max="-2" attributes="0"/>
   51.81 -              </Group>
   51.82 -              <EmptySpace max="32767" attributes="0"/>
   51.83 -          </Group>
   51.84 -      </Group>
   51.85 -    </DimensionLayout>
   51.86 -  </Layout>
   51.87 -  <SubComponents>
   51.88 -    <Component class="javax.swing.JLabel" name="classLabel">
   51.89 -      <Properties>
   51.90 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   51.91 -          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="NameRulePrefs.classLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   51.92 -        </Property>
   51.93 -      </Properties>
   51.94 -    </Component>
   51.95 -    <Component class="javax.swing.JLabel" name="functionLabel">
   51.96 -      <Properties>
   51.97 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   51.98 -          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="NameRulePrefs.functionLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   51.99 -        </Property>
  51.100 -      </Properties>
  51.101 -    </Component>
  51.102 -    <Component class="javax.swing.JLabel" name="moduleLabel">
  51.103 -      <Properties>
  51.104 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  51.105 -          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="NameRulePrefs.moduleLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  51.106 -        </Property>
  51.107 -      </Properties>
  51.108 -    </Component>
  51.109 -    <Component class="javax.swing.JLabel" name="parameterLabel">
  51.110 -      <Properties>
  51.111 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  51.112 -          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="NameRulePrefs.parameterLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  51.113 -        </Property>
  51.114 -      </Properties>
  51.115 -    </Component>
  51.116 -    <Component class="javax.swing.JCheckBox" name="selfCb">
  51.117 -      <Properties>
  51.118 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  51.119 -          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="NameRulePrefs.selfCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  51.120 -        </Property>
  51.121 -      </Properties>
  51.122 -      <Events>
  51.123 -        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
  51.124 -      </Events>
  51.125 -    </Component>
  51.126 -    <Component class="javax.swing.JComboBox" name="moduleCombo">
  51.127 -      <Properties>
  51.128 -        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
  51.129 -          <Connection code="getNameStyleModel()" type="code"/>
  51.130 -        </Property>
  51.131 -      </Properties>
  51.132 -      <Events>
  51.133 -        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
  51.134 -      </Events>
  51.135 -    </Component>
  51.136 -    <Component class="javax.swing.JComboBox" name="classCombo">
  51.137 -      <Properties>
  51.138 -        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
  51.139 -          <Connection code="getNameStyleModel()" type="code"/>
  51.140 -        </Property>
  51.141 -      </Properties>
  51.142 -      <Events>
  51.143 -        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
  51.144 -      </Events>
  51.145 -    </Component>
  51.146 -    <Component class="javax.swing.JComboBox" name="functionCombo">
  51.147 -      <Properties>
  51.148 -        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
  51.149 -          <Connection code="getNameStyleModel()" type="code"/>
  51.150 -        </Property>
  51.151 -      </Properties>
  51.152 -      <Events>
  51.153 -        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
  51.154 -      </Events>
  51.155 -    </Component>
  51.156 -    <Component class="javax.swing.JLabel" name="variableLabel">
  51.157 -      <Properties>
  51.158 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  51.159 -          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="NameRulePrefs.variableLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  51.160 -        </Property>
  51.161 -        <Property name="enabled" type="boolean" value="false"/>
  51.162 -      </Properties>
  51.163 -    </Component>
  51.164 -    <Component class="javax.swing.JComboBox" name="variableCombo">
  51.165 -      <Properties>
  51.166 -        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
  51.167 -          <Connection code="getNameStyleModel()" type="code"/>
  51.168 -        </Property>
  51.169 -        <Property name="enabled" type="boolean" value="false"/>
  51.170 -      </Properties>
  51.171 -      <Events>
  51.172 -        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
  51.173 -      </Events>
  51.174 -    </Component>
  51.175 -    <Component class="javax.swing.JLabel" name="ignoreLabel">
  51.176 -      <Properties>
  51.177 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  51.178 -          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="NameRulePrefs.ignoreLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  51.179 -        </Property>
  51.180 -      </Properties>
  51.181 -    </Component>
  51.182 -    <Component class="javax.swing.JTextField" name="ignoredText">
  51.183 -    </Component>
  51.184 -  </SubComponents>
  51.185 -</Form>
    52.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/NameRulePrefs.java	Sat Sep 12 23:03:15 2015 -0700
    52.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.3 @@ -1,291 +0,0 @@
    52.4 -/*
    52.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    52.6 - *
    52.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    52.8 - *
    52.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   52.10 - * Other names may be trademarks of their respective owners.
   52.11 - *
   52.12 - * The contents of this file are subject to the terms of either the GNU
   52.13 - * General Public License Version 2 only ("GPL") or the Common
   52.14 - * Development and Distribution License("CDDL") (collectively, the
   52.15 - * "License"). You may not use this file except in compliance with the
   52.16 - * License. You can obtain a copy of the License at
   52.17 - * http://www.netbeans.org/cddl-gplv2.html
   52.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   52.19 - * specific language governing permissions and limitations under the
   52.20 - * License.  When distributing the software, include this License Header
   52.21 - * Notice in each file and include the License file at
   52.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   52.23 - * particular file as subject to the "Classpath" exception as provided
   52.24 - * by Oracle in the GPL Version 2 section of the License file that
   52.25 - * accompanied this code. If applicable, add the following below the
   52.26 - * License Header, with the fields enclosed by brackets [] replaced by
   52.27 - * your own identifying information:
   52.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   52.29 - *
   52.30 - * If you wish your version of this file to be governed by only the CDDL
   52.31 - * or only the GPL Version 2, indicate your decision by adding
   52.32 - * "[Contributor] elects to include this software in this distribution
   52.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   52.34 - * single choice of license, a recipient has the option to distribute
   52.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   52.36 - * to extend the choice of license to its licensees as provided above.
   52.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   52.38 - * Version 2 license, then the option applies only if the new code is
   52.39 - * made subject to such option by the copyright holder.
   52.40 - *
   52.41 - * Contributor(s):
   52.42 - *
   52.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   52.44 - */
   52.45 -package org.netbeans.modules.python.editor.hints;
   52.46 -
   52.47 -import java.awt.Component;
   52.48 -import java.util.prefs.Preferences;
   52.49 -import javax.swing.ComboBoxModel;
   52.50 -import javax.swing.DefaultComboBoxModel;
   52.51 -import javax.swing.JLabel;
   52.52 -import javax.swing.JList;
   52.53 -import javax.swing.ListCellRenderer;
   52.54 -
   52.55 -/**
   52.56 - *
   52.57 - * @author Tor Norbye
   52.58 - */
   52.59 -public class NameRulePrefs extends javax.swing.JPanel {
   52.60 -    private NameRule rule;
   52.61 -    private Preferences prefs;
   52.62 -
   52.63 -    /** Creates new form NameRulePrefs */
   52.64 -    public NameRulePrefs(NameRule rule, Preferences prefs) {
   52.65 -        this.rule = rule;
   52.66 -        this.prefs = prefs;
   52.67 -
   52.68 -        initComponents();
   52.69 -
   52.70 -        ListCellRenderer renderer = new NameStyleRenderer();
   52.71 -        moduleCombo.setRenderer(renderer);
   52.72 -        functionCombo.setRenderer(renderer);
   52.73 -        classCombo.setRenderer(renderer);
   52.74 -        variableCombo.setRenderer(renderer);
   52.75 -
   52.76 -        moduleCombo.setSelectedItem(NameRule.getModuleNameStyle(prefs));
   52.77 -        functionCombo.setSelectedItem(NameRule.getFunctionNameStyle(prefs));
   52.78 -        classCombo.setSelectedItem(NameRule.getClassNameStyle(prefs));
   52.79 -        variableCombo.setSelectedItem(NameRule.getVariableNameStyle(prefs));
   52.80 -
   52.81 -        selfCb.setSelected(NameRule.isSelfRequired(prefs));
   52.82 -        ignoredText.setText(NameRule.getIgnoredNames(prefs));
   52.83 -    }
   52.84 -
   52.85 -    private ComboBoxModel getNameStyleModel() {
   52.86 -        return new DefaultComboBoxModel(NameStyle.values());
   52.87 -    }
   52.88 -
   52.89 -    private static class NameStyleRenderer extends JLabel implements ListCellRenderer/*, UIResource*/ {
   52.90 -        public NameStyleRenderer() {
   52.91 -            setOpaque(true);
   52.92 -        }
   52.93 -
   52.94 -        @Override
   52.95 -        public Component getListCellRendererComponent(JList list, Object value,
   52.96 -                int index, boolean isSelected, boolean cellHasFocus) {
   52.97 -            // #93658: GTK needs name to render cell renderer "natively"
   52.98 -            setName("ComboBox.listRenderer"); // NOI18N
   52.99 -
  52.100 -            if (isSelected) {
  52.101 -                setBackground(list.getSelectionBackground());
  52.102 -                setForeground(list.getSelectionForeground());
  52.103 -            } else {
  52.104 -                setBackground(list.getBackground());
  52.105 -                setForeground(list.getForeground());
  52.106 -            }
  52.107 -
  52.108 -            if (value instanceof NameStyle) {
  52.109 -                setText(((NameStyle)value).getDisplayName());
  52.110 -            }
  52.111 -
  52.112 -            return this;
  52.113 -        }
  52.114 -
  52.115 -        // #93658: GTK needs name to render cell renderer "natively"
  52.116 -        public 
  52.117 -        @Override
  52.118 -        String getName() {
  52.119 -            String name = super.getName();
  52.120 -            return name == null ? "ComboBox.renderer" : name;  // NOI18N
  52.121 -        }
  52.122 -    }
  52.123 -
  52.124 -    /** This method is called from within the constructor to
  52.125 -     * initialize the form.
  52.126 -     * WARNING: Do NOT modify this code. The content of this method is
  52.127 -     * always regenerated by the Form Editor.
  52.128 -     */
  52.129 -    @SuppressWarnings("unchecked")
  52.130 -    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  52.131 -    private void initComponents() {
  52.132 -
  52.133 -        classLabel = new javax.swing.JLabel();
  52.134 -        functionLabel = new javax.swing.JLabel();
  52.135 -        moduleLabel = new javax.swing.JLabel();
  52.136 -        parameterLabel = new javax.swing.JLabel();
  52.137 -        selfCb = new javax.swing.JCheckBox();
  52.138 -        moduleCombo = new javax.swing.JComboBox();
  52.139 -        classCombo = new javax.swing.JComboBox();
  52.140 -        functionCombo = new javax.swing.JComboBox();
  52.141 -        variableLabel = new javax.swing.JLabel();
  52.142 -        variableCombo = new javax.swing.JComboBox();
  52.143 -        ignoreLabel = new javax.swing.JLabel();
  52.144 -        ignoredText = new javax.swing.JTextField();
  52.145 -
  52.146 -        classLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.classLabel.text")); // NOI18N
  52.147 -
  52.148 -        functionLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.functionLabel.text")); // NOI18N
  52.149 -
  52.150 -        moduleLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.moduleLabel.text")); // NOI18N
  52.151 -
  52.152 -        parameterLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.parameterLabel.text")); // NOI18N
  52.153 -
  52.154 -        selfCb.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.selfCb.text")); // NOI18N
  52.155 -        selfCb.addActionListener(new java.awt.event.ActionListener() {
  52.156 -            public void actionPerformed(java.awt.event.ActionEvent evt) {
  52.157 -                changed(evt);
  52.158 -            }
  52.159 -        });
  52.160 -
  52.161 -        moduleCombo.setModel(getNameStyleModel());
  52.162 -        moduleCombo.addActionListener(new java.awt.event.ActionListener() {
  52.163 -            public void actionPerformed(java.awt.event.ActionEvent evt) {
  52.164 -                changed(evt);
  52.165 -            }
  52.166 -        });
  52.167 -
  52.168 -        classCombo.setModel(getNameStyleModel());
  52.169 -        classCombo.addActionListener(new java.awt.event.ActionListener() {
  52.170 -            public void actionPerformed(java.awt.event.ActionEvent evt) {
  52.171 -                changed(evt);
  52.172 -            }
  52.173 -        });
  52.174 -
  52.175 -        functionCombo.setModel(getNameStyleModel());
  52.176 -        functionCombo.addActionListener(new java.awt.event.ActionListener() {
  52.177 -            public void actionPerformed(java.awt.event.ActionEvent evt) {
  52.178 -                changed(evt);
  52.179 -            }
  52.180 -        });
  52.181 -
  52.182 -        variableLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.variableLabel.text")); // NOI18N
  52.183 -        variableLabel.setEnabled(false);
  52.184 -
  52.185 -        variableCombo.setModel(getNameStyleModel());
  52.186 -        variableCombo.setEnabled(false);
  52.187 -        variableCombo.addActionListener(new java.awt.event.ActionListener() {
  52.188 -            public void actionPerformed(java.awt.event.ActionEvent evt) {
  52.189 -                changed(evt);
  52.190 -            }
  52.191 -        });
  52.192 -
  52.193 -        ignoreLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.ignoreLabel.text")); // NOI18N
  52.194 -
  52.195 -        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
  52.196 -        this.setLayout(layout);
  52.197 -        layout.setHorizontalGroup(
  52.198 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  52.199 -            .addGroup(layout.createSequentialGroup()
  52.200 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  52.201 -                    .addGroup(layout.createSequentialGroup()
  52.202 -                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  52.203 -                            .addComponent(moduleLabel)
  52.204 -                            .addComponent(classLabel)
  52.205 -                            .addComponent(functionLabel)
  52.206 -                            .addComponent(variableLabel))
  52.207 -                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  52.208 -                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
  52.209 -                            .addComponent(variableCombo, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
  52.210 -                            .addComponent(classCombo, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
  52.211 -                            .addComponent(moduleCombo, javax.swing.GroupLayout.Alignment.LEADING, 0, 234, Short.MAX_VALUE)
  52.212 -                            .addComponent(functionCombo, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
  52.213 -                    .addComponent(parameterLabel)
  52.214 -                    .addComponent(selfCb)
  52.215 -                    .addGroup(layout.createSequentialGroup()
  52.216 -                        .addComponent(ignoreLabel)
  52.217 -                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  52.218 -                        .addComponent(ignoredText)))
  52.219 -                .addContainerGap())
  52.220 -        );
  52.221 -        layout.setVerticalGroup(
  52.222 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  52.223 -            .addGroup(layout.createSequentialGroup()
  52.224 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  52.225 -                    .addComponent(moduleLabel)
  52.226 -                    .addComponent(moduleCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
  52.227 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  52.228 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  52.229 -                    .addComponent(classLabel)
  52.230 -                    .addComponent(classCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
  52.231 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  52.232 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  52.233 -                    .addComponent(functionLabel)
  52.234 -                    .addComponent(functionCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
  52.235 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  52.236 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  52.237 -                    .addComponent(variableLabel)
  52.238 -                    .addComponent(variableCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
  52.239 -                .addGap(18, 18, 18)
  52.240 -                .addComponent(parameterLabel)
  52.241 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  52.242 -                .addComponent(selfCb)
  52.243 -                .addGap(18, 18, 18)
  52.244 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  52.245 -                    .addComponent(ignoreLabel)
  52.246 -                    .addComponent(ignoredText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
  52.247 -                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  52.248 -        );
  52.249 -    }// </editor-fold>//GEN-END:initComponents
  52.250 -
  52.251 -    private void changed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_changed
  52.252 -        Object source = evt.getSource();
  52.253 -
  52.254 -        if (source == moduleCombo) {
  52.255 -            NameStyle style = (NameStyle)moduleCombo.getSelectedItem();
  52.256 -            if (style != null) {
  52.257 -                rule.setModuleNameStyle(prefs, style);
  52.258 -            }
  52.259 -        } else if (source == functionCombo) {
  52.260 -            NameStyle style = (NameStyle)functionCombo.getSelectedItem();
  52.261 -            if (style != null) {
  52.262 -                rule.setFunctionNameStyle(prefs, style);
  52.263 -            }
  52.264 -        } else if (source == classCombo) {
  52.265 -            NameStyle style = (NameStyle)classCombo.getSelectedItem();
  52.266 -            if (style != null) {
  52.267 -                rule.setClassNameStyle(prefs, style);
  52.268 -            }
  52.269 -        } else if (source == variableCombo) {
  52.270 -            NameStyle style = (NameStyle)variableCombo.getSelectedItem();
  52.271 -            if (style != null) {
  52.272 -                rule.setVariableNameStyle(prefs, style);
  52.273 -            }
  52.274 -        } else if (source == ignoredText) {
  52.275 -            rule.setIgnoredNames(prefs, ignoredText.getText().trim());
  52.276 -        } else if (source == selfCb) {
  52.277 -            rule.setSelfRequired(prefs, selfCb.isSelected());
  52.278 -        }
  52.279 -    }//GEN-LAST:event_changed
  52.280 -    // Variables declaration - do not modify//GEN-BEGIN:variables
  52.281 -    private javax.swing.JComboBox classCombo;
  52.282 -    private javax.swing.JLabel classLabel;
  52.283 -    private javax.swing.JComboBox functionCombo;
  52.284 -    private javax.swing.JLabel functionLabel;
  52.285 -    private javax.swing.JLabel ignoreLabel;
  52.286 -    private javax.swing.JTextField ignoredText;
  52.287 -    private javax.swing.JComboBox moduleCombo;
  52.288 -    private javax.swing.JLabel moduleLabel;
  52.289 -    private javax.swing.JLabel parameterLabel;
  52.290 -    private javax.swing.JCheckBox selfCb;
  52.291 -    private javax.swing.JComboBox variableCombo;
  52.292 -    private javax.swing.JLabel variableLabel;
  52.293 -    // End of variables declaration//GEN-END:variables
  52.294 -}
    53.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/NameStyle.java	Sat Sep 12 23:03:15 2015 -0700
    53.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.3 @@ -1,169 +0,0 @@
    53.4 -/*
    53.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    53.6 - *
    53.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    53.8 - *
    53.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   53.10 - * Other names may be trademarks of their respective owners.
   53.11 - *
   53.12 - * The contents of this file are subject to the terms of either the GNU
   53.13 - * General Public License Version 2 only ("GPL") or the Common
   53.14 - * Development and Distribution License("CDDL") (collectively, the
   53.15 - * "License"). You may not use this file except in compliance with the
   53.16 - * License. You can obtain a copy of the License at
   53.17 - * http://www.netbeans.org/cddl-gplv2.html
   53.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   53.19 - * specific language governing permissions and limitations under the
   53.20 - * License.  When distributing the software, include this License Header
   53.21 - * Notice in each file and include the License file at
   53.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   53.23 - * particular file as subject to the "Classpath" exception as provided
   53.24 - * by Oracle in the GPL Version 2 section of the License file that
   53.25 - * accompanied this code. If applicable, add the following below the
   53.26 - * License Header, with the fields enclosed by brackets [] replaced by
   53.27 - * your own identifying information:
   53.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   53.29 - *
   53.30 - * If you wish your version of this file to be governed by only the CDDL
   53.31 - * or only the GPL Version 2, indicate your decision by adding
   53.32 - * "[Contributor] elects to include this software in this distribution
   53.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   53.34 - * single choice of license, a recipient has the option to distribute
   53.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   53.36 - * to extend the choice of license to its licensees as provided above.
   53.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   53.38 - * Version 2 license, then the option applies only if the new code is
   53.39 - * made subject to such option by the copyright holder.
   53.40 - *
   53.41 - * Contributor(s):
   53.42 - *
   53.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   53.44 - */
   53.45 -
   53.46 -package org.netbeans.modules.python.editor.hints;
   53.47 -
   53.48 -import org.openide.util.NbBundle;
   53.49 -
   53.50 -/**
   53.51 - *
   53.52 - * @author Tor Norbye
   53.53 - */
   53.54 -public enum NameStyle {
   53.55 -    NO_PREFERENCE(NbBundle.getMessage(NameStyle.class, "NoPreference")),
   53.56 -    LOWERCASE("lowercase"),
   53.57 -    LOWERCASE_WITH_UNDERSCORES("lowercase_with_underscores"),
   53.58 -    UPPERCASE("UPPERCASE"),
   53.59 -    UPPERCASE_WITH_UNDERSCORES("UPPERCASE_WITH_UNDERSCORES"),
   53.60 -    CAPITALIZED_WORDS("CapitalizedWords"),
   53.61 -    MIXED_CASE("mixedCase"),
   53.62 -    CAPITALIZED_WITH_UNDERSCORES("Capitalized_With_Underscores");
   53.63 -
   53.64 -    private String displayName;
   53.65 -
   53.66 -    NameStyle(String displayName) {
   53.67 -        this.displayName = displayName;
   53.68 -    }
   53.69 -
   53.70 -    String getDisplayName() {
   53.71 -        return displayName;
   53.72 -    }
   53.73 -
   53.74 -    public boolean complies(String name) {
   53.75 -        if (name.length() == 0) {
   53.76 -            return true;
   53.77 -        }
   53.78 -
   53.79 -        // Always allow one or two "_" at the beginning and end of the name since
   53.80 -        // these are used to indicate private, builtin, etc.
   53.81 -        int start = 0;
   53.82 -        int end = name.length();
   53.83 -        if (name.startsWith("__")) { // NOI18N
   53.84 -            start = 2;
   53.85 -        } else if (name.startsWith("_")) { // NOI18N
   53.86 -            start = 1;
   53.87 -        }
   53.88 -
   53.89 -        if (name.endsWith("__")) { // NOI18N
   53.90 -            end -= 2;
   53.91 -        } else if (name.endsWith("_")) { // NOI18N
   53.92 -            end -= 1;
   53.93 -        }
   53.94 -
   53.95 -        if (start >= end) {
   53.96 -            return false;
   53.97 -        }
   53.98 -
   53.99 -        switch (this) {
  53.100 -            case NO_PREFERENCE:
  53.101 -                return true;
  53.102 -
  53.103 -            case LOWERCASE_WITH_UNDERSCORES:
  53.104 -            case LOWERCASE:
  53.105 -                for (int i = start; i < end; i++) {
  53.106 -                    char c = name.charAt(i);
  53.107 -                    if (c == '_') {
  53.108 -                        if (this != LOWERCASE_WITH_UNDERSCORES) {
  53.109 -                            return false;
  53.110 -                        }
  53.111 -                    } else if (Character.isDigit(c)) {
  53.112 -                    } else if (!Character.isLowerCase(c)) {
  53.113 -                        return false;
  53.114 -                    }
  53.115 -                }
  53.116 -                
  53.117 -                return true;
  53.118 -                
  53.119 -
  53.120 -            case UPPERCASE:
  53.121 -            case UPPERCASE_WITH_UNDERSCORES:
  53.122 -                for (int i = start; i < end; i++) {
  53.123 -                    char c = name.charAt(i);
  53.124 -                    if (c == '_') {
  53.125 -                        if (this != UPPERCASE_WITH_UNDERSCORES) {
  53.126 -                            return false;
  53.127 -                        }
  53.128 -                    } else if (Character.isDigit(c)) {
  53.129 -                    } else if (!Character.isUpperCase(c)) {
  53.130 -                        return false;
  53.131 -                    }
  53.132 -                }
  53.133 -
  53.134 -                return true;
  53.135 -
  53.136 -            case MIXED_CASE:
  53.137 -            // TODO - require that characters after _ are capitalized?
  53.138 -            case CAPITALIZED_WORDS:
  53.139 -            case CAPITALIZED_WITH_UNDERSCORES:
  53.140 -                if (this == MIXED_CASE) {
  53.141 -                    // Must begin with lowercase
  53.142 -                    if (!Character.isLowerCase(name.charAt(start))) {
  53.143 -                        return false;
  53.144 -                    }
  53.145 -                } else if (this == CAPITALIZED_WORDS || this == CAPITALIZED_WITH_UNDERSCORES) {
  53.146 -                    // Must begin with uppercase
  53.147 -                    if (!Character.isUpperCase(name.charAt(start))) {
  53.148 -                        return false;
  53.149 -                    }
  53.150 -                }
  53.151 -                for (int i = start+1; i < end; i++) {
  53.152 -                    char c = name.charAt(i);
  53.153 -                    if (c == '_') {
  53.154 -                        if (this != CAPITALIZED_WITH_UNDERSCORES) {
  53.155 -                           return false;
  53.156 -                        }
  53.157 -                    } else if (Character.isDigit(c)) {
  53.158 -                    } else if (!Character.isUpperCase(c) && !Character.isLowerCase(c)) {
  53.159 -                        return false;
  53.160 -                    }
  53.161 -
  53.162 -                    // What about digits?
  53.163 -                }
  53.164 -
  53.165 -                return true;
  53.166 -            default:
  53.167 -                assert false : this;
  53.168 -        }
  53.169 -        
  53.170 -        return true;
  53.171 -    }
  53.172 -}
    54.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/PythonAstRule.java	Sat Sep 12 23:03:15 2015 -0700
    54.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.3 @@ -1,51 +0,0 @@
    54.4 -/*
    54.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    54.6 - *
    54.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    54.8 - *
    54.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   54.10 - * Other names may be trademarks of their respective owners.
   54.11 - *
   54.12 - * The contents of this file are subject to the terms of either the GNU
   54.13 - * General Public License Version 2 only ("GPL") or the Common
   54.14 - * Development and Distribution License("CDDL") (collectively, the
   54.15 - * "License"). You may not use this file except in compliance with the
   54.16 - * License. You can obtain a copy of the License at
   54.17 - * http://www.netbeans.org/cddl-gplv2.html
   54.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   54.19 - * specific language governing permissions and limitations under the
   54.20 - * License.  When distributing the software, include this License Header
   54.21 - * Notice in each file and include the License file at
   54.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   54.23 - * particular file as subject to the "Classpath" exception as provided
   54.24 - * by Oracle in the GPL Version 2 section of the License file that
   54.25 - * accompanied this code. If applicable, add the following below the
   54.26 - * License Header, with the fields enclosed by brackets [] replaced by
   54.27 - * your own identifying information:
   54.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   54.29 - *
   54.30 - * Contributor(s):
   54.31 - *
   54.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   54.33 - */
   54.34 -package org.netbeans.modules.python.editor.hints;
   54.35 -
   54.36 -import java.util.List;
   54.37 -import java.util.Set;
   54.38 -import org.netbeans.modules.csl.api.Hint;
   54.39 -import org.netbeans.modules.csl.api.Rule.AstRule;
   54.40 -
   54.41 -public abstract class PythonAstRule implements AstRule {
   54.42 -    /** 
   54.43 -     * Get the ElementKinds this rule should run on.
   54.44 -     * The integers should correspond to values in {@link org.mozilla.javascript.Token}
   54.45 -     */
   54.46 -    @Override
   54.47 -    public abstract Set<Class> getKinds();
   54.48 -
   54.49 -    /**
   54.50 -     * Run the test on given CompilationUnit and return list of Errors or
   54.51 -     * warrnings to be shown in the editor.
   54.52 -     */
   54.53 -    public abstract void run(PythonRuleContext context, List<Hint> result);
   54.54 -}
    55.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/PythonHintsProvider.java	Sat Sep 12 23:03:15 2015 -0700
    55.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.3 @@ -1,433 +0,0 @@
    55.4 -/*
    55.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    55.6 - *
    55.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    55.8 - *
    55.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   55.10 - * Other names may be trademarks of their respective owners.
   55.11 - *
   55.12 - * The contents of this file are subject to the terms of either the GNU
   55.13 - * General Public License Version 2 only ("GPL") or the Common
   55.14 - * Development and Distribution License("CDDL") (collectively, the
   55.15 - * "License"). You may not use this file except in compliance with the
   55.16 - * License. You can obtain a copy of the License at
   55.17 - * http://www.netbeans.org/cddl-gplv2.html
   55.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   55.19 - * specific language governing permissions and limitations under the
   55.20 - * License.  When distributing the software, include this License Header
   55.21 - * Notice in each file and include the License file at
   55.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   55.23 - * particular file as subject to the "Classpath" exception as provided
   55.24 - * by Oracle in the GPL Version 2 section of the License file that
   55.25 - * accompanied this code. If applicable, add the following below the
   55.26 - * License Header, with the fields enclosed by brackets [] replaced by
   55.27 - * your own identifying information:
   55.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   55.29 - *
   55.30 - * Contributor(s):
   55.31 - *
   55.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   55.33 - */
   55.34 -package org.netbeans.modules.python.editor.hints;
   55.35 -
   55.36 -import java.util.Collections;
   55.37 -import java.util.HashMap;
   55.38 -import java.util.Iterator;
   55.39 -import java.util.LinkedList;
   55.40 -import java.util.List;
   55.41 -import java.util.Map;
   55.42 -import java.util.Map.Entry;
   55.43 -import java.util.Set;
   55.44 -import org.netbeans.modules.csl.api.Error;
   55.45 -import org.netbeans.modules.csl.api.Hint;
   55.46 -import org.netbeans.modules.csl.api.HintFix;
   55.47 -import org.netbeans.modules.csl.api.HintSeverity;
   55.48 -import org.netbeans.modules.csl.api.HintsProvider;
   55.49 -import org.netbeans.modules.csl.api.HintsProvider.HintsManager;
   55.50 -import org.netbeans.modules.csl.api.OffsetRange;
   55.51 -import org.netbeans.modules.csl.api.Rule;
   55.52 -import org.netbeans.modules.csl.api.RuleContext;
   55.53 -import org.netbeans.modules.csl.spi.GsfUtilities;
   55.54 -import org.netbeans.modules.csl.spi.ParserResult;
   55.55 -import org.netbeans.modules.python.editor.AstPath;
   55.56 -import org.netbeans.modules.python.editor.PythonAstUtils;
   55.57 -import org.netbeans.modules.python.editor.PythonParserResult;
   55.58 -import org.openide.util.Exceptions;
   55.59 -import org.python.antlr.PythonTree;
   55.60 -import org.python.antlr.Visitor;
   55.61 -
   55.62 -/**
   55.63 - *
   55.64 - * @todo Write rules based on the PythonChecker ideas:
   55.65 - *   http://pychecker.sourceforge.net/
   55.66 - * @todo Write rules based on the PyLint ideas:
   55.67 - *   http://www.logilab.org/projects/pylint
   55.68 - *   http://www.logilab.org/card/pylintfeatures
   55.69 - *
   55.70 - * @author Tor Norbye
   55.71 - */
   55.72 -public class PythonHintsProvider implements HintsProvider {
   55.73 -    private boolean cancelled;
   55.74 -
   55.75 -    public PythonHintsProvider() {
   55.76 -    }
   55.77 -
   55.78 -    private static class ScopeRule implements Rule {
   55.79 -        @Override
   55.80 -        public boolean appliesTo(RuleContext context) {
   55.81 -            return true;
   55.82 -        }
   55.83 -
   55.84 -        @Override
   55.85 -        public String getDisplayName() {
   55.86 -            return "";
   55.87 -        }
   55.88 -
   55.89 -        @Override
   55.90 -        public boolean showInTasklist() {
   55.91 -            return true;
   55.92 -        }
   55.93 -
   55.94 -        @Override
   55.95 -        public HintSeverity getDefaultSeverity() {
   55.96 -            return HintSeverity.ERROR;
   55.97 -        }
   55.98 -    }
   55.99 -    
  55.100 -    @Override
  55.101 -    public void computeErrors(HintsManager manager, RuleContext context, List<Hint> result, List<Error> unhandled) {
  55.102 -        ParserResult parserResult = context.parserResult;
  55.103 -        if (parserResult == null) {
  55.104 -            return;
  55.105 -        }
  55.106 -
  55.107 -        PythonParserResult pr = (PythonParserResult)parserResult;
  55.108 -        List<Error> scopeErrors = pr.getSymbolTable().getErrors();
  55.109 -        if (scopeErrors.size() > 0) {
  55.110 -            List<HintFix> fixList = Collections.emptyList();
  55.111 -            Rule rule = new ScopeRule(); // HACK! Just need a rule that will return a severity!
  55.112 -            for (Error error : scopeErrors) {
  55.113 -                Hint desc = new Hint(rule, error.getDisplayName(), error.getFile(),
  55.114 -                        new OffsetRange(error.getStartPosition(), error.getEndPosition()), fixList, 10);
  55.115 -                result.add(desc);
  55.116 -            }
  55.117 -        }
  55.118 -
  55.119 -        List<? extends Error> errors = parserResult.getDiagnostics();
  55.120 -        if (errors == null || errors.size() == 0) {
  55.121 -            return;
  55.122 -        }
  55.123 -//
  55.124 -//        cancelled = false;
  55.125 -//
  55.126 -//        @SuppressWarnings("unchecked")
  55.127 -//        Map<String,List<JsErrorRule>> hints = (Map)manager.getErrors();
  55.128 -//
  55.129 -//        if (hints.isEmpty() || isCancelled()) {
  55.130 -        unhandled.addAll(errors);
  55.131 -//            return;
  55.132 -//        }
  55.133 -//
  55.134 -//        for (Error error : errors) {
  55.135 -//            if (!applyErrorRules(manager, context, error, hints, result)) {
  55.136 -//                unhandled.add(error);
  55.137 -//            }
  55.138 -//        }
  55.139 -    }
  55.140 -
  55.141 -    @Override
  55.142 -    public void computeSelectionHints(HintsManager manager, RuleContext context, List<Hint> result, int start, int end) {
  55.143 -        cancelled = false;
  55.144 -
  55.145 -        if (GsfUtilities.isCodeTemplateEditing(context.doc)) {
  55.146 -            return;
  55.147 -        }
  55.148 -
  55.149 -        ParserResult parserResult = context.parserResult;
  55.150 -        if (parserResult == null) {
  55.151 -            return;
  55.152 -        }
  55.153 -        PythonTree root = PythonAstUtils.getRoot(context.parserResult);
  55.154 -
  55.155 -        if (root == null) {
  55.156 -            return;
  55.157 -        }
  55.158 -        @SuppressWarnings("unchecked")
  55.159 -        List<? extends Rule.SelectionRule> hints = manager.getSelectionHints();
  55.160 -
  55.161 -        if (hints.isEmpty()) {
  55.162 -            return;
  55.163 -        }
  55.164 -
  55.165 -        if (isCancelled()) {
  55.166 -            return;
  55.167 -        }
  55.168 -
  55.169 -        try {
  55.170 -            context.doc.readLock();
  55.171 -            applySelectionRules(manager, context, hints, result);
  55.172 -        } finally {
  55.173 -            context.doc.readUnlock();
  55.174 -        }
  55.175 -}
  55.176 -
  55.177 -    private void applySelectionRules(HintsManager manager, RuleContext context, List<? extends Rule.SelectionRule> rules, List<Hint> result) {
  55.178 -
  55.179 -        PythonRuleContext pythonContext = (PythonRuleContext)context;
  55.180 -
  55.181 -        for (Rule.SelectionRule rule : rules) {
  55.182 -            if (!rule.appliesTo(context)) {
  55.183 -                continue;
  55.184 -            }
  55.185 -            
  55.186 -            if(!(rule instanceof PythonSelectionRule)) {
  55.187 -                continue;
  55.188 -            }
  55.189 -
  55.190 -            if (!manager.isEnabled((PythonSelectionRule)rule)) {
  55.191 -                continue;
  55.192 -            }
  55.193 -
  55.194 -            try {
  55.195 -                context.doc.readLock();
  55.196 -                ((PythonSelectionRule)rule).run(pythonContext, result);
  55.197 -            } finally {
  55.198 -                context.doc.readUnlock();
  55.199 -            }
  55.200 -        }
  55.201 -    }
  55.202 -
  55.203 -    @Override
  55.204 -    public void computeHints(HintsManager manager, RuleContext context, List<Hint> result) {
  55.205 -        cancelled = false;
  55.206 -
  55.207 -        if (context.parserResult == null) {
  55.208 -            return;
  55.209 -        }
  55.210 -        PythonTree root = PythonAstUtils.getRoot(context.parserResult);
  55.211 -
  55.212 -        if (root == null) {
  55.213 -            return;
  55.214 -        }
  55.215 -        @SuppressWarnings("unchecked")
  55.216 -        Map<Class, List<PythonAstRule>> hints = (Map)manager.getHints(false, context);
  55.217 -
  55.218 -        if (hints.isEmpty()) {
  55.219 -            return;
  55.220 -        }
  55.221 -
  55.222 -        if (isCancelled()) {
  55.223 -            return;
  55.224 -        }
  55.225 -
  55.226 -//        AstPath path = new AstPath();
  55.227 -//        path.descend(root);
  55.228 -//
  55.229 -//        //applyRules(manager, NodeTypes.ROOTNODE, root, path, info, hints, descriptions);
  55.230 -//        applyHints(manager, context, -1, root, path, hints, result);
  55.231 -//
  55.232 -//        scan(manager, context, root, path, hints, result);
  55.233 -//        path.ascend();
  55.234 -
  55.235 -
  55.236 -        RuleApplicator finder = new RuleApplicator(manager, context, hints, result);
  55.237 -        try {
  55.238 -            context.doc.readLock();
  55.239 -            finder.visit(root);
  55.240 -        } catch (Exception ex) {
  55.241 -            Exceptions.printStackTrace(ex);
  55.242 -        } finally {
  55.243 -            context.doc.readUnlock();
  55.244 -        }
  55.245 -    }
  55.246 -
  55.247 -    @SuppressWarnings("unchecked")
  55.248 -    @Override
  55.249 -    public void computeSuggestions(HintsManager manager, RuleContext context, List<Hint> result, int caretOffset) {
  55.250 -        cancelled = false;
  55.251 -        if (context.parserResult == null) {
  55.252 -            return;
  55.253 -        }
  55.254 -
  55.255 -        PythonTree root = PythonAstUtils.getRoot(context.parserResult);
  55.256 -
  55.257 -        if (root == null) {
  55.258 -            return;
  55.259 -        }
  55.260 -
  55.261 -        Map<Class, List<PythonAstRule>> suggestions = new HashMap<>();
  55.262 -        suggestions.putAll((Map)manager.getHints(true, context));
  55.263 -
  55.264 -        Set<Entry<Class, List<PythonAstRule>>> entrySet = (Set)manager.getSuggestions().entrySet();
  55.265 -        for (Entry<Class, List<PythonAstRule>> e : entrySet) {
  55.266 -            List<PythonAstRule> rules = suggestions.get(e.getKey());
  55.267 -
  55.268 -            if (rules != null) {
  55.269 -                List<PythonAstRule> res = new LinkedList<>();
  55.270 -
  55.271 -                res.addAll(rules);
  55.272 -                res.addAll(e.getValue());
  55.273 -
  55.274 -                suggestions.put(e.getKey(), res);
  55.275 -            } else {
  55.276 -                suggestions.put(e.getKey(), e.getValue());
  55.277 -            }
  55.278 -        }
  55.279 -
  55.280 -        if (suggestions.isEmpty()) {
  55.281 -            return;
  55.282 -        }
  55.283 -
  55.284 -
  55.285 -        if (isCancelled()) {
  55.286 -            return;
  55.287 -        }
  55.288 -
  55.289 -        try {
  55.290 -            context.doc.readLock();
  55.291 -
  55.292 -            PythonParserResult info = (PythonParserResult)context.parserResult;
  55.293 -            int astOffset = PythonAstUtils.getAstOffset(info, caretOffset);
  55.294 -            AstPath path = AstPath.get(root, astOffset);
  55.295 -            Iterator<PythonTree> it = path.leafToRoot();
  55.296 -            while (it.hasNext()) {
  55.297 -                if (isCancelled()) {
  55.298 -                    return;
  55.299 -                }
  55.300 -
  55.301 -                PythonTree node = it.next();
  55.302 -
  55.303 -                applySuggestions(manager, context, node.getClass(), node, path, suggestions, result);
  55.304 -            }
  55.305 -        } finally {
  55.306 -            context.doc.readUnlock();
  55.307 -        }
  55.308 -
  55.309 -    //applyRules(NodeTypes.ROOTNODE, path, info, suggestions, caretOffset, result);
  55.310 -    }
  55.311 -
  55.312 -    private void applySuggestions(HintsManager manager, RuleContext context, Class nodeType, PythonTree node, AstPath path, Map<Class, List<PythonAstRule>> hints,
  55.313 -            List<Hint> result) {
  55.314 -        List<PythonAstRule> rules = hints.get(nodeType);
  55.315 -
  55.316 -        if (rules != null) {
  55.317 -            PythonRuleContext pyCtx = (PythonRuleContext)context;
  55.318 -            pyCtx.node = node;
  55.319 -            pyCtx.path = path;
  55.320 -
  55.321 -            try {
  55.322 -                context.doc.readLock();
  55.323 -                for (PythonAstRule rule : rules) {
  55.324 -                    if (manager.isEnabled(rule)) {
  55.325 -                        rule.run(pyCtx, result);
  55.326 -                    }
  55.327 -                }
  55.328 -            } finally {
  55.329 -                context.doc.readUnlock();
  55.330 -            }
  55.331 -        }
  55.332 -    }
  55.333 -
  55.334 -//    /** Apply error rules and return true iff somebody added an error description for it */
  55.335 -//    private boolean applyErrorRules(HintsManager manager, RuleContext context, Error error, Map<String,List<JsErrorRule>> hints,
  55.336 -//            List<Hint> result) {
  55.337 -//        String code = error.getKey();
  55.338 -//        if (code != null) {
  55.339 -//            List<JsErrorRule> rules = hints.get(code);
  55.340 -//
  55.341 -//            if (rules != null) {
  55.342 -//                int countBefore = result.size();
  55.343 -//                PythonRuleContext jsContext = (PythonRuleContext)context;
  55.344 -//
  55.345 -//                boolean disabled = false;
  55.346 -//                for (JsErrorRule rule : rules) {
  55.347 -//                    if (!manager.isEnabled(rule)) {
  55.348 -//                        disabled = true;
  55.349 -//                    } else if (rule.appliesTo(context)) {
  55.350 -//                        rule.run(jsContext, error, result);
  55.351 -//                    }
  55.352 -//                }
  55.353 -//
  55.354 -//                return disabled || countBefore < result.size() || jsContext.remove;
  55.355 -//            }
  55.356 -//        }
  55.357 -//
  55.358 -//        return false;
  55.359 -//    }
  55.360 -//
  55.361 -//    private void applySelectionRules(HintsManager manager, RuleContext context, List<JsSelectionRule> rules,
  55.362 -//            List<Hint> result) {
  55.363 -//
  55.364 -//        for (JsSelectionRule rule : rules) {
  55.365 -//            if (!rule.appliesTo(context)) {
  55.366 -//                continue;
  55.367 -//            }
  55.368 -//
  55.369 -//            //if (!manager.isEnabled(rule)) {
  55.370 -//            //    continue;
  55.371 -//            //}
  55.372 -//
  55.373 -//            rule.run(context, result);
  55.374 -//        }
  55.375 -//    }
  55.376 -//
  55.377 -    @Override
  55.378 -    public void cancel() {
  55.379 -        cancelled = true;
  55.380 -    }
  55.381 -
  55.382 -    private boolean isCancelled() {
  55.383 -        return cancelled;
  55.384 -    }
  55.385 -
  55.386 -    @Override
  55.387 -    public RuleContext createRuleContext() {
  55.388 -        return new PythonRuleContext();
  55.389 -    }
  55.390 -
  55.391 -    @Override
  55.392 -    public List<Rule> getBuiltinRules() {
  55.393 -        return Collections.emptyList();
  55.394 -    }
  55.395 -
  55.396 -    private static class RuleApplicator extends Visitor {
  55.397 -        private HintsManager manager;
  55.398 -        private RuleContext context;
  55.399 -        private AstPath path;
  55.400 -        private Map<Class, List<PythonAstRule>> hints;
  55.401 -        private List<Hint> result;
  55.402 -
  55.403 -        public RuleApplicator(HintsManager manager, RuleContext context, Map<Class, List<PythonAstRule>> hints, List<Hint> result) {
  55.404 -            this.manager = manager;
  55.405 -            this.context = context;
  55.406 -            this.hints = hints;
  55.407 -            this.result = result;
  55.408 -
  55.409 -            path = new AstPath();
  55.410 -        }
  55.411 -
  55.412 -        @Override
  55.413 -        public void traverse(PythonTree node) throws Exception {
  55.414 -            path.descend(node);
  55.415 -            applyHints(node);
  55.416 -            super.traverse(node);
  55.417 -            path.ascend();
  55.418 -        }
  55.419 -
  55.420 -        private void applyHints(PythonTree node) {
  55.421 -            List<PythonAstRule> rules = hints.get(node.getClass());
  55.422 -
  55.423 -            if (rules != null) {
  55.424 -                PythonRuleContext jsContext = (PythonRuleContext)context;
  55.425 -                jsContext.node = node;
  55.426 -                jsContext.path = path;
  55.427 -
  55.428 -                for (PythonAstRule rule : rules) {
  55.429 -                    if (manager.isEnabled(rule)) {
  55.430 -                        rule.run(jsContext, result);
  55.431 -                    }
  55.432 -                }
  55.433 -            }
  55.434 -        }
  55.435 -    }
  55.436 -}
    56.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/PythonRuleContext.java	Sat Sep 12 23:03:15 2015 -0700
    56.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.3 @@ -1,45 +0,0 @@
    56.4 -/*
    56.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    56.6 - *
    56.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    56.8 - *
    56.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   56.10 - * Other names may be trademarks of their respective owners.
   56.11 - *
   56.12 - * The contents of this file are subject to the terms of either the GNU
   56.13 - * General Public License Version 2 only ("GPL") or the Common
   56.14 - * Development and Distribution License("CDDL") (collectively, the
   56.15 - * "License"). You may not use this file except in compliance with the
   56.16 - * License. You can obtain a copy of the License at
   56.17 - * http://www.netbeans.org/cddl-gplv2.html
   56.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   56.19 - * specific language governing permissions and limitations under the
   56.20 - * License.  When distributing the software, include this License Header
   56.21 - * Notice in each file and include the License file at
   56.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   56.23 - * particular file as subject to the "Classpath" exception as provided
   56.24 - * by Oracle in the GPL Version 2 section of the License file that
   56.25 - * accompanied this code. If applicable, add the following below the
   56.26 - * License Header, with the fields enclosed by brackets [] replaced by
   56.27 - * your own identifying information:
   56.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   56.29 - *
   56.30 - * Contributor(s):
   56.31 - *
   56.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   56.33 - */
   56.34 -package org.netbeans.modules.python.editor.hints;
   56.35 -
   56.36 -import org.netbeans.modules.python.editor.AstPath;
   56.37 -import org.python.antlr.PythonTree;
   56.38 -
   56.39 -/**
   56.40 - * Information about the current context a rule is being asked to evaluate.
   56.41 - * 
   56.42 - * @author Tor Norbye
   56.43 - */
   56.44 -public class PythonRuleContext extends org.netbeans.modules.csl.api.RuleContext {
   56.45 -    public AstPath path;
   56.46 -    public PythonTree node;
   56.47 -    public boolean remove;
   56.48 -}
    57.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/PythonSelectionRule.java	Sat Sep 12 23:03:15 2015 -0700
    57.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.3 @@ -1,128 +0,0 @@
    57.4 -/*
    57.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    57.6 - *
    57.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    57.8 - *
    57.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   57.10 - * Other names may be trademarks of their respective owners.
   57.11 - *
   57.12 - * The contents of this file are subject to the terms of either the GNU
   57.13 - * General Public License Version 2 only ("GPL") or the Common
   57.14 - * Development and Distribution License("CDDL") (collectively, the
   57.15 - * "License"). You may not use this file except in compliance with the
   57.16 - * License. You can obtain a copy of the License at
   57.17 - * http://www.netbeans.org/cddl-gplv2.html
   57.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   57.19 - * specific language governing permissions and limitations under the
   57.20 - * License.  When distributing the software, include this License Header
   57.21 - * Notice in each file and include the License file at
   57.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   57.23 - * particular file as subject to the "Classpath" exception as provided
   57.24 - * by Oracle in the GPL Version 2 section of the License file that
   57.25 - * accompanied this code. If applicable, add the following below the
   57.26 - * License Header, with the fields enclosed by brackets [] replaced by
   57.27 - * your own identifying information:
   57.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   57.29 - *
   57.30 - * Contributor(s):
   57.31 - *
   57.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   57.33 - */
   57.34 -package org.netbeans.modules.python.editor.hints;
   57.35 -
   57.36 -import javax.swing.text.BadLocationException;
   57.37 -import java.util.List;
   57.38 -import org.netbeans.modules.python.editor.PythonAstUtils;
   57.39 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   57.40 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   57.41 -import org.netbeans.api.lexer.Token;
   57.42 -import org.netbeans.api.lexer.TokenId;
   57.43 -import org.netbeans.editor.BaseDocument;
   57.44 -import org.netbeans.editor.Utilities;
   57.45 -import org.netbeans.modules.csl.api.Hint;
   57.46 -import org.netbeans.modules.csl.api.OffsetRange;
   57.47 -import org.netbeans.modules.csl.api.Rule.SelectionRule;
   57.48 -import org.netbeans.modules.csl.api.Rule.UserConfigurableRule;
   57.49 -import org.openide.util.Exceptions;
   57.50 -import org.python.antlr.PythonTree;
   57.51 -
   57.52 -/**
   57.53 - * Represents a rule to be run on text selection
   57.54 - *
   57.55 - * @author Tor Norbye
   57.56 - */
   57.57 -public abstract class PythonSelectionRule implements SelectionRule, UserConfigurableRule {
   57.58 -    protected abstract int getApplicability(PythonRuleContext context, PythonTree root, OffsetRange astRange);
   57.59 -
   57.60 -    //public abstract void run(PythonRuleContext context, List<Hint> result);
   57.61 -    public void run(PythonRuleContext context, List<Hint> result) {
   57.62 -        // TODO - decide if this code represents a complete statement...
   57.63 -        // For now - that's true iff there's no code to the left on the
   57.64 -        // start line and code to the right on the end line
   57.65 -        BaseDocument doc = context.doc;
   57.66 -        int originalStart = context.selectionStart;
   57.67 -        int originalEnd = context.selectionEnd;
   57.68 -        int docLength = doc.getLength();
   57.69 -
   57.70 -        if (originalEnd > docLength) {
   57.71 -            return;
   57.72 -        }
   57.73 -        OffsetRange narrowed = PythonLexerUtils.narrow(doc, new OffsetRange(originalStart, originalEnd), false);
   57.74 -        if (narrowed == OffsetRange.NONE) {
   57.75 -            return;
   57.76 -        }
   57.77 -
   57.78 -        int start = narrowed.getStart();
   57.79 -        int end = narrowed.getEnd();
   57.80 -        try {
   57.81 -            if (start > Utilities.getRowFirstNonWhite(doc, Math.min(docLength, start))) {
   57.82 -                return;
   57.83 -            }
   57.84 -            if (end < Utilities.getRowLastNonWhite(doc, Math.min(docLength, end)) + 1) {
   57.85 -                return;
   57.86 -            }
   57.87 -        } catch (BadLocationException ex) {
   57.88 -            Exceptions.printStackTrace(ex);
   57.89 -        }
   57.90 -
   57.91 -        PythonTree root = PythonAstUtils.getRoot(context.parserResult);
   57.92 -        if (root == null) {
   57.93 -            return;
   57.94 -        }
   57.95 -
   57.96 -        OffsetRange astRange = PythonAstUtils.getAstOffsets(context.parserResult, new OffsetRange(start, end));
   57.97 -        if (astRange == OffsetRange.NONE) {
   57.98 -            return;
   57.99 -        }
  57.100 -
  57.101 -        int applicability = getApplicability(context, root, astRange);
  57.102 -        if (applicability == 0) {
  57.103 -            return;
  57.104 -        }
  57.105 -        // Don't allow extract with if you're inside strings or comments
  57.106 -        Token<? extends PythonTokenId> startToken = PythonLexerUtils.getToken(doc, start);
  57.107 -        Token<? extends PythonTokenId> endToken = PythonLexerUtils.getToken(doc, end);
  57.108 -        if (startToken == null || endToken == null) {
  57.109 -            return;
  57.110 -        }
  57.111 -        TokenId startId = startToken.id();
  57.112 -        if (startId == PythonTokenId.STRING_LITERAL ||
  57.113 -                (startId == PythonTokenId.COMMENT && start > 0 && startToken == PythonLexerUtils.getToken(doc, start - 1))) {
  57.114 -            return;
  57.115 -        }
  57.116 -        TokenId endId = endToken.id();
  57.117 -        if (endId == PythonTokenId.STRING_LITERAL) {
  57.118 -            return;
  57.119 -        }
  57.120 -
  57.121 -        // TODO - don't enable inside comments or strings!!
  57.122 -        // TODO - if you are including functions or classes it should probably
  57.123 -        // be disabled!
  57.124 -
  57.125 -        OffsetRange range = new OffsetRange(originalStart, originalEnd);
  57.126 -
  57.127 -        run(context, result, range, applicability);
  57.128 -    }
  57.129 -
  57.130 -    public abstract void run(PythonRuleContext context, List<Hint> result, OffsetRange range, int applicability);
  57.131 -}
    58.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/RelativeImports.java	Sat Sep 12 23:03:15 2015 -0700
    58.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.3 @@ -1,246 +0,0 @@
    58.4 -/*
    58.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    58.6 - *
    58.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    58.8 - *
    58.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   58.10 - * Other names may be trademarks of their respective owners.
   58.11 - *
   58.12 - * The contents of this file are subject to the terms of either the GNU
   58.13 - * General Public License Version 2 only ("GPL") or the Common
   58.14 - * Development and Distribution License("CDDL") (collectively, the
   58.15 - * "License"). You may not use this file except in compliance with the
   58.16 - * License. You can obtain a copy of the License at
   58.17 - * http://www.netbeans.org/cddl-gplv2.html
   58.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   58.19 - * specific language governing permissions and limitations under the
   58.20 - * License.  When distributing the software, include this License Header
   58.21 - * Notice in each file and include the License file at
   58.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   58.23 - * particular file as subject to the "Classpath" exception as provided
   58.24 - * by Oracle in the GPL Version 2 section of the License file that
   58.25 - * accompanied this code. If applicable, add the following below the
   58.26 - * License Header, with the fields enclosed by brackets [] replaced by
   58.27 - * your own identifying information:
   58.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   58.29 - *
   58.30 - * If you wish your version of this file to be governed by only the CDDL
   58.31 - * or only the GPL Version 2, indicate your decision by adding
   58.32 - * "[Contributor] elects to include this software in this distribution
   58.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   58.34 - * single choice of license, a recipient has the option to distribute
   58.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   58.36 - * to extend the choice of license to its licensees as provided above.
   58.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   58.38 - * Version 2 license, then the option applies only if the new code is
   58.39 - * made subject to such option by the copyright holder.
   58.40 - *
   58.41 - * Contributor(s):
   58.42 - *
   58.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   58.44 - */
   58.45 -package org.netbeans.modules.python.editor.hints;
   58.46 -
   58.47 -import java.util.ArrayList;
   58.48 -import java.util.Collections;
   58.49 -import java.util.List;
   58.50 -import java.util.Set;
   58.51 -import java.util.prefs.Preferences;
   58.52 -import javax.swing.JComponent;
   58.53 -import javax.swing.text.BadLocationException;
   58.54 -import org.netbeans.modules.python.editor.PythonAstUtils;
   58.55 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   58.56 -import org.netbeans.editor.BaseDocument;
   58.57 -import org.netbeans.editor.Utilities;
   58.58 -import org.netbeans.modules.csl.api.EditList;
   58.59 -import org.netbeans.modules.csl.api.Hint;
   58.60 -import org.netbeans.modules.csl.api.HintFix;
   58.61 -import org.netbeans.modules.csl.api.HintSeverity;
   58.62 -import org.netbeans.modules.csl.api.OffsetRange;
   58.63 -import org.netbeans.modules.csl.api.PreviewableFix;
   58.64 -import org.netbeans.modules.csl.api.RuleContext;
   58.65 -import org.netbeans.modules.csl.spi.ParserResult;
   58.66 -import org.netbeans.modules.python.editor.PythonParserResult;
   58.67 -import org.openide.filesystems.FileObject;
   58.68 -import org.openide.util.Exceptions;
   58.69 -import org.openide.util.NbBundle;
   58.70 -import org.python.antlr.PythonTree;
   58.71 -import org.python.antlr.ast.ImportFrom;
   58.72 -
   58.73 -/**
   58.74 - * Import statements should be one per line. This quickfix
   58.75 - * offers to make it so.
   58.76 - *
   58.77 - * @todo Ensure that
   58.78 - *  {@code from __future__ import absolute_import}
   58.79 - *   is present, at least until Python 2.7
   58.80 - *
   58.81 - * @author Tor Norbye
   58.82 - */
   58.83 -public class RelativeImports extends PythonAstRule {
   58.84 -    @Override
   58.85 -    public Set<Class> getKinds() {
   58.86 -        return Collections.singleton((Class)ImportFrom.class);
   58.87 -    }
   58.88 -
   58.89 -    @Override
   58.90 -    public void run(PythonRuleContext context, List<Hint> result) {
   58.91 -        ImportFrom imp = (ImportFrom)context.node;
   58.92 -        if (imp.getInternalModule() != null && imp.getInternalModule().startsWith(".")) {
   58.93 -            PythonTree node = context.node;
   58.94 -            PythonParserResult info = (PythonParserResult) context.parserResult;
   58.95 -            OffsetRange astOffsets = PythonAstUtils.getNameRange(info, node);
   58.96 -            OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
   58.97 -            BaseDocument doc = context.doc;
   58.98 -            try {
   58.99 -                if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
  58.100 -                        (context.caretOffset == -1 ||
  58.101 -                        Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
  58.102 -                    List<HintFix> fixList = new ArrayList<>();
  58.103 -                    fixList.add(new RelativeImportsFix(context, imp));
  58.104 -                    String displayName = getDisplayName();
  58.105 -                    Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
  58.106 -                    result.add(desc);
  58.107 -                }
  58.108 -            } catch (BadLocationException ex) {
  58.109 -                Exceptions.printStackTrace(ex);
  58.110 -            }
  58.111 -        }
  58.112 -    }
  58.113 -
  58.114 -    @Override
  58.115 -    public String getId() {
  58.116 -        return "RelativeImports"; // NOI18N
  58.117 -    }
  58.118 -
  58.119 -    @Override
  58.120 -    public String getDisplayName() {
  58.121 -        return NbBundle.getMessage(RelativeImports.class, "RelativeImports");
  58.122 -    }
  58.123 -
  58.124 -    @Override
  58.125 -    public String getDescription() {
  58.126 -        return NbBundle.getMessage(RelativeImports.class, "RelativeImportsDesc");
  58.127 -    }
  58.128 -
  58.129 -    @Override
  58.130 -    public boolean getDefaultEnabled() {
  58.131 -        return true;
  58.132 -    }
  58.133 -
  58.134 -    @Override
  58.135 -    public JComponent getCustomizer(Preferences node) {
  58.136 -        return null;
  58.137 -    }
  58.138 -
  58.139 -    @Override
  58.140 -    public boolean appliesTo(RuleContext context) {
  58.141 -        return true;
  58.142 -    }
  58.143 -
  58.144 -    @Override
  58.145 -    public boolean showInTasklist() {
  58.146 -        return true;
  58.147 -    }
  58.148 -
  58.149 -    @Override
  58.150 -    public HintSeverity getDefaultSeverity() {
  58.151 -        return HintSeverity.WARNING;
  58.152 -    }
  58.153 -
  58.154 -    private static class RelativeImportsFix implements PreviewableFix {
  58.155 -        private final PythonRuleContext context;
  58.156 -        private final ImportFrom imp;
  58.157 -
  58.158 -        private RelativeImportsFix(PythonRuleContext context, ImportFrom imp) {
  58.159 -            this.context = context;
  58.160 -            this.imp = imp;
  58.161 -        }
  58.162 -
  58.163 -        @Override
  58.164 -        public String getDescription() {
  58.165 -            return NbBundle.getMessage(RelativeImports.class, "RelativeImportsFix");
  58.166 -        }
  58.167 -
  58.168 -        @Override
  58.169 -        public boolean canPreview() {
  58.170 -            return true;
  58.171 -        }
  58.172 -
  58.173 -        @Override
  58.174 -        public EditList getEditList() throws Exception {
  58.175 -            BaseDocument doc = context.doc;
  58.176 -            EditList edits = new EditList(doc);
  58.177 -
  58.178 -            // Algorithm:
  58.179 -            //  (1) Figure out which package we are in
  58.180 -            //  (2) Subtrack package elements per dot
  58.181 -            //  (3) Replace relative reference
  58.182 -
  58.183 -            OffsetRange astRange = PythonAstUtils.getRange(imp);
  58.184 -            if (astRange != OffsetRange.NONE) {
  58.185 -                PythonParserResult info = (PythonParserResult)context.parserResult;
  58.186 -                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
  58.187 -                if (lexRange != OffsetRange.NONE) {
  58.188 -                    FileObject fo = info.getSnapshot().getSource().getFileObject();
  58.189 -                    if (fo != null) {
  58.190 -                        String path = imp.getInternalModule();
  58.191 -                        int i = 0;
  58.192 -                        for (; i < path.length(); i++) {
  58.193 -                            if (path.charAt(i) != '.') {
  58.194 -                                break;
  58.195 -                            }
  58.196 -                        }
  58.197 -                        int levels = i;
  58.198 -                        path = path.substring(levels);
  58.199 -
  58.200 -                        for (int j = 0; j < levels; j++) {
  58.201 -                            if (fo != null) {
  58.202 -                                fo = fo.getParent();
  58.203 -                            }
  58.204 -                        }
  58.205 -
  58.206 -                        // Finally, find out the absolute path we are in
  58.207 -                        // Hopefully, I will have access to the python load path
  58.208 -                        // here. But in the mean time, I can just see which 
  58.209 -                        // packages I am in...
  58.210 -                        while (fo != null) {
  58.211 -                            if (fo.getFileObject("__init__.py") != null) { // NOI18N
  58.212 -                                // Yep, we're still in a package
  58.213 -                                if (path.length() > 0) {
  58.214 -                                    path = fo.getName() + "." + path; // NOI18N
  58.215 -                                } else {
  58.216 -                                    path = fo.getName();
  58.217 -                                }
  58.218 -                            }
  58.219 -                            fo = fo.getParent();
  58.220 -                        }
  58.221 -                        String text = doc.getText(lexRange.getStart(), lexRange.getLength());
  58.222 -                        int relativePos = text.indexOf(imp.getInternalModule());
  58.223 -                        if (relativePos != -1) {
  58.224 -                            edits.replace(lexRange.getStart() + relativePos, imp.getInternalModule().length(), path, false, 0);
  58.225 -                        }
  58.226 -                    }
  58.227 -                }
  58.228 -            }
  58.229 -
  58.230 -            return edits;
  58.231 -        }
  58.232 -
  58.233 -        @Override
  58.234 -        public void implement() throws Exception {
  58.235 -            EditList edits = getEditList();
  58.236 -            edits.apply();
  58.237 -        }
  58.238 -
  58.239 -        @Override
  58.240 -        public boolean isSafe() {
  58.241 -            return true;
  58.242 -        }
  58.243 -
  58.244 -        @Override
  58.245 -        public boolean isInteractive() {
  58.246 -            return false;
  58.247 -        }
  58.248 -    }
  58.249 -}
    59.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/SplitImports.java	Sat Sep 12 23:03:15 2015 -0700
    59.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.3 @@ -1,222 +0,0 @@
    59.4 -/*
    59.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    59.6 - *
    59.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    59.8 - *
    59.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   59.10 - * Other names may be trademarks of their respective owners.
   59.11 - *
   59.12 - * The contents of this file are subject to the terms of either the GNU
   59.13 - * General Public License Version 2 only ("GPL") or the Common
   59.14 - * Development and Distribution License("CDDL") (collectively, the
   59.15 - * "License"). You may not use this file except in compliance with the
   59.16 - * License. You can obtain a copy of the License at
   59.17 - * http://www.netbeans.org/cddl-gplv2.html
   59.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   59.19 - * specific language governing permissions and limitations under the
   59.20 - * License.  When distributing the software, include this License Header
   59.21 - * Notice in each file and include the License file at
   59.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   59.23 - * particular file as subject to the "Classpath" exception as provided
   59.24 - * by Oracle in the GPL Version 2 section of the License file that
   59.25 - * accompanied this code. If applicable, add the following below the
   59.26 - * License Header, with the fields enclosed by brackets [] replaced by
   59.27 - * your own identifying information:
   59.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   59.29 - *
   59.30 - * If you wish your version of this file to be governed by only the CDDL
   59.31 - * or only the GPL Version 2, indicate your decision by adding
   59.32 - * "[Contributor] elects to include this software in this distribution
   59.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   59.34 - * single choice of license, a recipient has the option to distribute
   59.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   59.36 - * to extend the choice of license to its licensees as provided above.
   59.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   59.38 - * Version 2 license, then the option applies only if the new code is
   59.39 - * made subject to such option by the copyright holder.
   59.40 - *
   59.41 - * Contributor(s):
   59.42 - *
   59.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   59.44 - */
   59.45 -package org.netbeans.modules.python.editor.hints;
   59.46 -
   59.47 -import java.util.ArrayList;
   59.48 -import java.util.Collections;
   59.49 -import java.util.List;
   59.50 -import java.util.Set;
   59.51 -import java.util.prefs.Preferences;
   59.52 -import javax.swing.JComponent;
   59.53 -import javax.swing.text.BadLocationException;
   59.54 -import org.netbeans.modules.python.editor.PythonAstUtils;
   59.55 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   59.56 -import org.netbeans.editor.BaseDocument;
   59.57 -import org.netbeans.editor.Utilities;
   59.58 -import org.netbeans.modules.csl.api.EditList;
   59.59 -import org.netbeans.modules.csl.api.Hint;
   59.60 -import org.netbeans.modules.csl.api.HintFix;
   59.61 -import org.netbeans.modules.csl.api.HintSeverity;
   59.62 -import org.netbeans.modules.csl.api.OffsetRange;
   59.63 -import org.netbeans.modules.csl.api.PreviewableFix;
   59.64 -import org.netbeans.modules.csl.api.RuleContext;
   59.65 -import org.netbeans.modules.csl.spi.GsfUtilities;
   59.66 -import org.netbeans.modules.editor.indent.api.IndentUtils;
   59.67 -import org.netbeans.modules.python.editor.PythonParserResult;
   59.68 -import org.netbeans.modules.python.editor.options.CodeStyle;
   59.69 -import org.openide.util.Exceptions;
   59.70 -import org.openide.util.NbBundle;
   59.71 -import org.python.antlr.PythonTree;
   59.72 -import org.python.antlr.ast.Import;
   59.73 -import org.python.antlr.ast.alias;
   59.74 -
   59.75 -/**
   59.76 - * Import statements should be one per line. This quickfix
   59.77 - * offers to make it so.
   59.78 - *
   59.79 - * @author Tor Norbye
   59.80 - */
   59.81 -public class SplitImports extends PythonAstRule {
   59.82 -    @Override
   59.83 -    public Set<Class> getKinds() {
   59.84 -        return Collections.singleton((Class)Import.class);
   59.85 -    }
   59.86 -
   59.87 -    @Override
   59.88 -    public void run(PythonRuleContext context, List<Hint> result) {
   59.89 -        Import imp = (Import)context.node;
   59.90 -        List<alias> names = imp.getInternalNames();
   59.91 -        if (names != null && names.size() > 1) {
   59.92 -            PythonTree node = context.node;
   59.93 -            PythonParserResult info = (PythonParserResult)context.parserResult;
   59.94 -            OffsetRange astOffsets = PythonAstUtils.getNameRange(info, node);
   59.95 -            OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
   59.96 -            BaseDocument doc = context.doc;
   59.97 -            try {
   59.98 -                if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
   59.99 -                        (context.caretOffset == -1 ||
  59.100 -                        Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
  59.101 -                    List<HintFix> fixList = new ArrayList<>();
  59.102 -                    fixList.add(new SplitImportsFix(context, imp));
  59.103 -                    String displayName = getDisplayName();
  59.104 -                    Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
  59.105 -                    result.add(desc);
  59.106 -                }
  59.107 -            } catch (BadLocationException ex) {
  59.108 -                Exceptions.printStackTrace(ex);
  59.109 -            }
  59.110 -        }
  59.111 -    }
  59.112 -
  59.113 -    @Override
  59.114 -    public String getId() {
  59.115 -        return "SplitImports"; // NOI18N
  59.116 -    }
  59.117 -
  59.118 -    @Override
  59.119 -    public String getDisplayName() {
  59.120 -        return NbBundle.getMessage(SplitImports.class, "SplitImports");
  59.121 -    }
  59.122 -
  59.123 -    @Override
  59.124 -    public String getDescription() {
  59.125 -        return NbBundle.getMessage(SplitImports.class, "SplitImportsDesc");
  59.126 -    }
  59.127 -
  59.128 -    @Override
  59.129 -    public boolean getDefaultEnabled() {
  59.130 -        return true;
  59.131 -    }
  59.132 -
  59.133 -    @Override
  59.134 -    public JComponent getCustomizer(Preferences node) {
  59.135 -        return null;
  59.136 -    }
  59.137 -
  59.138 -    @Override
  59.139 -    public boolean appliesTo(RuleContext context) {
  59.140 -        CodeStyle codeStyle = CodeStyle.getDefault(context.doc);
  59.141 -        return codeStyle == null || codeStyle.oneImportPerLine();
  59.142 -    }
  59.143 -
  59.144 -    @Override
  59.145 -    public boolean showInTasklist() {
  59.146 -        return true;
  59.147 -    }
  59.148 -
  59.149 -    @Override
  59.150 -    public HintSeverity getDefaultSeverity() {
  59.151 -        return HintSeverity.WARNING;
  59.152 -    }
  59.153 -
  59.154 -    private static class SplitImportsFix implements PreviewableFix {
  59.155 -        private final PythonRuleContext context;
  59.156 -        private final Import imp;
  59.157 -
  59.158 -        private SplitImportsFix(PythonRuleContext context, Import imp) {
  59.159 -            this.context = context;
  59.160 -            this.imp = imp;
  59.161 -        }
  59.162 -
  59.163 -        @Override
  59.164 -        public String getDescription() {
  59.165 -            return NbBundle.getMessage(SplitImports.class, "SplitImportsFix");
  59.166 -        }
  59.167 -
  59.168 -        @Override
  59.169 -        public boolean canPreview() {
  59.170 -            return true;
  59.171 -        }
  59.172 -
  59.173 -        @Override
  59.174 -        public EditList getEditList() throws Exception {
  59.175 -            BaseDocument doc = context.doc;
  59.176 -            EditList edits = new EditList(doc);
  59.177 -
  59.178 -            OffsetRange astRange = PythonAstUtils.getRange(imp);
  59.179 -            if (astRange != OffsetRange.NONE) {
  59.180 -                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets((PythonParserResult) context.parserResult, astRange);
  59.181 -                if (lexRange != OffsetRange.NONE) {
  59.182 -                    int indent = GsfUtilities.getLineIndent(doc, lexRange.getStart());
  59.183 -                    StringBuilder sb = new StringBuilder();
  59.184 -                    List<alias> names = imp.getInternalNames();
  59.185 -                    if (names != null) {
  59.186 -                        for (alias at : names) {
  59.187 -                            if (indent > 0 && sb.length() > 0) {
  59.188 -                                sb.append(IndentUtils.createIndentString(doc, indent));
  59.189 -                            }
  59.190 -                            sb.append("import "); // NOI18N
  59.191 -                            sb.append(at.getInternalName());
  59.192 -                            if (at.getInternalAsname() != null && at.getInternalAsname().length() > 0) {
  59.193 -                                sb.append(" as "); // NOI18N
  59.194 -                                sb.append(at.getInternalAsname());
  59.195 -                            }
  59.196 -                            sb.append("\n");
  59.197 -                        }
  59.198 -                    }
  59.199 -                    // Remove the final newline since Import doesn't include it
  59.200 -                    sb.setLength(sb.length() - 1);
  59.201 -
  59.202 -                    edits.replace(lexRange.getStart(), lexRange.getLength(), sb.toString(), false, 0);
  59.203 -                }
  59.204 -            }
  59.205 -
  59.206 -            return edits;
  59.207 -        }
  59.208 -
  59.209 -        @Override
  59.210 -        public void implement() throws Exception {
  59.211 -            EditList edits = getEditList();
  59.212 -            edits.apply();
  59.213 -        }
  59.214 -
  59.215 -        @Override
  59.216 -        public boolean isSafe() {
  59.217 -            return true;
  59.218 -        }
  59.219 -
  59.220 -        @Override
  59.221 -        public boolean isInteractive() {
  59.222 -            return false;
  59.223 -        }
  59.224 -    }
  59.225 -}
    60.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/SurroundWith.java	Sat Sep 12 23:03:15 2015 -0700
    60.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.3 @@ -1,377 +0,0 @@
    60.4 -/*
    60.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    60.6 - *
    60.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    60.8 - *
    60.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   60.10 - * Other names may be trademarks of their respective owners.
   60.11 - *
   60.12 - * The contents of this file are subject to the terms of either the GNU
   60.13 - * General Public License Version 2 only ("GPL") or the Common
   60.14 - * Development and Distribution License("CDDL") (collectively, the
   60.15 - * "License"). You may not use this file except in compliance with the
   60.16 - * License. You can obtain a copy of the License at
   60.17 - * http://www.netbeans.org/cddl-gplv2.html
   60.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   60.19 - * specific language governing permissions and limitations under the
   60.20 - * License.  When distributing the software, include this License Header
   60.21 - * Notice in each file and include the License file at
   60.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   60.23 - * particular file as subject to the "Classpath" exception as provided
   60.24 - * by Oracle in the GPL Version 2 section of the License file that
   60.25 - * accompanied this code. If applicable, add the following below the
   60.26 - * License Header, with the fields enclosed by brackets [] replaced by
   60.27 - * your own identifying information:
   60.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   60.29 - *
   60.30 - * Contributor(s):
   60.31 - *
   60.32 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
   60.33 - */
   60.34 -package org.netbeans.modules.python.editor.hints;
   60.35 -
   60.36 -import java.util.ArrayList;
   60.37 -import java.util.List;
   60.38 -import java.util.prefs.Preferences;
   60.39 -import javax.swing.JComponent;
   60.40 -import javax.swing.text.JTextComponent;
   60.41 -import javax.swing.text.Position;
   60.42 -import org.netbeans.editor.BaseDocument;
   60.43 -import org.netbeans.editor.Utilities;
   60.44 -import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager;
   60.45 -import org.netbeans.modules.csl.api.EditList;
   60.46 -import org.netbeans.modules.csl.api.Hint;
   60.47 -import org.netbeans.modules.csl.api.HintFix;
   60.48 -import org.netbeans.modules.csl.api.HintSeverity;
   60.49 -import org.netbeans.modules.csl.api.OffsetRange;
   60.50 -import org.netbeans.modules.csl.api.PreviewableFix;
   60.51 -import org.netbeans.modules.csl.api.RuleContext;
   60.52 -import org.netbeans.modules.csl.spi.GsfUtilities;
   60.53 -import org.netbeans.modules.editor.indent.api.IndentUtils;
   60.54 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   60.55 -import org.openide.util.Exceptions;
   60.56 -import org.openide.util.NbBundle;
   60.57 -import org.python.antlr.PythonTree;
   60.58 -import org.python.antlr.Visitor;
   60.59 -import org.python.antlr.ast.ClassDef;
   60.60 -import org.python.antlr.ast.FunctionDef;
   60.61 -import org.python.antlr.ast.Import;
   60.62 -import org.python.antlr.ast.ImportFrom;
   60.63 -
   60.64 -/**
   60.65 - * Offer to surround code with for example try/except/finally
   60.66 - *
   60.67 - * @author Tor Norbye
   60.68 - */
   60.69 -public class SurroundWith extends PythonSelectionRule {
   60.70 -    @Override
   60.71 -    protected int getApplicability(PythonRuleContext context, PythonTree root, OffsetRange astRange) {
   60.72 -        if (!ApplicabilityVisitor.applies(root, astRange)) {
   60.73 -            return 0;
   60.74 -        }
   60.75 -
   60.76 -        return 1;
   60.77 -    }
   60.78 -
   60.79 -    @Override
   60.80 -    public void run(PythonRuleContext context, List<Hint> result, OffsetRange range, int applicability) {
   60.81 -        int start = range.getStart();
   60.82 -        int end = range.getEnd();
   60.83 -
   60.84 -        // Adjust the fix range to be right around the dot so that the light bulb ends up
   60.85 -        // on the same line as the caret and alt-enter works
   60.86 -        JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
   60.87 -        if (target != null) {
   60.88 -            int dot = target.getCaret().getDot();
   60.89 -            range = new OffsetRange(dot, dot);
   60.90 -        }
   60.91 -
   60.92 -        List<HintFix> fixList = new ArrayList<>(3);
   60.93 -        fixList.add(new SurroundWithFix(context, start, end, false, true));
   60.94 -        fixList.add(new SurroundWithFix(context, start, end, true, true));
   60.95 -        fixList.add(new SurroundWithFix(context, start, end, true, false));
   60.96 -        String displayName = getDisplayName();
   60.97 -        Hint desc = new Hint(this, displayName, context.parserResult.getSnapshot().getSource().getFileObject(),
   60.98 -                range, fixList, 1500);
   60.99 -        result.add(desc);
  60.100 -    }
  60.101 -
  60.102 -    @Override
  60.103 -    public boolean appliesTo(RuleContext context) {
  60.104 -        return true;
  60.105 -    }
  60.106 -
  60.107 -    @Override
  60.108 -    public String getDisplayName() {
  60.109 -        return NbBundle.getMessage(SurroundWith.class, "SurroundWith");
  60.110 -    }
  60.111 -
  60.112 -    @Override
  60.113 -    public boolean showInTasklist() {
  60.114 -        return false;
  60.115 -    }
  60.116 -
  60.117 -    @Override
  60.118 -    public HintSeverity getDefaultSeverity() {
  60.119 -        return HintSeverity.CURRENT_LINE_WARNING;
  60.120 -    }
  60.121 -
  60.122 -    @Override
  60.123 -    public String getId() {
  60.124 -        return "SurroundWith"; // NOI18N
  60.125 -    }
  60.126 -
  60.127 -    @Override
  60.128 -    public String getDescription() {
  60.129 -        return "";
  60.130 -    }
  60.131 -
  60.132 -    @Override
  60.133 -    public boolean getDefaultEnabled() {
  60.134 -        return true;
  60.135 -    }
  60.136 -
  60.137 -    @Override
  60.138 -    public JComponent getCustomizer(Preferences node) {
  60.139 -        return null;
  60.140 -    }
  60.141 -
  60.142 -    private static class SurroundWithFix implements PreviewableFix {
  60.143 -        private final PythonRuleContext context;
  60.144 -        private final boolean includeFinally;
  60.145 -        private final boolean includeExcept;
  60.146 -        private Position startPos;
  60.147 -        private Position endPos;
  60.148 -        private Position codeTemplatePos;
  60.149 -        private String codeTemplateText;
  60.150 -        private final int start;
  60.151 -        private final int end;
  60.152 -
  60.153 -        private SurroundWithFix(PythonRuleContext context,
  60.154 -                int start, int end,
  60.155 -                boolean includeFinally, boolean includeExcept) {
  60.156 -            assert includeExcept || includeFinally;
  60.157 -
  60.158 -            this.context = context;
  60.159 -
  60.160 -            OffsetRange range = PythonLexerUtils.narrow(context.doc, new OffsetRange(start, end), false);
  60.161 -            this.start = range.getStart();
  60.162 -            this.end = range.getEnd();
  60.163 -            this.includeFinally = includeFinally;
  60.164 -            this.includeExcept = includeExcept;
  60.165 -        }
  60.166 -
  60.167 -        @Override
  60.168 -        public String getDescription() {
  60.169 -            if (includeExcept && includeFinally) {
  60.170 -                return NbBundle.getMessage(CreateDocString.class, "SurroundWithTEF");
  60.171 -            } else if (includeExcept) {
  60.172 -                return NbBundle.getMessage(CreateDocString.class, "SurroundWithTE");
  60.173 -            } else {
  60.174 -                assert includeFinally;
  60.175 -                return NbBundle.getMessage(CreateDocString.class, "SurroundWithTF");
  60.176 -            }
  60.177 -        }
  60.178 -
  60.179 -        @Override
  60.180 -        public boolean canPreview() {
  60.181 -            return true;
  60.182 -        }
  60.183 -
  60.184 -        @Override
  60.185 -        public EditList getEditList() throws Exception {
  60.186 -            return getEditList(true);
  60.187 -        }
  60.188 -
  60.189 -        private EditList getEditList(boolean previewOnly) throws Exception {
  60.190 -            BaseDocument doc = context.doc;
  60.191 -            EditList edits = new EditList(doc);
  60.192 -
  60.193 -            int indentSize = IndentUtils.indentLevelSize(doc);
  60.194 -            String oneIndent = IndentUtils.createIndentString(doc, indentSize);
  60.195 -            //int initialIndent = GsfUtilities.getLineIndent(doc, start);
  60.196 -            int lineStart = Utilities.getRowStart(doc, start);
  60.197 -            String initialIndentStr = IndentUtils.createIndentString(doc, IndentUtils.lineIndent(doc, lineStart));
  60.198 -            int nextLine = Utilities.getRowEnd(doc, end) + 1;
  60.199 -            if (nextLine > doc.getLength()) {
  60.200 -                nextLine = doc.getLength();
  60.201 -                edits.replace(nextLine, 0, "\n", false, 1);
  60.202 -            }
  60.203 -
  60.204 -            // Indent the selected lines
  60.205 -            edits.replace(lineStart, 0, initialIndentStr + "try:\n", false, 1);
  60.206 -            for (int offset = start; offset < end; offset = Utilities.getRowEnd(doc, offset) + 1) {
  60.207 -                edits.replace(offset, 0, oneIndent, false, 1);
  60.208 -            }
  60.209 -
  60.210 -            StringBuilder sb = new StringBuilder();
  60.211 -            if (includeExcept) {
  60.212 -                sb.append(initialIndentStr);
  60.213 -                sb.append("except ");
  60.214 -                if (!previewOnly) {
  60.215 -                    sb.append("${except default=\"");
  60.216 -                }
  60.217 -                sb.append("Exception, e");
  60.218 -                if (!previewOnly) {
  60.219 -                    sb.append("\"}");
  60.220 -                }
  60.221 -                sb.append(":\n");
  60.222 -                sb.append(initialIndentStr);
  60.223 -                sb.append(oneIndent);
  60.224 -                int caretDelta = sb.length();
  60.225 -                startPos = edits.createPosition(nextLine + caretDelta);
  60.226 -                if (!previewOnly) {
  60.227 -                    sb.append("${action default=\"");
  60.228 -                }
  60.229 -                sb.append("print \"Exception: \", e");
  60.230 -                if (!previewOnly) {
  60.231 -                    sb.append("\"}");
  60.232 -                }
  60.233 -                caretDelta = sb.length();
  60.234 -                endPos = edits.createPosition(nextLine + caretDelta);
  60.235 -                sb.append("\n");
  60.236 -                if (!previewOnly && !includeExcept) {
  60.237 -                    sb.append("${cursor}");
  60.238 -                }
  60.239 -            }
  60.240 -            if (includeFinally) {
  60.241 -                sb.append(initialIndentStr);
  60.242 -                sb.append("finally:\n");
  60.243 -                sb.append(initialIndentStr);
  60.244 -                sb.append(oneIndent);
  60.245 -                if (!previewOnly) {
  60.246 -                    sb.append("${finally default=\"\"}\n${cursor}");
  60.247 -                }
  60.248 -                int caretDelta = sb.length();
  60.249 -                if (!includeExcept) {
  60.250 -                    endPos = startPos = edits.createPosition(nextLine + caretDelta);
  60.251 -                }
  60.252 -                sb.append("\n");
  60.253 -            }
  60.254 -            if (previewOnly) {
  60.255 -                edits.replace(nextLine, 0, sb.toString(), false, 1);
  60.256 -            } else {
  60.257 -                codeTemplatePos = edits.createPosition(nextLine, Position.Bias.Backward);
  60.258 -                codeTemplateText = sb.toString();
  60.259 -            }
  60.260 -
  60.261 -            return edits;
  60.262 -        }
  60.263 -
  60.264 -        @Override
  60.265 -        public void implement() throws Exception {
  60.266 -            EditList edits = getEditList(true);
  60.267 -
  60.268 -            JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
  60.269 -            edits.apply();
  60.270 -            if (target != null) {
  60.271 -                if (codeTemplateText != null && codeTemplatePos != null) {
  60.272 -                    final CodeTemplateManager ctm = CodeTemplateManager.get(context.doc);
  60.273 -                    if (ctm != null) {
  60.274 -                        target.getCaret().setDot(codeTemplatePos.getOffset());
  60.275 -                        ctm.createTemporary(codeTemplateText).insert(target);
  60.276 -                    }
  60.277 -                } else if (startPos != null && endPos != null) {
  60.278 -                    target.setSelectionStart(startPos.getOffset());
  60.279 -                    target.setSelectionEnd(endPos.getOffset());
  60.280 -                }
  60.281 -            }
  60.282 -        }
  60.283 -
  60.284 -        @Override
  60.285 -        public boolean isSafe() {
  60.286 -            return true;
  60.287 -        }
  60.288 -
  60.289 -        @Override
  60.290 -        public boolean isInteractive() {
  60.291 -            return false;
  60.292 -        }
  60.293 -    }
  60.294 -
  60.295 -    /** @todo Prune search in traverse, ala AstPath.
  60.296 -     *  @todo Build up start and end AstPaths.
  60.297 -     */
  60.298 -    private static class ApplicabilityVisitor extends Visitor {
  60.299 -        private boolean applies = true;
  60.300 -        private final int start;
  60.301 -        private final int end;
  60.302 -
  60.303 -        static boolean applies(PythonTree root, OffsetRange astRange) {
  60.304 -            ApplicabilityVisitor visitor = new ApplicabilityVisitor(astRange);
  60.305 -            try {
  60.306 -                visitor.visit(root);
  60.307 -            } catch (Exception ex) {
  60.308 -                Exceptions.printStackTrace(ex);
  60.309 -                return false;
  60.310 -            }
  60.311 -            return visitor.isApplicable();
  60.312 -        }
  60.313 -
  60.314 -        ApplicabilityVisitor(OffsetRange astRange) {
  60.315 -            this.start = astRange.getStart();
  60.316 -            this.end = astRange.getEnd();
  60.317 -        }
  60.318 -
  60.319 -        public boolean isApplicable() {
  60.320 -            return applies;
  60.321 -        }
  60.322 -
  60.323 -        private void maybeBail(PythonTree node) {
  60.324 -            int nodeStart = node.getCharStartIndex();
  60.325 -            int nodeEnd = node.getCharStopIndex();
  60.326 -            if (nodeStart >= start && nodeStart < end) {
  60.327 -                applies = false;
  60.328 -            }
  60.329 -            if (nodeEnd > start && nodeEnd < end) {
  60.330 -                applies = false;
  60.331 -            }
  60.332 -        }
  60.333 -
  60.334 -        @Override
  60.335 -        public void traverse(PythonTree node) throws Exception {
  60.336 -            if (!applies) {
  60.337 -                return;
  60.338 -            }
  60.339 -
  60.340 -            int nodeStart = node.getCharStartIndex();
  60.341 -            int nodeStop = node.getCharStopIndex();
  60.342 -            //if (!(nodeStop < start || nodeStart > end)) {
  60.343 -            if (nodeStop >= start && nodeStart <= end) {
  60.344 -                super.traverse(node);
  60.345 -            }
  60.346 -        }
  60.347 -
  60.348 -        @Override
  60.349 -        public Object visitClassDef(ClassDef node) throws Exception {
  60.350 -            maybeBail(node);
  60.351 -            return super.visitClassDef(node);
  60.352 -        }
  60.353 -
  60.354 -        @Override
  60.355 -        public Object visitFunctionDef(FunctionDef node) throws Exception {
  60.356 -            maybeBail(node);
  60.357 -            return super.visitFunctionDef(node);
  60.358 -        }
  60.359 -
  60.360 -        @Override
  60.361 -        public Object visitImport(Import node) throws Exception {
  60.362 -            maybeBail(node);
  60.363 -            return super.visitImport(node);
  60.364 -        }
  60.365 -
  60.366 -        @Override
  60.367 -        public Object visitImportFrom(ImportFrom node) throws Exception {
  60.368 -            maybeBail(node);
  60.369 -            return super.visitImportFrom(node);
  60.370 -        }
  60.371 -
  60.372 -        // Module is okay - you get this when you select all text in a simple "script" file
  60.373 -        // with only statements
  60.374 -        //@Override
  60.375 -        //public Object visitModule(Module node) throws Exception {
  60.376 -        //    maybeBail(node);
  60.377 -        //    return super.visitModule(node);
  60.378 -        //}
  60.379 -    }
  60.380 -}
    61.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/UnresolvedClassComponents.java	Sat Sep 12 23:03:15 2015 -0700
    61.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.3 @@ -1,207 +0,0 @@
    61.4 -/*
    61.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    61.6 - *
    61.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    61.8 - *
    61.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   61.10 - * Other names may be trademarks of their respective owners.
   61.11 - *
   61.12 - * The contents of this file are subject to the terms of either the GNU
   61.13 - * General Public License Version 2 only ("GPL") or the Common
   61.14 - * Development and Distribution License("CDDL") (collectively, the
   61.15 - * "License"). You may not use this file except in compliance with the
   61.16 - * License. You can obtain a copy of the License at
   61.17 - * http://www.netbeans.org/cddl-gplv2.html
   61.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   61.19 - * specific language governing permissions and limitations under the
   61.20 - * License.  When distributing the software, include this License Header
   61.21 - * Notice in each file and include the License file at
   61.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   61.23 - * particular file as subject to the "Classpath" exception as provided
   61.24 - * by Oracle in the GPL Version 2 section of the License file that
   61.25 - * accompanied this code. If applicable, add the following below the
   61.26 - * License Header, with the fields enclosed by brackets [] replaced by
   61.27 - * your own identifying information:
   61.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   61.29 - *
   61.30 - * If you wish your version of this file to be governed by only the CDDL
   61.31 - * or only the GPL Version 2, indicate your decision by adding
   61.32 - * "[Contributor] elects to include this software in this distribution
   61.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   61.34 - * single choice of license, a recipient has the option to distribute
   61.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   61.36 - * to extend the choice of license to its licensees as provided above.
   61.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   61.38 - * Version 2 license, then the option applies only if the new code is
   61.39 - * made subject to such option by the copyright holder.
   61.40 - *
   61.41 - * Contributor(s):
   61.42 - *
   61.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   61.44 - */
   61.45 -package org.netbeans.modules.python.editor.hints;
   61.46 -
   61.47 -import java.util.Collections;
   61.48 -import java.util.List;
   61.49 -import java.util.Set;
   61.50 -import java.util.prefs.Preferences;
   61.51 -import javax.swing.JComponent;
   61.52 -import org.netbeans.modules.csl.api.Hint;
   61.53 -import org.netbeans.modules.csl.api.HintFix;
   61.54 -import org.netbeans.modules.csl.api.HintSeverity;
   61.55 -import org.netbeans.modules.csl.api.OffsetRange;
   61.56 -import org.netbeans.modules.csl.api.RuleContext;
   61.57 -import org.netbeans.modules.python.editor.PythonAstUtils;
   61.58 -import org.netbeans.modules.python.editor.PythonParserResult;
   61.59 -import org.netbeans.modules.python.editor.imports.ImportManager;
   61.60 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   61.61 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
   61.62 -import org.openide.util.NbBundle;
   61.63 -import org.python.antlr.PythonTree;
   61.64 -import org.python.antlr.ast.Module;
   61.65 -
   61.66 -/**
   61.67 - * Detect Unresolved class attributes
   61.68 - *
   61.69 - * @author Jean-Yves Mengant
   61.70 - */
   61.71 -public class UnresolvedClassComponents extends PythonAstRule {
   61.72 -
   61.73 -    private final static String CLASS_UNRESOLVED_ATTRIBUTES = "UnresolvedAttributes";
   61.74 -    private final static String CLASS_UNRESOLVED_INHERITANCE_VAR = "UnresolvedInheritanceVariable";
   61.75 -    private final static String CLASS_UNRESOLVED_ATTRIBUTES_VAR = "UnresolvedAttributesVariable";
   61.76 -    private final static String CLASS_UNRESOLVED_ATTRIBUTES_DESC = "UnresolvedAttributesDesc";
   61.77 -
   61.78 -
   61.79 -
   61.80 -    public UnresolvedClassComponents() {
   61.81 -    }
   61.82 -
   61.83 -    @Override
   61.84 -    public boolean appliesTo(RuleContext context) {
   61.85 -        return true;
   61.86 -    }
   61.87 -
   61.88 -    @Override
   61.89 -    public Set<Class> getKinds() {
   61.90 -        return Collections.<Class>singleton(Module.class);
   61.91 -    }
   61.92 -
   61.93 -    private void populateMessages( PythonParserResult info, List<PythonTree> unresolved , List<Hint> result ,boolean isClass ) {
   61.94 -        if (unresolved.size() > 0) {
   61.95 -
   61.96 -            for (PythonTree node : unresolved) {
   61.97 -                // Compute suggestions
   61.98 -                String name = PythonAstUtils.getName(node);
   61.99 -                if (name == null) {
  61.100 -                    name = "";
  61.101 -                }
  61.102 -                List<HintFix> fixList = Collections.emptyList();
  61.103 -                String message ;
  61.104 -                if ( isClass)
  61.105 -                  message = NbBundle.getMessage(NameRule.class, CLASS_UNRESOLVED_INHERITANCE_VAR, name);
  61.106 -                else
  61.107 -                  message = NbBundle.getMessage(NameRule.class, CLASS_UNRESOLVED_ATTRIBUTES_VAR, name);
  61.108 -                OffsetRange range = PythonAstUtils.getRange( node);
  61.109 -                range = PythonLexerUtils.getLexerOffsets(info, range);
  61.110 -                if (range != OffsetRange.NONE) {
  61.111 -                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
  61.112 -                    result.add(desc);
  61.113 -                }
  61.114 -            }
  61.115 -        }
  61.116 -    }
  61.117 -
  61.118 -
  61.119 -    @Override
  61.120 -    public void run(PythonRuleContext context, List<Hint> result) {
  61.121 -        PythonParserResult info = (PythonParserResult) context.parserResult;
  61.122 -        SymbolTable symbolTable = info.getSymbolTable();
  61.123 -
  61.124 -        List<PythonTree> unresolvedAttributes = symbolTable.getUnresolvedAttributes(info);
  61.125 -        populateMessages(info,unresolvedAttributes,result,false) ;
  61.126 -        List<PythonTree> unresolvedParents = symbolTable.getUnresolvedParents(info);
  61.127 -        populateMessages(info,unresolvedParents,result,true) ;
  61.128 -    }
  61.129 -
  61.130 -    @Override
  61.131 -    public String getId() {
  61.132 -        return CLASS_UNRESOLVED_ATTRIBUTES; // NOI18N
  61.133 -    }
  61.134 -
  61.135 -    @Override
  61.136 -    public String getDisplayName() {
  61.137 -        return NbBundle.getMessage(NameRule.class, CLASS_UNRESOLVED_ATTRIBUTES);
  61.138 -    }
  61.139 -
  61.140 -    @Override
  61.141 -    public String getDescription() {
  61.142 -        return NbBundle.getMessage(NameRule.class, CLASS_UNRESOLVED_ATTRIBUTES_DESC);
  61.143 -    }
  61.144 -
  61.145 -    @Override
  61.146 -    public boolean getDefaultEnabled() {
  61.147 -        return false;
  61.148 -    }
  61.149 -
  61.150 -    @Override
  61.151 -    public boolean showInTasklist() {
  61.152 -        return true;
  61.153 -    }
  61.154 -
  61.155 -    @Override
  61.156 -    public HintSeverity getDefaultSeverity() {
  61.157 -        return HintSeverity.ERROR;
  61.158 -    }
  61.159 -
  61.160 -    @Override
  61.161 -    public JComponent getCustomizer(Preferences node) {
  61.162 -        return null;
  61.163 -    }
  61.164 -
  61.165 -    private static class ImportFix implements HintFix {
  61.166 -        private final PythonRuleContext context;
  61.167 -        private final PythonTree node;
  61.168 -        private final String module;
  61.169 -
  61.170 -        private ImportFix(PythonRuleContext context, PythonTree node, String module) {
  61.171 -            this.context = context;
  61.172 -            this.node = node;
  61.173 -            this.module = module;
  61.174 -        }
  61.175 -
  61.176 -        @Override
  61.177 -        public String getDescription() {
  61.178 -            return NbBundle.getMessage(CreateDocString.class, "FixImport", module);
  61.179 -        }
  61.180 -
  61.181 -        @Override
  61.182 -        public void implement() throws Exception {
  61.183 -            String mod = this.module;
  61.184 -            String symbol = null;
  61.185 -            int colon = mod.indexOf(':');
  61.186 -            if (colon != -1) {
  61.187 -                int end = mod.indexOf('(', colon + 1);
  61.188 -                if (end == -1) {
  61.189 -                    end = mod.indexOf(';', colon + 1);
  61.190 -                    if (end == -1) {
  61.191 -                        end = mod.length();
  61.192 -                    }
  61.193 -                }
  61.194 -                symbol = mod.substring(colon + 1, end).trim();
  61.195 -                mod = mod.substring(0, colon).trim();
  61.196 -            }
  61.197 -            new ImportManager((PythonParserResult) context.parserResult).ensureImported(mod, symbol, false, false, true);
  61.198 -        }
  61.199 -
  61.200 -        @Override
  61.201 -        public boolean isSafe() {
  61.202 -            return true;
  61.203 -        }
  61.204 -
  61.205 -        @Override
  61.206 -        public boolean isInteractive() {
  61.207 -            return false;
  61.208 -        }
  61.209 -    }
  61.210 -}
    62.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/UnresolvedDetector.java	Sat Sep 12 23:03:15 2015 -0700
    62.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.3 @@ -1,228 +0,0 @@
    62.4 -/*
    62.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    62.6 - *
    62.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    62.8 - *
    62.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   62.10 - * Other names may be trademarks of their respective owners.
   62.11 - *
   62.12 - * The contents of this file are subject to the terms of either the GNU
   62.13 - * General Public License Version 2 only ("GPL") or the Common
   62.14 - * Development and Distribution License("CDDL") (collectively, the
   62.15 - * "License"). You may not use this file except in compliance with the
   62.16 - * License. You can obtain a copy of the License at
   62.17 - * http://www.netbeans.org/cddl-gplv2.html
   62.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   62.19 - * specific language governing permissions and limitations under the
   62.20 - * License.  When distributing the software, include this License Header
   62.21 - * Notice in each file and include the License file at
   62.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   62.23 - * particular file as subject to the "Classpath" exception as provided
   62.24 - * by Oracle in the GPL Version 2 section of the License file that
   62.25 - * accompanied this code. If applicable, add the following below the
   62.26 - * License Header, with the fields enclosed by brackets [] replaced by
   62.27 - * your own identifying information:
   62.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   62.29 - *
   62.30 - * If you wish your version of this file to be governed by only the CDDL
   62.31 - * or only the GPL Version 2, indicate your decision by adding
   62.32 - * "[Contributor] elects to include this software in this distribution
   62.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   62.34 - * single choice of license, a recipient has the option to distribute
   62.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   62.36 - * to extend the choice of license to its licensees as provided above.
   62.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   62.38 - * Version 2 license, then the option applies only if the new code is
   62.39 - * made subject to such option by the copyright holder.
   62.40 - *
   62.41 - * Contributor(s):
   62.42 - *
   62.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   62.44 - */
   62.45 -package org.netbeans.modules.python.editor.hints;
   62.46 -
   62.47 -import java.util.ArrayList;
   62.48 -import java.util.Collections;
   62.49 -import java.util.List;
   62.50 -import java.util.Set;
   62.51 -import java.util.prefs.Preferences;
   62.52 -import javax.swing.JComponent;
   62.53 -import org.netbeans.modules.csl.api.Hint;
   62.54 -import org.netbeans.modules.csl.api.HintFix;
   62.55 -import org.netbeans.modules.csl.api.HintSeverity;
   62.56 -import org.netbeans.modules.csl.api.OffsetRange;
   62.57 -import org.netbeans.modules.csl.api.RuleContext;
   62.58 -import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
   62.59 -import org.netbeans.modules.python.editor.PythonAstUtils;
   62.60 -import org.netbeans.modules.python.editor.PythonIndex;
   62.61 -import org.netbeans.modules.python.editor.PythonParserResult;
   62.62 -import org.netbeans.modules.python.editor.elements.IndexedElement;
   62.63 -import org.netbeans.modules.python.editor.imports.ImportManager;
   62.64 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   62.65 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   62.66 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
   62.67 -import org.openide.util.NbBundle;
   62.68 -import org.python.antlr.PythonTree;
   62.69 -import org.python.antlr.ast.Attribute;
   62.70 -import org.python.antlr.ast.Call;
   62.71 -import org.python.antlr.ast.Module;
   62.72 -
   62.73 -/**
   62.74 - * Detect Unresolved variables
   62.75 - *
   62.76 - * @author Tor Norbye
   62.77 - */
   62.78 -public class UnresolvedDetector extends PythonAstRule {
   62.79 -    public UnresolvedDetector() {
   62.80 -    }
   62.81 -
   62.82 -    @Override
   62.83 -    public boolean appliesTo(RuleContext context) {
   62.84 -        return true;
   62.85 -    }
   62.86 -
   62.87 -    @Override
   62.88 -    public Set<Class> getKinds() {
   62.89 -        return Collections.<Class>singleton(Module.class);
   62.90 -    }
   62.91 -
   62.92 -    @Override
   62.93 -    public void run(PythonRuleContext context, List<Hint> result) {
   62.94 -        PythonParserResult info = (PythonParserResult) context.parserResult;
   62.95 -        SymbolTable symbolTable = info.getSymbolTable();
   62.96 -
   62.97 -        List<PythonTree> unresolvedNames = symbolTable.getUnresolved(info);
   62.98 -        if (unresolvedNames.size() > 0) {
   62.99 -            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
  62.100 -
  62.101 -            for (PythonTree node : unresolvedNames) {
  62.102 -                // Compute suggestions
  62.103 -                String name = PythonAstUtils.getName(node);
  62.104 -                if (name == null) {
  62.105 -                    name = "";
  62.106 -                }
  62.107 -                List<HintFix> fixList = new ArrayList<>(3);
  62.108 -                // Is is a reference to a module?
  62.109 -                boolean tryModule = false;
  62.110 -                if (node.getParent() instanceof Call) {
  62.111 -                    Call call = (Call)node.getParent();
  62.112 -                    PythonTree t = call.getInternalFunc();
  62.113 -                    if (t instanceof Attribute) {
  62.114 -                        tryModule = true;
  62.115 -                    }
  62.116 -                }
  62.117 -                String message = NbBundle.getMessage(NameRule.class, "UnresolvedVariable", name);
  62.118 -                if (name.equals("true")) { // NOI18N
  62.119 -                    // Help for new language converts...
  62.120 -                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "True"); // NOI18N
  62.121 -                } else if (name.equals("false")) {
  62.122 -                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "False"); // NOI18N
  62.123 -                } else if (name.equals("nil") || name.equals("null")) {
  62.124 -                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "None"); // NOI18N
  62.125 -                } else if (name.equals("this")) {
  62.126 -                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "self"); // NOI18N
  62.127 -                } else if (tryModule) {
  62.128 -                    Set<IndexedElement> moduleElements = index.getModules(name, QuerySupport.Kind.EXACT);
  62.129 -                    if (moduleElements.size() > 0) {
  62.130 -                        fixList.add(new ImportFix(context, node, name));
  62.131 -                    }
  62.132 -                } else {
  62.133 -                    Set<String> modules = index.getImportsFor(name, true);
  62.134 -                    if (modules.size() > 0) {
  62.135 -                        for (String module : modules) {
  62.136 -                            fixList.add(new ImportFix(context, node, module));
  62.137 -                        }
  62.138 -                    }
  62.139 -                }
  62.140 -
  62.141 -                OffsetRange range = PythonAstUtils.getNameRange(info, node);
  62.142 -                range = PythonLexerUtils.getLexerOffsets(info, range);
  62.143 -                if (range != OffsetRange.NONE) {
  62.144 -                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
  62.145 -                    result.add(desc);
  62.146 -                }
  62.147 -            }
  62.148 -        }
  62.149 -    }
  62.150 -
  62.151 -    @Override
  62.152 -    public String getId() {
  62.153 -        return "Unresolved"; // NOI18N
  62.154 -    }
  62.155 -
  62.156 -    @Override
  62.157 -    public String getDisplayName() {
  62.158 -        return NbBundle.getMessage(NameRule.class, "Unresolved");
  62.159 -    }
  62.160 -
  62.161 -    @Override
  62.162 -    public String getDescription() {
  62.163 -        return NbBundle.getMessage(NameRule.class, "UnresolvedDesc");
  62.164 -    }
  62.165 -
  62.166 -    @Override
  62.167 -    public boolean getDefaultEnabled() {
  62.168 -        return false;
  62.169 -    }
  62.170 -
  62.171 -    @Override
  62.172 -    public boolean showInTasklist() {
  62.173 -        return true;
  62.174 -    }
  62.175 -
  62.176 -    @Override
  62.177 -    public HintSeverity getDefaultSeverity() {
  62.178 -        return HintSeverity.ERROR;
  62.179 -    }
  62.180 -
  62.181 -    @Override
  62.182 -    public JComponent getCustomizer(Preferences node) {
  62.183 -        return null;
  62.184 -    }
  62.185 -
  62.186 -    private static class ImportFix implements HintFix {
  62.187 -        private final PythonRuleContext context;
  62.188 -        private final PythonTree node;
  62.189 -        private final String module;
  62.190 -
  62.191 -        private ImportFix(PythonRuleContext context, PythonTree node, String module) {
  62.192 -            this.context = context;
  62.193 -            this.node = node;
  62.194 -            this.module = module;
  62.195 -        }
  62.196 -
  62.197 -        @Override
  62.198 -        public String getDescription() {
  62.199 -            return NbBundle.getMessage(CreateDocString.class, "FixImport", module);
  62.200 -        }
  62.201 -
  62.202 -        @Override
  62.203 -        public void implement() throws Exception {
  62.204 -            String mod = this.module;
  62.205 -            String symbol = null;
  62.206 -            int colon = mod.indexOf(':');
  62.207 -            if (colon != -1) {
  62.208 -                int end = mod.indexOf('(', colon + 1);
  62.209 -                if (end == -1) {
  62.210 -                    end = mod.indexOf(';', colon + 1);
  62.211 -                    if (end == -1) {
  62.212 -                        end = mod.length();
  62.213 -                    }
  62.214 -                }
  62.215 -                symbol = mod.substring(colon + 1, end).trim();
  62.216 -                mod = mod.substring(0, colon).trim();
  62.217 -            }
  62.218 -            new ImportManager((PythonParserResult) context.parserResult).ensureImported(mod, symbol, false, false, true);
  62.219 -        }
  62.220 -
  62.221 -        @Override
  62.222 -        public boolean isSafe() {
  62.223 -            return true;
  62.224 -        }
  62.225 -
  62.226 -        @Override
  62.227 -        public boolean isInteractive() {
  62.228 -            return false;
  62.229 -        }
  62.230 -    }
  62.231 -}
    63.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/UnusedDetector.java	Sat Sep 12 23:03:15 2015 -0700
    63.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.3 @@ -1,244 +0,0 @@
    63.4 -/*
    63.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    63.6 - *
    63.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    63.8 - *
    63.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   63.10 - * Other names may be trademarks of their respective owners.
   63.11 - *
   63.12 - * The contents of this file are subject to the terms of either the GNU
   63.13 - * General Public License Version 2 only ("GPL") or the Common
   63.14 - * Development and Distribution License("CDDL") (collectively, the
   63.15 - * "License"). You may not use this file except in compliance with the
   63.16 - * License. You can obtain a copy of the License at
   63.17 - * http://www.netbeans.org/cddl-gplv2.html
   63.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   63.19 - * specific language governing permissions and limitations under the
   63.20 - * License.  When distributing the software, include this License Header
   63.21 - * Notice in each file and include the License file at
   63.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   63.23 - * particular file as subject to the "Classpath" exception as provided
   63.24 - * by Oracle in the GPL Version 2 section of the License file that
   63.25 - * accompanied this code. If applicable, add the following below the
   63.26 - * License Header, with the fields enclosed by brackets [] replaced by
   63.27 - * your own identifying information:
   63.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   63.29 - *
   63.30 - * If you wish your version of this file to be governed by only the CDDL
   63.31 - * or only the GPL Version 2, indicate your decision by adding
   63.32 - * "[Contributor] elects to include this software in this distribution
   63.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   63.34 - * single choice of license, a recipient has the option to distribute
   63.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   63.36 - * to extend the choice of license to its licensees as provided above.
   63.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   63.38 - * Version 2 license, then the option applies only if the new code is
   63.39 - * made subject to such option by the copyright holder.
   63.40 - *
   63.41 - * Contributor(s):
   63.42 - *
   63.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   63.44 - */
   63.45 -package org.netbeans.modules.python.editor.hints;
   63.46 -
   63.47 -import java.util.ArrayList;
   63.48 -import java.util.Collections;
   63.49 -import java.util.HashSet;
   63.50 -import java.util.List;
   63.51 -import java.util.Set;
   63.52 -import java.util.prefs.Preferences;
   63.53 -import javax.swing.JComponent;
   63.54 -import org.netbeans.modules.csl.api.Hint;
   63.55 -import org.netbeans.modules.csl.api.HintFix;
   63.56 -import org.netbeans.modules.csl.api.HintSeverity;
   63.57 -import org.netbeans.modules.csl.api.OffsetRange;
   63.58 -import org.netbeans.modules.csl.api.RuleContext;
   63.59 -import org.netbeans.modules.python.editor.PythonAstUtils;
   63.60 -import org.netbeans.modules.python.editor.PythonParserResult;
   63.61 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   63.62 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
   63.63 -import org.openide.util.NbBundle;
   63.64 -import org.python.antlr.PythonTree;
   63.65 -import org.python.antlr.ast.Assign;
   63.66 -import org.python.antlr.ast.For;
   63.67 -import org.python.antlr.ast.Module;
   63.68 -import org.python.antlr.ast.Tuple;
   63.69 -import org.python.antlr.base.expr;
   63.70 -
   63.71 -/**
   63.72 - * Detect unused variables
   63.73 - *
   63.74 - * @todo Find a more reliable way of detecting return tuples without relying on the
   63.75 - *  parent reference
   63.76 - *
   63.77 - * @author Tor Norbye
   63.78 - */
   63.79 -public class UnusedDetector extends PythonAstRule {
   63.80 -    /** Default names ignored */
   63.81 -    private static final String DEFAULT_IGNORED_NAMES = "_, dummy";
   63.82 -    private static final String PARAMS_KEY = "params"; // NOI18N
   63.83 -    private static final String SKIP_TUPLE_ASSIGN_KEY = "skipTuples"; // NOI18N
   63.84 -    private static final String IGNORED_KEY = "ignorednames"; // NOI18N
   63.85 -
   63.86 -    public UnusedDetector() {
   63.87 -    }
   63.88 -
   63.89 -    @Override
   63.90 -    public boolean appliesTo(RuleContext context) {
   63.91 -        return true;
   63.92 -    }
   63.93 -
   63.94 -    @Override
   63.95 -    public Set<Class> getKinds() {
   63.96 -        return Collections.<Class>singleton(Module.class);
   63.97 -    }
   63.98 -
   63.99 -    @Override
  63.100 -    public void run(PythonRuleContext context, List<Hint> result) {
  63.101 -        PythonParserResult info = (PythonParserResult) context.parserResult;
  63.102 -        SymbolTable symbolTable = info.getSymbolTable();
  63.103 -
  63.104 -        boolean skipParams = true;
  63.105 -        Preferences pref = context.manager.getPreferences(this);
  63.106 -        if (pref != null) {
  63.107 -            skipParams = getSkipParameters(pref);
  63.108 -        }
  63.109 -
  63.110 -        List<PythonTree> unusedNames = symbolTable.getUnused(true, skipParams);
  63.111 -        if (unusedNames.size() == 0) {
  63.112 -            return;
  63.113 -        }
  63.114 -
  63.115 -        boolean skipTupleAssigns = true;
  63.116 -        Set<String> ignoreNames = Collections.emptySet();
  63.117 -        if (pref != null) {
  63.118 -            skipParams = getSkipParameters(pref);
  63.119 -            skipTupleAssigns = getSkipTupleAssignments(pref);
  63.120 -            String ignoreNamesStr = getIgnoreNames(pref);
  63.121 -            if (ignoreNamesStr.length() > 0) {
  63.122 -                ignoreNames = new HashSet<>();
  63.123 -                for (String s : ignoreNamesStr.split(",")) { // NOI18N
  63.124 -                    ignoreNames.add(s.trim());
  63.125 -                }
  63.126 -            }
  63.127 -        }
  63.128 -
  63.129 -        for (PythonTree node : unusedNames) {
  63.130 -            if (skipTupleAssigns && isTupleAssignment(node)) {
  63.131 -                continue;
  63.132 -            }
  63.133 -            String name = PythonAstUtils.getName(node);
  63.134 -            if (name == null) {
  63.135 -                name = "";
  63.136 -            }
  63.137 -            if (ignoreNames.contains(name)) {
  63.138 -                continue;
  63.139 -            }
  63.140 -            OffsetRange range = PythonAstUtils.getNameRange(info, node);
  63.141 -            range = PythonLexerUtils.getLexerOffsets(info, range);
  63.142 -            if (range != OffsetRange.NONE) {
  63.143 -                List<HintFix> fixList = new ArrayList<>(3);
  63.144 -                String message = NbBundle.getMessage(NameRule.class, "UnusedVariable", name);
  63.145 -                Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
  63.146 -                result.add(desc);
  63.147 -            }
  63.148 -        }
  63.149 -    }
  63.150 -
  63.151 -    private boolean isTupleAssignment(PythonTree node) {
  63.152 -        // This may not work right since the parent pointers often aren't set right;
  63.153 -        // find a more efficient way to do it correctly than a path search for each node
  63.154 -        if (node.getParent() instanceof Tuple) {
  63.155 -            // Allow tuples in tuples
  63.156 -            PythonTree parentParent = node.getParent().getParent();
  63.157 -            while (parentParent instanceof Tuple) {
  63.158 -                parentParent = parentParent.getParent();
  63.159 -                node = node.getParent();
  63.160 -            }
  63.161 -            if (parentParent instanceof Assign) {
  63.162 -                Assign assign = (Assign)parentParent;
  63.163 -                List<expr> targets = assign.getInternalTargets();
  63.164 -                if (targets != null && targets.size() > 0 && targets.get(0) == node.getParent()) {
  63.165 -                    return true;
  63.166 -                }
  63.167 -            }
  63.168 -            if (parentParent instanceof For &&
  63.169 -                    ((For)parentParent).getInternalTarget() == node.getParent()) {
  63.170 -                return true;
  63.171 -            }
  63.172 -        }
  63.173 -
  63.174 -        return false;
  63.175 -    }
  63.176 -
  63.177 -    @Override
  63.178 -    public String getId() {
  63.179 -        return "Unused"; // NOI18N
  63.180 -    }
  63.181 -
  63.182 -    @Override
  63.183 -    public String getDisplayName() {
  63.184 -        return NbBundle.getMessage(NameRule.class, "Unused");
  63.185 -    }
  63.186 -
  63.187 -    @Override
  63.188 -    public String getDescription() {
  63.189 -        return NbBundle.getMessage(NameRule.class, "UnusedDesc");
  63.190 -    }
  63.191 -
  63.192 -    @Override
  63.193 -    public boolean getDefaultEnabled() {
  63.194 -        return true;
  63.195 -    }
  63.196 -
  63.197 -    @Override
  63.198 -    public boolean showInTasklist() {
  63.199 -        return true;
  63.200 -    }
  63.201 -
  63.202 -    @Override
  63.203 -    public HintSeverity getDefaultSeverity() {
  63.204 -        return HintSeverity.WARNING;
  63.205 -    }
  63.206 -
  63.207 -    @Override
  63.208 -    public JComponent getCustomizer(Preferences node) {
  63.209 -        return new UnusedDetectorPrefs(node);
  63.210 -    }
  63.211 -
  63.212 -    static boolean getSkipParameters(Preferences prefs) {
  63.213 -        return prefs.getBoolean(PARAMS_KEY, true);
  63.214 -    }
  63.215 -
  63.216 -    static void setSkipParameters(Preferences prefs, boolean skipParams) {
  63.217 -        if (skipParams) {
  63.218 -            prefs.remove(PARAMS_KEY);
  63.219 -        } else {
  63.220 -            prefs.putBoolean(PARAMS_KEY, false);
  63.221 -        }
  63.222 -    }
  63.223 -
  63.224 -    static boolean getSkipTupleAssignments(Preferences prefs) {
  63.225 -        return prefs.getBoolean(SKIP_TUPLE_ASSIGN_KEY, true);
  63.226 -    }
  63.227 -
  63.228 -    static void setSkipTupleAssignments(Preferences prefs, boolean skipTupleAssigns) {
  63.229 -        if (skipTupleAssigns) {
  63.230 -            prefs.remove(SKIP_TUPLE_ASSIGN_KEY);
  63.231 -        } else {
  63.232 -            prefs.putBoolean(SKIP_TUPLE_ASSIGN_KEY, false);
  63.233 -        }
  63.234 -    }
  63.235 -
  63.236 -    static String getIgnoreNames(Preferences prefs) {
  63.237 -        return prefs.get(IGNORED_KEY, DEFAULT_IGNORED_NAMES);
  63.238 -    }
  63.239 -
  63.240 -    static void setIgnoreNames(Preferences prefs, String ignoredNames) {
  63.241 -        if (ignoredNames.length() == 0) {
  63.242 -            prefs.remove(IGNORED_KEY);
  63.243 -        } else {
  63.244 -            prefs.put(IGNORED_KEY, ignoredNames);
  63.245 -        }
  63.246 -    }
  63.247 -}
    64.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/UnusedDetectorPrefs.form	Sat Sep 12 23:03:15 2015 -0700
    64.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.3 @@ -1,84 +0,0 @@
    64.4 -<?xml version="1.0" encoding="UTF-8" ?>
    64.5 -
    64.6 -<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    64.7 -  <AuxValues>
    64.8 -    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
    64.9 -    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   64.10 -    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   64.11 -    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
   64.12 -    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   64.13 -    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
   64.14 -    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="2"/>
   64.15 -    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   64.16 -    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   64.17 -  </AuxValues>
   64.18 -
   64.19 -  <Layout>
   64.20 -    <DimensionLayout dim="0">
   64.21 -      <Group type="103" groupAlignment="0" attributes="0">
   64.22 -          <Component id="skipParams" min="-2" max="-2" attributes="0"/>
   64.23 -          <Component id="skipTupleAssignments" alignment="0" min="-2" max="-2" attributes="0"/>
   64.24 -          <Group type="102" alignment="0" attributes="0">
   64.25 -              <Component id="ignoredLabel" min="-2" max="-2" attributes="0"/>
   64.26 -              <EmptySpace max="-2" attributes="0"/>
   64.27 -              <Component id="ignoredNames" min="-2" max="-2" attributes="0"/>
   64.28 -          </Group>
   64.29 -      </Group>
   64.30 -    </DimensionLayout>
   64.31 -    <DimensionLayout dim="1">
   64.32 -      <Group type="103" groupAlignment="0" attributes="0">
   64.33 -          <Group type="102" attributes="0">
   64.34 -              <Component id="skipParams" min="-2" max="-2" attributes="0"/>
   64.35 -              <EmptySpace max="-2" attributes="0"/>
   64.36 -              <Component id="skipTupleAssignments" min="-2" max="-2" attributes="0"/>
   64.37 -              <EmptySpace max="-2" attributes="0"/>
   64.38 -              <Group type="103" groupAlignment="3" attributes="0">
   64.39 -                  <Component id="ignoredLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   64.40 -                  <Component id="ignoredNames" alignment="3" min="-2" max="-2" attributes="0"/>
   64.41 -              </Group>
   64.42 -              <EmptySpace max="32767" attributes="0"/>
   64.43 -          </Group>
   64.44 -      </Group>
   64.45 -    </DimensionLayout>
   64.46 -  </Layout>
   64.47 -  <SubComponents>
   64.48 -    <Component class="javax.swing.JCheckBox" name="skipParams">
   64.49 -      <Properties>
   64.50 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   64.51 -          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="UnusedDetectorPrefs.skipParams.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   64.52 -        </Property>
   64.53 -      </Properties>
   64.54 -      <Events>
   64.55 -        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
   64.56 -      </Events>
   64.57 -    </Component>
   64.58 -    <Component class="javax.swing.JCheckBox" name="skipTupleAssignments">
   64.59 -      <Properties>
   64.60 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   64.61 -          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="UnusedDetectorPrefs.skipTupleAssignments.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   64.62 -        </Property>
   64.63 -      </Properties>
   64.64 -      <Events>
   64.65 -        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
   64.66 -      </Events>
   64.67 -    </Component>
   64.68 -    <Component class="javax.swing.JTextField" name="ignoredNames">
   64.69 -      <Properties>
   64.70 -        <Property name="columns" type="int" value="25"/>
   64.71 -      </Properties>
   64.72 -      <Events>
   64.73 -        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
   64.74 -      </Events>
   64.75 -    </Component>
   64.76 -    <Component class="javax.swing.JLabel" name="ignoredLabel">
   64.77 -      <Properties>
   64.78 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
   64.79 -          <ComponentRef name="ignoredNames"/>
   64.80 -        </Property>
   64.81 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   64.82 -          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="UnusedDetectorPrefs.ignoredLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   64.83 -        </Property>
   64.84 -      </Properties>
   64.85 -    </Component>
   64.86 -  </SubComponents>
   64.87 -</Form>
    65.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/UnusedDetectorPrefs.java	Sat Sep 12 23:03:15 2015 -0700
    65.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.3 @@ -1,152 +0,0 @@
    65.4 -/*
    65.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    65.6 - *
    65.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    65.8 - *
    65.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   65.10 - * Other names may be trademarks of their respective owners.
   65.11 - *
   65.12 - * The contents of this file are subject to the terms of either the GNU
   65.13 - * General Public License Version 2 only ("GPL") or the Common
   65.14 - * Development and Distribution License("CDDL") (collectively, the
   65.15 - * "License"). You may not use this file except in compliance with the
   65.16 - * License. You can obtain a copy of the License at
   65.17 - * http://www.netbeans.org/cddl-gplv2.html
   65.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   65.19 - * specific language governing permissions and limitations under the
   65.20 - * License.  When distributing the software, include this License Header
   65.21 - * Notice in each file and include the License file at
   65.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   65.23 - * particular file as subject to the "Classpath" exception as provided
   65.24 - * by Oracle in the GPL Version 2 section of the License file that
   65.25 - * accompanied this code. If applicable, add the following below the
   65.26 - * License Header, with the fields enclosed by brackets [] replaced by
   65.27 - * your own identifying information:
   65.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   65.29 - *
   65.30 - * If you wish your version of this file to be governed by only the CDDL
   65.31 - * or only the GPL Version 2, indicate your decision by adding
   65.32 - * "[Contributor] elects to include this software in this distribution
   65.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   65.34 - * single choice of license, a recipient has the option to distribute
   65.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   65.36 - * to extend the choice of license to its licensees as provided above.
   65.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   65.38 - * Version 2 license, then the option applies only if the new code is
   65.39 - * made subject to such option by the copyright holder.
   65.40 - *
   65.41 - * Contributor(s):
   65.42 - *
   65.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   65.44 - */
   65.45 -
   65.46 -/*
   65.47 - * UnusedDetectorPrefs.java
   65.48 - *
   65.49 - * Created on Nov 10, 2008, 9:48:35 AM
   65.50 - */
   65.51 -package org.netbeans.modules.python.editor.hints;
   65.52 -
   65.53 -import java.awt.event.ActionListener;
   65.54 -import java.util.prefs.Preferences;
   65.55 -
   65.56 -/**
   65.57 - * Preferences where users can configure the unused detector rules
   65.58 - * 
   65.59 - * @author Tor Norbye
   65.60 - */
   65.61 -public class UnusedDetectorPrefs extends javax.swing.JPanel implements ActionListener {
   65.62 -    private Preferences prefs;
   65.63 -
   65.64 -    /** Creates new form UnusedDetectorPrefs */
   65.65 -    public UnusedDetectorPrefs(Preferences prefs) {
   65.66 -        initComponents();
   65.67 -        this.prefs = prefs;
   65.68 -        skipParams.setSelected(UnusedDetector.getSkipParameters(prefs));
   65.69 -        skipTupleAssignments.setSelected(UnusedDetector.getSkipTupleAssignments(prefs));
   65.70 -        String ignore = UnusedDetector.getIgnoreNames(prefs);
   65.71 -        if (ignore == null) {
   65.72 -            ignore = "";
   65.73 -        }
   65.74 -        ignoredNames.setText(ignore);
   65.75 -    }
   65.76 -
   65.77 -    @SuppressWarnings("unchecked")
   65.78 -    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
   65.79 -    private void initComponents() {
   65.80 -
   65.81 -        skipParams = new javax.swing.JCheckBox();
   65.82 -        skipTupleAssignments = new javax.swing.JCheckBox();
   65.83 -        ignoredNames = new javax.swing.JTextField();
   65.84 -        ignoredLabel = new javax.swing.JLabel();
   65.85 -
   65.86 -        skipParams.setText(org.openide.util.NbBundle.getMessage(UnusedDetectorPrefs.class, "UnusedDetectorPrefs.skipParams.text")); // NOI18N
   65.87 -        skipParams.addActionListener(this);
   65.88 -
   65.89 -        skipTupleAssignments.setText(org.openide.util.NbBundle.getMessage(UnusedDetectorPrefs.class, "UnusedDetectorPrefs.skipTupleAssignments.text")); // NOI18N
   65.90 -        skipTupleAssignments.addActionListener(this);
   65.91 -
   65.92 -        ignoredNames.setColumns(25);
   65.93 -        ignoredNames.addActionListener(this);
   65.94 -
   65.95 -        ignoredLabel.setLabelFor(ignoredNames);
   65.96 -        ignoredLabel.setText(org.openide.util.NbBundle.getMessage(UnusedDetectorPrefs.class, "UnusedDetectorPrefs.ignoredLabel.text")); // NOI18N
   65.97 -
   65.98 -        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
   65.99 -        this.setLayout(layout);
  65.100 -        layout.setHorizontalGroup(
  65.101 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  65.102 -            .addComponent(skipParams)
  65.103 -            .addComponent(skipTupleAssignments)
  65.104 -            .addGroup(layout.createSequentialGroup()
  65.105 -                .addComponent(ignoredLabel)
  65.106 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  65.107 -                .addComponent(ignoredNames, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
  65.108 -        );
  65.109 -        layout.setVerticalGroup(
  65.110 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  65.111 -            .addGroup(layout.createSequentialGroup()
  65.112 -                .addComponent(skipParams)
  65.113 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  65.114 -                .addComponent(skipTupleAssignments)
  65.115 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  65.116 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  65.117 -                    .addComponent(ignoredLabel)
  65.118 -                    .addComponent(ignoredNames, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
  65.119 -                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  65.120 -        );
  65.121 -    }
  65.122 -
  65.123 -    // Code for dispatching events from components to event handlers.
  65.124 -
  65.125 -    public void actionPerformed(java.awt.event.ActionEvent evt) {
  65.126 -        if (evt.getSource() == skipParams) {
  65.127 -            UnusedDetectorPrefs.this.changed(evt);
  65.128 -        }
  65.129 -        else if (evt.getSource() == skipTupleAssignments) {
  65.130 -            UnusedDetectorPrefs.this.changed(evt);
  65.131 -        }
  65.132 -        else if (evt.getSource() == ignoredNames) {
  65.133 -            UnusedDetectorPrefs.this.changed(evt);
  65.134 -        }
  65.135 -    }// </editor-fold>//GEN-END:initComponents
  65.136 -
  65.137 -    private void changed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_changed
  65.138 -        Object source = evt.getSource();
  65.139 -        if (source == ignoredNames) {
  65.140 -            UnusedDetector.setIgnoreNames(prefs, ignoredNames.getText().trim());
  65.141 -        } else if (source == skipParams) {
  65.142 -            UnusedDetector.setSkipParameters(prefs, skipParams.isSelected());
  65.143 -        } else if (source == skipTupleAssignments) {
  65.144 -            UnusedDetector.setSkipTupleAssignments(prefs, skipTupleAssignments.isSelected());
  65.145 -        } else {
  65.146 -            assert false : source;
  65.147 -        }
  65.148 -    }//GEN-LAST:event_changed
  65.149 -    // Variables declaration - do not modify//GEN-BEGIN:variables
  65.150 -    private javax.swing.JLabel ignoredLabel;
  65.151 -    private javax.swing.JTextField ignoredNames;
  65.152 -    private javax.swing.JCheckBox skipParams;
  65.153 -    private javax.swing.JCheckBox skipTupleAssignments;
  65.154 -    // End of variables declaration//GEN-END:variables
  65.155 -}
    66.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/UnusedImports.java	Sat Sep 12 23:03:15 2015 -0700
    66.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.3 @@ -1,286 +0,0 @@
    66.4 -/*
    66.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    66.6 - *
    66.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    66.8 - *
    66.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   66.10 - * Other names may be trademarks of their respective owners.
   66.11 - *
   66.12 - * The contents of this file are subject to the terms of either the GNU
   66.13 - * General Public License Version 2 only ("GPL") or the Common
   66.14 - * Development and Distribution License("CDDL") (collectively, the
   66.15 - * "License"). You may not use this file except in compliance with the
   66.16 - * License. You can obtain a copy of the License at
   66.17 - * http://www.netbeans.org/cddl-gplv2.html
   66.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   66.19 - * specific language governing permissions and limitations under the
   66.20 - * License.  When distributing the software, include this License Header
   66.21 - * Notice in each file and include the License file at
   66.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   66.23 - * particular file as subject to the "Classpath" exception as provided
   66.24 - * by Oracle in the GPL Version 2 section of the License file that
   66.25 - * accompanied this code. If applicable, add the following below the
   66.26 - * License Header, with the fields enclosed by brackets [] replaced by
   66.27 - * your own identifying information:
   66.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   66.29 - *
   66.30 - * If you wish your version of this file to be governed by only the CDDL
   66.31 - * or only the GPL Version 2, indicate your decision by adding
   66.32 - * "[Contributor] elects to include this software in this distribution
   66.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   66.34 - * single choice of license, a recipient has the option to distribute
   66.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   66.36 - * to extend the choice of license to its licensees as provided above.
   66.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   66.38 - * Version 2 license, then the option applies only if the new code is
   66.39 - * made subject to such option by the copyright holder.
   66.40 - *
   66.41 - * Contributor(s):
   66.42 - *
   66.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   66.44 - */
   66.45 -package org.netbeans.modules.python.editor.hints;
   66.46 -
   66.47 -import java.util.ArrayList;
   66.48 -import java.util.Collections;
   66.49 -import java.util.HashMap;
   66.50 -import java.util.List;
   66.51 -import java.util.Map;
   66.52 -import java.util.Set;
   66.53 -import java.util.prefs.Preferences;
   66.54 -import javax.swing.JComponent;
   66.55 -import org.netbeans.editor.BaseDocument;
   66.56 -import org.netbeans.modules.csl.api.EditList;
   66.57 -import org.netbeans.modules.csl.api.Hint;
   66.58 -import org.netbeans.modules.csl.api.HintFix;
   66.59 -import org.netbeans.modules.csl.api.HintSeverity;
   66.60 -import org.netbeans.modules.csl.api.OffsetRange;
   66.61 -import org.netbeans.modules.csl.api.RuleContext;
   66.62 -import org.netbeans.modules.python.editor.PythonAstUtils;
   66.63 -import org.netbeans.modules.python.editor.PythonParserResult;
   66.64 -import org.netbeans.modules.python.editor.imports.ImportEntry;
   66.65 -import org.netbeans.modules.python.editor.imports.ImportManager;
   66.66 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   66.67 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
   66.68 -import org.openide.filesystems.FileObject;
   66.69 -import org.openide.util.NbBundle;
   66.70 -import org.python.antlr.PythonTree;
   66.71 -import org.python.antlr.ast.Import;
   66.72 -import org.python.antlr.ast.ImportFrom;
   66.73 -import org.python.antlr.ast.Module;
   66.74 -import org.python.antlr.ast.alias;
   66.75 -
   66.76 -/**
   66.77 - * Detect unused imports
   66.78 - *
   66.79 - * @author Tor Norbye
   66.80 - */
   66.81 -public class UnusedImports extends PythonAstRule {
   66.82 -    public UnusedImports() {
   66.83 -    }
   66.84 -
   66.85 -    @Override
   66.86 -    public boolean appliesTo(RuleContext context) {
   66.87 -        FileObject fo = context.parserResult.getSnapshot().getSource().getFileObject();
   66.88 -        return fo == null || !fo.getName().equals("__init__"); // NOI18N
   66.89 -    }
   66.90 -
   66.91 -    @Override
   66.92 -    public Set<Class> getKinds() {
   66.93 -        return Collections.<Class>singleton(Module.class);
   66.94 -    }
   66.95 -
   66.96 -    @Override
   66.97 -    public void run(PythonRuleContext context, List<Hint> result) {
   66.98 -        computeUnusedImports(this, context, result, null);
   66.99 -    }
  66.100 -
  66.101 -    private static void computeUnusedImports(UnusedImports detector, PythonRuleContext context, List<Hint> result, Map<PythonTree, List<String>> unused) {
  66.102 -        assert result == null || unused == null; // compute either results or set of unused
  66.103 -
  66.104 -        PythonParserResult info = (PythonParserResult) context.parserResult;
  66.105 -        SymbolTable symbolTable = info.getSymbolTable();
  66.106 -        List<ImportEntry> unusedImports = symbolTable.getUnusedImports();
  66.107 -        if (unusedImports.isEmpty()) {
  66.108 -            return;
  66.109 -        }
  66.110 -        Map<PythonTree, List<String>> maps = new HashMap<>();
  66.111 -        for (ImportEntry entry : unusedImports) {
  66.112 -            maps.put(entry.node, new ArrayList<String>());
  66.113 -        }
  66.114 -        for (ImportEntry entry : unusedImports) {
  66.115 -            if (entry.isFromImport) {
  66.116 -                String name = entry.asName != null ? entry.asName : entry.symbol;
  66.117 -                maps.get(entry.node).add(name);
  66.118 -            } else {
  66.119 -                String name = entry.asName != null ? entry.asName : entry.module;
  66.120 -                maps.get(entry.node).add(name);
  66.121 -            }
  66.122 -        }
  66.123 -        for (Map.Entry<PythonTree, List<String>> entry : maps.entrySet()) {
  66.124 -            PythonTree node = entry.getKey();
  66.125 -            List<String> list = entry.getValue();
  66.126 -            if (node instanceof Import) {
  66.127 -                Import imp = (Import)node;
  66.128 -                List<alias> names = imp.getInternalNames();
  66.129 -                if (names != null && names.size() == list.size()) {
  66.130 -                    list.clear();
  66.131 -                }
  66.132 -            } else {
  66.133 -                assert node instanceof ImportFrom;
  66.134 -                ImportFrom imp = (ImportFrom)node;
  66.135 -                List<alias> names = imp.getInternalNames();
  66.136 -                if (names != null && names.size() == list.size()) {
  66.137 -                    list.clear();
  66.138 -                }
  66.139 -            }
  66.140 -        }
  66.141 -
  66.142 -        for (Map.Entry<PythonTree, List<String>> entry : maps.entrySet()) {
  66.143 -            PythonTree node = entry.getKey();
  66.144 -            List<String> list = entry.getValue();
  66.145 -            if (list.size() == 0) {
  66.146 -                list = null;
  66.147 -            }
  66.148 -            if (unused != null) {
  66.149 -                unused.put(node, list);
  66.150 -            } else {
  66.151 -                addError(detector, context, node, list, result);
  66.152 -            }
  66.153 -        }
  66.154 -    }
  66.155 -
  66.156 -    private static void addError(UnusedImports detector, PythonRuleContext context, PythonTree node, List<String> symbols, List<Hint> result) {
  66.157 -        PythonParserResult info = (PythonParserResult) context.parserResult;
  66.158 -        OffsetRange range = PythonAstUtils.getNameRange(info, node);
  66.159 -        range = PythonLexerUtils.getLexerOffsets(info, range);
  66.160 -        if (range != OffsetRange.NONE) {
  66.161 -            List<HintFix> fixList = new ArrayList<>(3);
  66.162 -            fixList.add(new UnusedFix(detector, context, node, symbols, false));
  66.163 -            fixList.add(new UnusedFix(detector, context, null, null, false)); // Remove All
  66.164 -            fixList.add(new UnusedFix(detector, context, null, null, true)); // Organize
  66.165 -            String message;
  66.166 -            if (symbols != null) {
  66.167 -                message = NbBundle.getMessage(NameRule.class, "UnusedImportSymbols", symbols);
  66.168 -            } else {
  66.169 -                message = NbBundle.getMessage(NameRule.class, "UnusedImport");
  66.170 -            }
  66.171 -            Hint desc = new Hint(detector, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2500);
  66.172 -            result.add(desc);
  66.173 -        }
  66.174 -    }
  66.175 -
  66.176 -    @Override
  66.177 -    public String getId() {
  66.178 -        return "UnusedImports"; // NOI18N
  66.179 -    }
  66.180 -
  66.181 -    @Override
  66.182 -    public String getDisplayName() {
  66.183 -        return NbBundle.getMessage(NameRule.class, "UnusedImports");
  66.184 -    }
  66.185 -
  66.186 -    @Override
  66.187 -    public String getDescription() {
  66.188 -        return NbBundle.getMessage(NameRule.class, "UnusedImportsDesc");
  66.189 -    }
  66.190 -
  66.191 -    @Override
  66.192 -    public boolean getDefaultEnabled() {
  66.193 -        return true;
  66.194 -    }
  66.195 -
  66.196 -    @Override
  66.197 -    public boolean showInTasklist() {
  66.198 -        return false; // ? or maybe yes?
  66.199 -    }
  66.200 -
  66.201 -    @Override
  66.202 -    public HintSeverity getDefaultSeverity() {
  66.203 -        return HintSeverity.WARNING;
  66.204 -    }
  66.205 -
  66.206 -    @Override
  66.207 -    public JComponent getCustomizer(Preferences node) {
  66.208 -        return null;
  66.209 -    }
  66.210 -
  66.211 -    /**
  66.212 -     * Fix to insert self argument or rename first argument to self
  66.213 -     */
  66.214 -    private static class UnusedFix implements /*PreviewableFix*/ HintFix { // Preview not particularly helpful and clutters menu
  66.215 -        private final UnusedImports detector;
  66.216 -        private final PythonRuleContext context;
  66.217 -        private final PythonTree node;
  66.218 -        private final List<String> symbols;
  66.219 -        private final boolean organizeOnly;
  66.220 -
  66.221 -        private UnusedFix(UnusedImports detector, PythonRuleContext context, PythonTree node, List<String> symbols, boolean organizeOnly) {
  66.222 -            this.detector = detector;
  66.223 -            this.context = context;
  66.224 -            this.node = node;
  66.225 -            this.symbols = symbols;
  66.226 -            this.organizeOnly = organizeOnly;
  66.227 -        }
  66.228 -
  66.229 -        @Override
  66.230 -        public String getDescription() {
  66.231 -            if (node == null) {
  66.232 -                if (organizeOnly) {
  66.233 -                    return NbBundle.getMessage(CreateDocString.class, "OrganizeImports");
  66.234 -                } else {
  66.235 -                    return NbBundle.getMessage(CreateDocString.class, "DeleteAllUnused");
  66.236 -                }
  66.237 -            } else if (symbols != null) {
  66.238 -                return NbBundle.getMessage(CreateDocString.class, "UnusedFixSymbols", symbols);
  66.239 -            } else {
  66.240 -                return NbBundle.getMessage(CreateDocString.class, "UnusedFix");
  66.241 -            }
  66.242 -        }
  66.243 -
  66.244 -        public boolean canPreview() {
  66.245 -            return true;
  66.246 -        }
  66.247 -
  66.248 -        public EditList getEditList() throws Exception {
  66.249 -            BaseDocument doc = context.doc;
  66.250 -            EditList edits = new EditList(doc);
  66.251 -
  66.252 -            ImportManager importManager = new ImportManager((PythonParserResult) context.parserResult);
  66.253 -
  66.254 -            if (node == null) {
  66.255 -                if (organizeOnly) {
  66.256 -                    importManager.cleanup(edits, 0, doc.getLength(), true);
  66.257 -                } else {
  66.258 -                    Map<PythonTree, List<String>> onlyNames = new HashMap<>();
  66.259 -                    computeUnusedImports(detector, context, null, onlyNames);
  66.260 -                    Set<PythonTree> candidates = onlyNames.keySet();
  66.261 -                    importManager.removeImports(edits, candidates, false, onlyNames);
  66.262 -                }
  66.263 -            } else {
  66.264 -                Set<PythonTree> candidates = Collections.singleton(node);
  66.265 -                Map<PythonTree, List<String>> onlyNames = new HashMap<>();
  66.266 -                onlyNames.put(node, symbols);
  66.267 -                importManager.removeImports(edits, candidates, false, onlyNames);
  66.268 -            }
  66.269 -
  66.270 -            return edits;
  66.271 -        }
  66.272 -
  66.273 -        @Override
  66.274 -        public void implement() throws Exception {
  66.275 -            EditList edits = getEditList();
  66.276 -            edits.apply();
  66.277 -        }
  66.278 -
  66.279 -        @Override
  66.280 -        public boolean isSafe() {
  66.281 -            return true;
  66.282 -        }
  66.283 -
  66.284 -        @Override
  66.285 -        public boolean isInteractive() {
  66.286 -            return false;
  66.287 -        }
  66.288 -    }
  66.289 -}
    67.1 --- a/python.editor/src/org/netbeans/modules/python/editor/imports/FastImportAction.java	Sat Sep 12 23:03:15 2015 -0700
    67.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/imports/FastImportAction.java	Sun Sep 13 11:47:42 2015 +0200
    67.3 @@ -59,10 +59,10 @@
    67.4  import org.netbeans.editor.BaseAction;
    67.5  import org.netbeans.editor.Utilities;
    67.6  import org.netbeans.modules.csl.spi.GsfUtilities;
    67.7 -import org.netbeans.modules.python.editor.PythonAstUtils;
    67.8 -import org.netbeans.modules.python.editor.PythonIndex;
    67.9 -import org.netbeans.modules.python.editor.PythonParserResult;
   67.10 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   67.11 +import org.netbeans.modules.python.source.PythonAstUtils;
   67.12 +import org.netbeans.modules.python.source.PythonIndex;
   67.13 +import org.netbeans.modules.python.source.PythonParserResult;
   67.14 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
   67.15  import org.openide.ErrorManager;
   67.16  import org.openide.filesystems.FileObject;
   67.17  import org.openide.util.Exceptions;
    68.1 --- a/python.editor/src/org/netbeans/modules/python/editor/imports/FixImportsAction.java	Sat Sep 12 23:03:15 2015 -0700
    68.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/imports/FixImportsAction.java	Sun Sep 13 11:47:42 2015 +0200
    68.3 @@ -41,6 +41,8 @@
    68.4   */
    68.5  package org.netbeans.modules.python.editor.imports;
    68.6  
    68.7 +import org.netbeans.modules.python.source.ImportEntry;
    68.8 +import org.netbeans.modules.python.source.ImportManager;
    68.9  import java.awt.Dialog;
   68.10  import java.awt.Toolkit;
   68.11  import java.awt.event.ActionEvent;
   68.12 @@ -62,9 +64,9 @@
   68.13  import org.netbeans.modules.parsing.api.Source;
   68.14  import org.netbeans.modules.parsing.api.UserTask;
   68.15  import org.netbeans.modules.parsing.spi.ParseException;
   68.16 -import org.netbeans.modules.python.editor.PythonAstUtils;
   68.17 -import org.netbeans.modules.python.editor.PythonParserResult;
   68.18 -import org.netbeans.modules.python.editor.options.CodeStyle.ImportCleanupStyle;
   68.19 +import org.netbeans.modules.python.source.PythonAstUtils;
   68.20 +import org.netbeans.modules.python.source.PythonParserResult;
   68.21 +import org.netbeans.modules.python.source.CodeStyle.ImportCleanupStyle;
   68.22  import org.openide.DialogDescriptor;
   68.23  import org.openide.DialogDisplayer;
   68.24  import org.openide.awt.StatusDisplayer;
   68.25 @@ -100,6 +102,10 @@
   68.26   * @author Tor Norbye
   68.27   */
   68.28  public class FixImportsAction extends BaseAction {
   68.29 +    private static final String PREFS_KEY = FixImportsAction.class.getName();
   68.30 +    // TODO - use document style instead!
   68.31 +    private static final String KEY_REMOVE_UNUSED_IMPORTS = "removeUnusedImports"; // NOI18N
   68.32 +    
   68.33      public FixImportsAction() {
   68.34          super("fix-imports", 0); // NOI18N
   68.35      }
   68.36 @@ -153,7 +159,7 @@
   68.37                  boolean fixImports = false;
   68.38                  String[] selections = null;
   68.39                  boolean removeUnusedImports;
   68.40 -                Preferences prefs = NbPreferences.forModule(FixImportsAction.class).node(ImportManager.PREFS_KEY);
   68.41 +                Preferences prefs = NbPreferences.forModule(FixImportsAction.class).node(PREFS_KEY);
   68.42  
   68.43                  List<String> ambiguousSymbols = new ArrayList<>();
   68.44                  Set<ImportEntry> unused = new HashSet<>();
   68.45 @@ -199,7 +205,7 @@
   68.46                          FixDuplicateImportStmts panel = new FixDuplicateImportStmts();
   68.47  
   68.48                          panel.initPanel(names, variants, icons, defaults,
   68.49 -                                prefs.getBoolean(ImportManager.KEY_REMOVE_UNUSED_IMPORTS, true));
   68.50 +                                prefs.getBoolean(KEY_REMOVE_UNUSED_IMPORTS, true));
   68.51  
   68.52                          DialogDescriptor dd = new DialogDescriptor(panel, NbBundle.getMessage(FixImportsAction.class, "FixDupImportStmts_Title")); //NOI18N
   68.53                          Dialog d = DialogDisplayer.getDefault().createDialog(dd);
   68.54 @@ -227,10 +233,10 @@
   68.55                      } else {
   68.56                          fixImports = true;
   68.57                          selections = defaults;
   68.58 -                        removeUnusedImports = prefs.getBoolean(ImportManager.KEY_REMOVE_UNUSED_IMPORTS, true);
   68.59 +                        removeUnusedImports = prefs.getBoolean(KEY_REMOVE_UNUSED_IMPORTS, true);
   68.60                      }
   68.61                  } else {
   68.62 -                    removeUnusedImports = prefs.getBoolean(ImportManager.KEY_REMOVE_UNUSED_IMPORTS, true);
   68.63 +                    removeUnusedImports = prefs.getBoolean(KEY_REMOVE_UNUSED_IMPORTS, true);
   68.64                      // Just clean up imports
   68.65                      fixImports = true;
   68.66                      selections = null;
   68.67 @@ -238,7 +244,7 @@
   68.68  
   68.69                  if (fixImports) {
   68.70                      if (shouldShowImportsPanel) {
   68.71 -                        prefs.putBoolean(ImportManager.KEY_REMOVE_UNUSED_IMPORTS, removeUnusedImports);
   68.72 +                        prefs.putBoolean(KEY_REMOVE_UNUSED_IMPORTS, removeUnusedImports);
   68.73                      }
   68.74  
   68.75                      if (!removeUnusedImports) {
    69.1 --- a/python.editor/src/org/netbeans/modules/python/editor/imports/ImportEntry.java	Sat Sep 12 23:03:15 2015 -0700
    69.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.3 @@ -1,171 +0,0 @@
    69.4 -/*
    69.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    69.6 - *
    69.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    69.8 - *
    69.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   69.10 - * Other names may be trademarks of their respective owners.
   69.11 - *
   69.12 - * The contents of this file are subject to the terms of either the GNU
   69.13 - * General Public License Version 2 only ("GPL") or the Common
   69.14 - * Development and Distribution License("CDDL") (collectively, the
   69.15 - * "License"). You may not use this file except in compliance with the
   69.16 - * License. You can obtain a copy of the License at
   69.17 - * http://www.netbeans.org/cddl-gplv2.html
   69.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   69.19 - * specific language governing permissions and limitations under the
   69.20 - * License.  When distributing the software, include this License Header
   69.21 - * Notice in each file and include the License file at
   69.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   69.23 - * particular file as subject to the "Classpath" exception as provided
   69.24 - * by Oracle in the GPL Version 2 section of the License file that
   69.25 - * accompanied this code. If applicable, add the following below the
   69.26 - * License Header, with the fields enclosed by brackets [] replaced by
   69.27 - * your own identifying information:
   69.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   69.29 - *
   69.30 - * Contributor(s):
   69.31 - *
   69.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   69.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   69.34 - * Microsystems, Inc. All Rights Reserved.
   69.35 - *
   69.36 - * If you wish your version of this file to be governed by only the CDDL
   69.37 - * or only the GPL Version 2, indicate your decision by adding
   69.38 - * "[Contributor] elects to include this software in this distribution
   69.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   69.40 - * single choice of license, a recipient has the option to distribute
   69.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   69.42 - * to extend the choice of license to its licensees as provided above.
   69.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   69.44 - * Version 2 license, then the option applies only if the new code is
   69.45 - * made subject to such option by the copyright holder.
   69.46 - */
   69.47 -package org.netbeans.modules.python.editor.imports;
   69.48 -
   69.49 -import org.python.antlr.PythonTree;
   69.50 -
   69.51 -/**
   69.52 - * State about a single atomic import. (A single import statement in Python
   69.53 - *  can correspond to many atomic imports: one for each symbol or module
   69.54 - *  imported)
   69.55 - *
   69.56 - * @author Tor Norbye
   69.57 - */
   69.58 -public class ImportEntry implements Comparable<ImportEntry> {
   69.59 -    public final String module;
   69.60 -    public final String asName;
   69.61 -    public final String symbol;
   69.62 -    public final boolean isSystem;
   69.63 -    public final boolean isFromImport;
   69.64 -    /**
   69.65 -     * Natural order of import statements (in the source). This will be non zero if
   69.66 -     * we want to preserve the original order rather than the alphabetical order.
   69.67 -     */
   69.68 -    public int ordinal;
   69.69 -    /** 
   69.70 -     * Corresponding import statement node. This will be non null if we want to consider
   69.71 -     * duplicate import statements as different 
   69.72 -     */
   69.73 -    public PythonTree node;
   69.74 -    /**
   69.75 -     * Whether we have a symbol import AND we're sorting by symbol imports.
   69.76 -     * Will be false even for symbol imports when we're not sorting by symbols.
   69.77 -     */
   69.78 -    public boolean sortedFrom;
   69.79 -
   69.80 -    public ImportEntry(String module, String symbol, String asName, boolean isSystem, PythonTree node, int ordinal) {
   69.81 -        super();
   69.82 -        this.module = module;
   69.83 -        this.symbol = symbol;
   69.84 -        this.asName = asName;
   69.85 -        this.isSystem = isSystem;
   69.86 -        this.isFromImport = symbol != null;
   69.87 -        this.node = node;
   69.88 -        this.ordinal = ordinal;
   69.89 -
   69.90 -        this.sortedFrom = symbol != null;
   69.91 -    }
   69.92 -
   69.93 -    public ImportEntry(String module, String asName, boolean isSystem, PythonTree node, int ordinal) {
   69.94 -        this(module, null, asName, isSystem, node, ordinal);
   69.95 -    }
   69.96 -
   69.97 -    @Override
   69.98 -    public boolean equals(Object obj) {
   69.99 -        if (obj == null) {
  69.100 -            return false;
  69.101 -        }
  69.102 -        if (getClass() != obj.getClass()) {
  69.103 -            return false;
  69.104 -        }
  69.105 -        final ImportEntry other = (ImportEntry)obj;
  69.106 -        if (this.node != other.node) {
  69.107 -            return false;
  69.108 -        }
  69.109 -        if ((this.module == null) ? (other.module != null) : !this.module.equals(other.module)) {
  69.110 -            return false;
  69.111 -        }
  69.112 -        if ((this.asName == null) ? (other.asName != null) : !this.asName.equals(other.asName)) {
  69.113 -            return false;
  69.114 -        }
  69.115 -        if ((this.symbol == null) ? (other.symbol != null) : !this.symbol.equals(other.symbol)) {
  69.116 -            return false;
  69.117 -        }
  69.118 -        return true;
  69.119 -    }
  69.120 -
  69.121 -    @Override
  69.122 -    public int hashCode() {
  69.123 -        int hash = 7;
  69.124 -        hash = 29 * hash + (this.module != null ? this.module.hashCode() : 0);
  69.125 -        return hash;
  69.126 -    }
  69.127 -
  69.128 -    @Override
  69.129 -    public int compareTo(ImportEntry other) {
  69.130 -        boolean thisIsFuture = "__future__".equals(module); // NOI18N
  69.131 -        boolean otherIsFuture = "__future__".equals(other.module); // NOI18N
  69.132 -        if (thisIsFuture != otherIsFuture) {
  69.133 -            return thisIsFuture ? -1 : 1;
  69.134 -        }
  69.135 -        if (isSystem != other.isSystem) {
  69.136 -            return isSystem ? -1 : 1;
  69.137 -        }
  69.138 -        if (sortedFrom != other.sortedFrom) {
  69.139 -            return sortedFrom ? 1 : -1;
  69.140 -        }
  69.141 -        if (ordinal != other.ordinal) {
  69.142 -            return ordinal - other.ordinal;
  69.143 -        }
  69.144 -        // Then we sort by module name
  69.145 -        int result = module.compareTo(other.module);
  69.146 -        if (result != 0) {
  69.147 -            return result;
  69.148 -        }
  69.149 -        // And then, for each module, first the imports, then the from imports
  69.150 -        if (isFromImport != other.isFromImport) {
  69.151 -            return isFromImport ? 1 : -1;
  69.152 -        }
  69.153 -        if (symbol != null) {
  69.154 -            assert other.symbol != null;
  69.155 -            // since isFromImport==
  69.156 -            result = symbol.compareTo(other.symbol);
  69.157 -            if (result != 0) {
  69.158 -                return result;
  69.159 -            }
  69.160 -        }
  69.161 -        if (asName == null) {
  69.162 -            return (other.asName == null) ? 0 : 1;
  69.163 -        }
  69.164 -        if (other.asName == null) {
  69.165 -            return -1;
  69.166 -        }
  69.167 -        return asName.compareTo(other.asName);
  69.168 -    }
  69.169 -
  69.170 -    @Override
  69.171 -    public String toString() {
  69.172 -        return "ImportEntry(" + module + ", " + symbol + ", " + asName + ")"; // NOI18N
  69.173 -    }
  69.174 -}
    70.1 --- a/python.editor/src/org/netbeans/modules/python/editor/imports/ImportManager.java	Sat Sep 12 23:03:15 2015 -0700
    70.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.3 @@ -1,1050 +0,0 @@
    70.4 -/*
    70.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    70.6 - *
    70.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    70.8 - *
    70.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   70.10 - * Other names may be trademarks of their respective owners.
   70.11 - *
   70.12 - * The contents of this file are subject to the terms of either the GNU
   70.13 - * General Public License Version 2 only ("GPL") or the Common
   70.14 - * Development and Distribution License("CDDL") (collectively, the
   70.15 - * "License"). You may not use this file except in compliance with the
   70.16 - * License. You can obtain a copy of the License at
   70.17 - * http://www.netbeans.org/cddl-gplv2.html
   70.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   70.19 - * specific language governing permissions and limitations under the
   70.20 - * License.  When distributing the software, include this License Header
   70.21 - * Notice in each file and include the License file at
   70.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   70.23 - * particular file as subject to the "Classpath" exception as provided
   70.24 - * by Oracle in the GPL Version 2 section of the License file that
   70.25 - * accompanied this code. If applicable, add the following below the
   70.26 - * License Header, with the fields enclosed by brackets [] replaced by
   70.27 - * your own identifying information:
   70.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   70.29 - *
   70.30 - * If you wish your version of this file to be governed by only the CDDL
   70.31 - * or only the GPL Version 2, indicate your decision by adding
   70.32 - * "[Contributor] elects to include this software in this distribution
   70.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   70.34 - * single choice of license, a recipient has the option to distribute
   70.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   70.36 - * to extend the choice of license to its licensees as provided above.
   70.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   70.38 - * Version 2 license, then the option applies only if the new code is
   70.39 - * made subject to such option by the copyright holder.
   70.40 - *
   70.41 - * Contributor(s):
   70.42 - *
   70.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   70.44 - */
   70.45 -package org.netbeans.modules.python.editor.imports;
   70.46 -
   70.47 -import java.awt.Toolkit;
   70.48 -import java.util.ArrayList;
   70.49 -import java.util.Collection;
   70.50 -import java.util.Collections;
   70.51 -import java.util.HashMap;
   70.52 -import java.util.HashSet;
   70.53 -import java.util.List;
   70.54 -import java.util.Map;
   70.55 -import java.util.Set;
   70.56 -import javax.swing.text.BadLocationException;
   70.57 -import org.netbeans.api.editor.EditorRegistry;
   70.58 -import org.netbeans.editor.BaseDocument;
   70.59 -import org.netbeans.editor.Utilities;
   70.60 -import org.netbeans.modules.csl.api.EditList;
   70.61 -import org.netbeans.modules.csl.api.OffsetRange;
   70.62 -import org.netbeans.modules.csl.spi.GsfUtilities;
   70.63 -import org.netbeans.modules.editor.indent.api.IndentUtils;
   70.64 -import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
   70.65 -import org.netbeans.modules.python.editor.PythonAstUtils;
   70.66 -import org.netbeans.modules.python.editor.PythonIndex;
   70.67 -import org.netbeans.modules.python.editor.PythonParserResult;
   70.68 -import org.netbeans.modules.python.editor.elements.IndexedElement;
   70.69 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
   70.70 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   70.71 -import org.netbeans.modules.python.editor.options.CodeStyle;
   70.72 -import org.netbeans.modules.python.editor.options.CodeStyle.ImportCleanupStyle;
   70.73 -import org.netbeans.modules.python.editor.scopes.SymbolTable;
   70.74 -import org.netbeans.modules.python.editor.scopes.SymInfo;
   70.75 -import org.openide.util.Exceptions;
   70.76 -import org.openide.util.NbBundle;
   70.77 -import org.python.antlr.PythonTree;
   70.78 -import org.python.antlr.ast.Import;
   70.79 -import org.python.antlr.ast.ImportFrom;
   70.80 -import org.python.antlr.ast.Str;
   70.81 -import org.python.antlr.ast.alias;
   70.82 -
   70.83 -/**
   70.84 - * Computations regarding module imports.
   70.85 - *
   70.86 - * @todo Handle commenting out portions of imports
   70.87 - * @todo If I can make this fast, consider highlighting unused imports.
   70.88 - * @todo On code completion I should import the corresponding package+class (make the
   70.89 - *   class part optional)
   70.90 - * @todo Watch out for commented out imports getting wiped out in organize imports
   70.91 - *   because it's between imports. These need to be moved to the end!!!
   70.92 - * @todo Offer to group imports
   70.93 - * @todo Don't import functions
   70.94 - *
   70.95 - * @author Tor Norbye
   70.96 - */
   70.97 -public final class ImportManager {
   70.98 -    static final String PREFS_KEY = FixImportsAction.class.getName();
   70.99 -    // TODO - use document style instead!
  70.100 -    static final String KEY_REMOVE_UNUSED_IMPORTS = "removeUnusedImports"; // NOI18N
  70.101 -    private PythonParserResult info;
  70.102 -    private List<Import> imports;
  70.103 -    private List<ImportFrom> importsFrom;
  70.104 -    private PythonTree root;
  70.105 -    private BaseDocument doc;
  70.106 -    private List<PythonTree> mainImports;
  70.107 -    private Set<PythonTree> topLevelImports;
  70.108 -
  70.109 -    // Settings
  70.110 -    private boolean systemLibsFirst = true;
  70.111 -    private boolean splitImports = true;
  70.112 -    private boolean sortImports = true;
  70.113 -    private boolean separateFromImps = false;
  70.114 -    private ImportCleanupStyle cleanup = ImportCleanupStyle.COMMENT_OUT;
  70.115 -    private boolean removeDuplicates;
  70.116 -    private int rightMargin;
  70.117 -
  70.118 -    public ImportManager(PythonParserResult info) {
  70.119 -        this(info, GsfUtilities.getDocument(info.getSnapshot().getSource().getFileObject(), false), null);
  70.120 -    }
  70.121 -
  70.122 -    public ImportManager(PythonParserResult info, BaseDocument doc) {
  70.123 -        this(info, doc, null);
  70.124 -    }
  70.125 -
  70.126 -    public ImportManager(PythonParserResult info, BaseDocument doc, CodeStyle codeStyle) {
  70.127 -        this.info = info;
  70.128 -
  70.129 -        root = PythonAstUtils.getRoot(info);
  70.130 -
  70.131 -        SymbolTable symbolTable = PythonAstUtils.getParseResult(info).getSymbolTable();
  70.132 -        imports = symbolTable.getImports();
  70.133 -        importsFrom = symbolTable.getImportsFrom();
  70.134 -        topLevelImports = symbolTable.getTopLevelImports();
  70.135 -        mainImports = symbolTable.getMainImports();
  70.136 -
  70.137 -        this.doc = doc;
  70.138 -
  70.139 -        if (codeStyle == null) {
  70.140 -            codeStyle = CodeStyle.getDefault(doc);
  70.141 -        }
  70.142 -        systemLibsFirst = codeStyle.systemLibsFirst();
  70.143 -        splitImports = codeStyle.oneImportPerLine();
  70.144 -        cleanup = codeStyle.cleanupImports();
  70.145 -        sortImports = codeStyle.sortImports();
  70.146 -        separateFromImps = codeStyle.separateFromImps();
  70.147 -        if (separateFromImps) {
  70.148 -            sortImports = true;
  70.149 -        }
  70.150 -        removeDuplicates = codeStyle.removeDuplicates();
  70.151 -        rightMargin = codeStyle.getRightMargin();
  70.152 -
  70.153 -    }
  70.154 -
  70.155 -    public static boolean isFutureImport(ImportFrom fromStatement) {
  70.156 -        return "__future__".equals(fromStatement.getInternalModule()); // NOI18N
  70.157 -    }
  70.158 -
  70.159 -    public void setCleanup(ImportCleanupStyle cleanup) {
  70.160 -        this.cleanup = cleanup;
  70.161 -    }
  70.162 -
  70.163 -    public void cleanup(EditList edits, int startOffset, int endOffset, boolean force) {
  70.164 -        OffsetRange lexRange = getMainImportsRange();
  70.165 -        if (lexRange == OffsetRange.NONE ||
  70.166 -                !(new OffsetRange(startOffset, endOffset).overlaps(lexRange))) {
  70.167 -            // Not touching imports
  70.168 -            return;
  70.169 -        }
  70.170 -
  70.171 -        if (cleanup != ImportCleanupStyle.LEAVE_ALONE) {
  70.172 -            List<String> ambiguousSymbols = new ArrayList<>();
  70.173 -            Map<String, String> defaultLists = new HashMap<>();
  70.174 -            Map<String, List<String>> alternatives = new HashMap<>();
  70.175 -            Set<ImportEntry> unused = new HashSet<>();
  70.176 -            Set<ImportEntry> duplicates = new HashSet<>();
  70.177 -
  70.178 -            computeImports(ambiguousSymbols, defaultLists, alternatives, unused, duplicates);
  70.179 -            if (ambiguousSymbols.size() == 0 || force) {
  70.180 -                apply(edits, new String[0], unused, duplicates);
  70.181 -                return;
  70.182 -            }
  70.183 -        } else if (removeDuplicates) {
  70.184 -            Set<ImportEntry> duplicates = findDuplicates();
  70.185 -            apply(edits, new String[0], Collections.<ImportEntry>emptySet(), duplicates);
  70.186 -            return;
  70.187 -        }
  70.188 -
  70.189 -        apply(edits, new String[0], Collections.<ImportEntry>emptySet(), Collections.<ImportEntry>emptySet());
  70.190 -    }
  70.191 -
  70.192 -    public List<Import> getImports() {
  70.193 -        return imports;
  70.194 -    }
  70.195 -
  70.196 -    public List<ImportFrom> getImportsFrom() {
  70.197 -        return importsFrom;
  70.198 -    }
  70.199 -
  70.200 -    private Set<ImportEntry> findDuplicates() {
  70.201 -        Set<ImportEntry> duplicates = new HashSet<>();
  70.202 -        // TODO!
  70.203 -
  70.204 -        return duplicates;
  70.205 -    }
  70.206 -
  70.207 -    public boolean computeImports(
  70.208 -            List<String> ambiguousSymbols,
  70.209 -            Map<String, String> defaults,
  70.210 -            Map<String, List<String>> alternatives, Set<ImportEntry> unused, Set<ImportEntry> duplicates) {
  70.211 -
  70.212 -        boolean ambiguous = false;
  70.213 -
  70.214 -        SymbolTable symbolTable = new SymbolTable(PythonAstUtils.getRoot(info), info.getSnapshot().getSource().getFileObject());
  70.215 -        Map<String, SymInfo> unresolved = symbolTable.getUnresolvedNames(info);
  70.216 -
  70.217 -        if (unresolved.size() > 0) {
  70.218 -            ambiguousSymbols.addAll(unresolved.keySet());
  70.219 -            Collections.sort(ambiguousSymbols);
  70.220 -
  70.221 -            // Try to compute suggestions.
  70.222 -            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
  70.223 -            Set<IndexedElement> modules = index.getModules("", QuerySupport.Kind.PREFIX);
  70.224 -            for (IndexedElement module : modules) {
  70.225 -                String name = module.getName();
  70.226 -                if (unresolved.containsKey(name)) {
  70.227 -                    List<String> list = new ArrayList<>(4);
  70.228 -                    list.add(name);
  70.229 -                    defaults.put(name, name);
  70.230 -                    alternatives.put(name, list);
  70.231 -                }
  70.232 -            }
  70.233 -
  70.234 -            List<String> unresolvedList = new ArrayList<>(unresolved.keySet());
  70.235 -            Collections.sort(unresolvedList);
  70.236 -            for (String symbol : unresolvedList) {
  70.237 -                // TODO - determine if it's a call or variable
  70.238 -                // TODO - track import usages too!
  70.239 -                Collection<String> importsFor = index.getImportsFor(symbol, true);
  70.240 -                // TODO - insert symbols   + " (whole module)"
  70.241 -                if (importsFor.size() > 0) {
  70.242 -                    if (importsFor.size() > 1) {
  70.243 -                        List<String> l = new ArrayList<>(importsFor);
  70.244 -                        Collections.sort(l);
  70.245 -                        importsFor = l;
  70.246 -                    }
  70.247 -                    List<String> list = alternatives.get(symbol);
  70.248 -                    if (list == null) {
  70.249 -                        list = new ArrayList<>();
  70.250 -                        alternatives.put(symbol, list);
  70.251 -                    }
  70.252 -                    for (String s : importsFor) {
  70.253 -                        if (!list.contains(s)) {
  70.254 -                            list.add(s);
  70.255 -                        }
  70.256 -                    }
  70.257 -                    if (list.size() > 1) {
  70.258 -                        ambiguous = true;
  70.259 -                    }
  70.260 -
  70.261 -                // TODO - if it's a call, try to match functions instead of imported symbols
  70.262 -                } else {
  70.263 -                    ambiguous = true;
  70.264 -                }
  70.265 -            }
  70.266 -
  70.267 -        // TODO - look up -functions- and -data- defined across all modules
  70.268 -        // that might define these guys
  70.269 -
  70.270 -        }
  70.271 -
  70.272 -        List<String> unambiguousNames = new ArrayList<>();
  70.273 -        for (Map.Entry<String, List<String>> entry : alternatives.entrySet()) {
  70.274 -            List<String> list = entry.getValue();
  70.275 -            if (list == null || list.size() == 0) {
  70.276 -                ambiguous = true;
  70.277 -            } else if (list.size() == 1) {
  70.278 -                String key = entry.getKey();
  70.279 -                unambiguousNames.add(key);
  70.280 -            }
  70.281 -        }
  70.282 -
  70.283 -        // If we've had to choose certain libraries (e.g. because they're the
  70.284 -        // only choice available in some cases) then make those libraries default
  70.285 -        // for all the ambiguous cases as well
  70.286 -        if (!unambiguousNames.isEmpty()) {
  70.287 -            for (String name : alternatives.keySet()) {
  70.288 -                List<String> list = alternatives.get(name);
  70.289 -                for (String choice : list) {
  70.290 -                    if (unambiguousNames.contains(choice)) {
  70.291 -                        defaults.put(name, choice);
  70.292 -                    }
  70.293 -                }
  70.294 -            }
  70.295 -        }
  70.296 -
  70.297 -        unused.addAll(symbolTable.getUnusedImports());
  70.298 -
  70.299 -// During development
  70.300 -//ambiguous = true;
  70.301 -
  70.302 -        return ambiguous;
  70.303 -    }
  70.304 -
  70.305 -    public void apply(EditList edits, String[] selections, Set<ImportEntry> removeEntries, Set<ImportEntry> duplicates) {
  70.306 -        // Update the imports
  70.307 -        // Sort the imports
  70.308 -        // Delete the unused imports
  70.309 -        boolean apply = false;
  70.310 -        if (edits == null) {
  70.311 -            edits = new EditList(doc);
  70.312 -            apply = true;
  70.313 -        }
  70.314 -
  70.315 -        Set<PythonTree> removedAlready = new HashSet<>();
  70.316 -
  70.317 -        Set<PythonTree> mainImport;
  70.318 -        //if (sortImports) {
  70.319 -        mainImport = new HashSet<>(mainImports);
  70.320 -        //} else {
  70.321 -        //    mainImport = Collections.<PythonTree>emptySet();
  70.322 -        //}
  70.323 -        Set<PythonTree> topLevel = topLevelImports;
  70.324 -
  70.325 -//
  70.326 -//        // Remove duplicates. Note - these are always removed, not just commented out.
  70.327 -//        if (duplicates.size() > 0 && cleanup != ImportCleanupStyle.LEAVE_ALONE) {
  70.328 -//            Set<PythonTree> candidates = new HashSet<PythonTree>();
  70.329 -//            // Map from import node to list of names that should be removed, if only some are duplicates
  70.330 -//            Map<PythonTree,List<String>> names = new HashMap<PythonTree,List<String>>();
  70.331 -//            // Find the corresponding import
  70.332 -//            //List<PythonTree> candidates = new ArrayList<PythonTree>();
  70.333 -//            boolean foundFirst = false;
  70.334 -//            for (Import imp : imports) {
  70.335 -//                if (imp.names != null) {
  70.336 -//                    boolean all = true;
  70.337 -//                    boolean some = false;
  70.338 -//                    for (alias at : imp.getInternalNames()) {
  70.339 -//                        if (duplicates.contains(at.getInternalName())) {
  70.340 -//                            if (!foundFirst) {
  70.341 -//                                foundFirst = true;
  70.342 -//                            } else {
  70.343 -//                                some = true;
  70.344 -//                                List<String> nameList = names.get(imp);
  70.345 -//                                if (nameList == null) {
  70.346 -//                                    nameList = new ArrayList<String>();
  70.347 -//                                    names.put(imp, nameList);
  70.348 -//                                }
  70.349 -//                                nameList.add(at.getInternalName());
  70.350 -//                            }
  70.351 -//                            break;
  70.352 -//                        } else {
  70.353 -//                            all = false;
  70.354 -//                        }
  70.355 -//                    }
  70.356 -//                    if (some) {
  70.357 -//                        candidates.add(imp);
  70.358 -//                        if (all) {
  70.359 -//                            // No need to limit deletion to just one
  70.360 -//                            names.put(imp, null);
  70.361 -//                        }
  70.362 -//                    }
  70.363 -//                }
  70.364 -//            }
  70.365 -//
  70.366 -//            for (ImportFrom from : importsFrom) {
  70.367 -//                if (from.names != null) {
  70.368 -//                    boolean all = true;
  70.369 -//                    boolean some = false;
  70.370 -//                    for (alias at : from.names) {
  70.371 -//                        assert at.getInternalName() != null;
  70.372 -//                        String value;
  70.373 -//                        if (at.getInternalAsname() != null) {
  70.374 -//                            value = from.module + ":" + at.getInternalName() + ":" + at.getInternalAsname();
  70.375 -//                        } else {
  70.376 -//                            value = from.module + ":" + at.getInternalName();
  70.377 -//                        }
  70.378 -//                        if (duplicates.contains(value)) {
  70.379 -//                            if (!foundFirst) {
  70.380 -//                                foundFirst = true;
  70.381 -//                            } else {
  70.382 -//                                some = true;
  70.383 -//                                List<String> nameList = names.get(from);
  70.384 -//                                if (nameList == null) {
  70.385 -//                                    nameList = new ArrayList<String>();
  70.386 -//                                    names.put(from, nameList);
  70.387 -//                                }
  70.388 -//                                nameList.add(at.getInternalName());
  70.389 -//                            }
  70.390 -//                        } else {
  70.391 -//                            all = false;
  70.392 -//                        }
  70.393 -//                    }
  70.394 -//                    if (some) {
  70.395 -//                        candidates.add(from);
  70.396 -//                        if (all) {
  70.397 -//                            // No need to limit deletion to just one
  70.398 -//                            names.put(from, null);
  70.399 -//                        }
  70.400 -//                    }
  70.401 -//                }
  70.402 -//            }
  70.403 -//
  70.404 -//            Set<PythonTree> filtered = new HashSet<PythonTree>();
  70.405 -//            for (PythonTree node : candidates) {
  70.406 -//                if (!mainImport.contains(node) && topLevel.contains(node)) {
  70.407 -//                    filtered.add(node);
  70.408 -//                }
  70.409 -//            }
  70.410 -//
  70.411 -//            removedAlready.addAll(filtered);
  70.412 -//
  70.413 -//            // Note - we always REMOVE duplicate imports rather than just commenting
  70.414 -//            // them out. We may sometimes be wrong about unused imports, so we let
  70.415 -//            // users leave them commented out when we clean up to make it easier
  70.416 -//            // to backtrack if we were wrong. However, duplicate imports is something
  70.417 -//            // we can accurately detect and leaving them commented out isn't something
  70.418 -//            // users will probably want.
  70.419 -//            removeImports(edits, filtered, /*commentOut*/false, names);
  70.420 -//        }
  70.421 -
  70.422 -        if (cleanup == ImportCleanupStyle.LEAVE_ALONE) {
  70.423 -            removeEntries.clear();
  70.424 -        } else {
  70.425 -            Set<ImportEntry> newSet = new HashSet<>();
  70.426 -            Set<PythonTree> filtered = new HashSet<>();
  70.427 -            for (ImportEntry entry : removeEntries) {
  70.428 -                PythonTree node = entry.node;
  70.429 -                if (!mainImport.contains(node) && topLevel.contains(node)) {
  70.430 -                    filtered.add(node);
  70.431 -                } else {
  70.432 -                    if (removeDuplicates) {
  70.433 -                        entry.node = null;
  70.434 -                    }
  70.435 -                    if (sortImports) {
  70.436 -                        entry.ordinal = 0;
  70.437 -                    }
  70.438 -                    if (!separateFromImps) {
  70.439 -                        entry.sortedFrom = false;
  70.440 -                    }
  70.441 -                }
  70.442 -
  70.443 -                newSet.add(entry);
  70.444 -            }
  70.445 -            removeEntries = newSet;
  70.446 -//        int ordinal = 0;
  70.447 -//        if (unused.size() > 0 && cleanup != ImportCleanupStyle.LEAVE_ALONE) {
  70.448 -//            Set<PythonTree> candidates = new HashSet<PythonTree>();
  70.449 -//            Map<PythonTree,List<String>> names = new HashMap<PythonTree,List<String>>();
  70.450 -//            // Find the corresponding import
  70.451 -//            //List<PythonTree> candidates = new ArrayList<PythonTree>();
  70.452 -//            for (Import imp : imports) {
  70.453 -//                if (imp.names != null) {
  70.454 -//                    boolean all = true;
  70.455 -//                    boolean some = false;
  70.456 -//                    for (alias at : imp.getInternalNames()) {
  70.457 -//                        if (unused.contains(at.getInternalName())) {
  70.458 -//                            some = true;
  70.459 -//                            List<String> nameList = names.get(imp);
  70.460 -//                            if (nameList == null) {
  70.461 -//                                nameList = new ArrayList<String>();
  70.462 -//                                names.put(imp, nameList);
  70.463 -//                            }
  70.464 -//                            nameList.add(at.getInternalName());
  70.465 -//
  70.466 -//                            boolean isSystem = false; // Don't care what it is for deletion
  70.467 -//                            removeEntries.add(new ImportEntry(at.getInternalName(), at.getInternalAsname(), isSystem,
  70.468 -//                                    removeDuplicates ? null : imp,
  70.469 -//                                    sortImports ? 0 : ordinal++));
  70.470 -//                          break;
  70.471 -//                        } else {
  70.472 -//                            all = false;
  70.473 -//                        }
  70.474 -//                    }
  70.475 -//
  70.476 -//                    if (some) {
  70.477 -//                        candidates.add(imp);
  70.478 -//                        if (all) {
  70.479 -//                            // No need to limit deletion to just one
  70.480 -//                            names.put(imp, null);
  70.481 -//                        }
  70.482 -//                    }
  70.483 -//                }
  70.484 -//            }
  70.485 -//
  70.486 -//            for (ImportFrom from : importsFrom) {
  70.487 -//                if (from.names != null) {
  70.488 -//                    boolean all = true;
  70.489 -//                    boolean some = false;
  70.490 -//                    for (alias at : from.names) {
  70.491 -//                        boolean isSystem = false; // Don't care what it is for deletion
  70.492 -//
  70.493 -//                        assert at.getInternalName() != null;
  70.494 -//                        String value;
  70.495 -//                        if (at.getInternalAsname() != null) {
  70.496 -//                            value = from.module + ":" + at.getInternalName() + ":" + at.getInternalAsname();
  70.497 -//                        } else {
  70.498 -//                            value = from.module + ":" + at.getInternalName();
  70.499 -//                        }
  70.500 -//                        if (unused.contains(value)) {
  70.501 -//                            removeEntries.add(new ImportEntry(from.module, at.getInternalName(), at.getInternalAsname(), isSystem,
  70.502 -//                                    removeDuplicates ? null : from,
  70.503 -//                                    sortImports ? 0 : ordinal++));
  70.504 -//                            some = true;
  70.505 -//                            List<String> nameList = names.get(from);
  70.506 -//                            if (nameList == null) {
  70.507 -//                                nameList = new ArrayList<String>();
  70.508 -//                                names.put(from, nameList);
  70.509 -//                            }
  70.510 -//                            nameList.add(at.getInternalName());
  70.511 -//                        } else {
  70.512 -//                            all = false;
  70.513 -//                        }
  70.514 -//                    }
  70.515 -//                    if (some) {
  70.516 -//                        candidates.add(from);
  70.517 -//                        if (all) {
  70.518 -//                            // No need to limit deletion to just one
  70.519 -//                            names.put(from, null);
  70.520 -//                        }
  70.521 -//                    }
  70.522 -//                }
  70.523 -//            }
  70.524 -//
  70.525 -//            // Don't try to delete nodes we've already deleted or commented out
  70.526 -//            // because they are unused
  70.527 -//
  70.528 -//            candidates.removeAll(removedAlready);
  70.529 -//
  70.530 -//            Set<PythonTree> filtered = new HashSet<PythonTree>();
  70.531 -//            for (PythonTree node : candidates) {
  70.532 -//                if (!mainImport.contains(node) && topLevel.contains(node)) {
  70.533 -//                    filtered.add(node);
  70.534 -//                }
  70.535 -//            }
  70.536 -
  70.537 -            removeImports(edits, filtered, cleanup == ImportCleanupStyle.COMMENT_OUT, null);
  70.538 -        }
  70.539 -
  70.540 -        PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
  70.541 -
  70.542 -        Collection<ImportEntry> newEntries = new ArrayList<>();
  70.543 -        if (selections != null) {
  70.544 -            for (String module : selections) {
  70.545 -                if (module.startsWith("<html>")) { // NOI18N
  70.546 -                    // Skip cannot resolve stuff
  70.547 -                    continue;
  70.548 -                }
  70.549 -                int colon = module.indexOf(':');
  70.550 -                if (colon != -1) {
  70.551 -                    int end = module.indexOf('(', colon + 1);
  70.552 -                    if (end == -1) {
  70.553 -                        end = module.indexOf(';', colon + 1);
  70.554 -                        if (end == -1) {
  70.555 -                            end = module.length();
  70.556 -                        }
  70.557 -                    }
  70.558 -                    String symbol = module.substring(colon + 1, end).trim();
  70.559 -                    module = module.substring(0, colon).trim();
  70.560 -                    boolean isSystem = systemLibsFirst && index.isSystemModule(module);
  70.561 -                    ImportEntry importEntry = new ImportEntry(module, symbol, null, isSystem, null, 0);
  70.562 -                    if (!separateFromImps) {
  70.563 -                        importEntry.sortedFrom = false;
  70.564 -                    }
  70.565 -                    newEntries.add(importEntry);
  70.566 -                } else {
  70.567 -                    boolean isSystem = systemLibsFirst && index.isSystemModule(module);
  70.568 -                    ImportEntry importEntry = new ImportEntry(module, null, null, isSystem, null, 0);
  70.569 -                    if (!separateFromImps) {
  70.570 -                        importEntry.sortedFrom = false;
  70.571 -                    }
  70.572 -                    newEntries.add(importEntry);
  70.573 -                }
  70.574 -            }
  70.575 -        }
  70.576 -
  70.577 -        rewriteMainImports(edits, newEntries, removeEntries);
  70.578 -
  70.579 -        if (apply) {
  70.580 -            edits.apply();
  70.581 -        }
  70.582 -    }
  70.583 -
  70.584 -    public boolean isTopLevel(PythonTree node) {
  70.585 -        return topLevelImports.contains(node);
  70.586 -    }
  70.587 -
  70.588 -    /**
  70.589 -     * Remove or comment out the given import statements (Import or ImportFrom).
  70.590 -     * @param edits The edit list to add edits for comment or removal
  70.591 -     * @param candidates The set of Import or ImportFrom nodes
  70.592 -     * @param commentOut If true, comment out the import, or else, delete it
  70.593 -     * @param onlyNames A map from nodes to lists where if the list is null,
  70.594 -     *   remove or comment out the entire import, otherwise comment
  70.595 -     *   or delete only the specified name portions.
  70.596 -     */
  70.597 -    public void removeImports(EditList edits, Set<PythonTree> candidates, boolean commentOut, Map<PythonTree, List<String>> onlyNames) {
  70.598 -        for (PythonTree node : candidates) {
  70.599 -            // Don't touch imports that aren't top level!!!
  70.600 -            // These can be inside If blocks and such so we don't
  70.601 -            // have enough knowledge to mess with them
  70.602 -            if (!isTopLevel(node)) {
  70.603 -                continue;
  70.604 -            }
  70.605 -
  70.606 -            OffsetRange astRange = PythonAstUtils.getRange(node);
  70.607 -            OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
  70.608 -            if (lexRange == OffsetRange.NONE) {
  70.609 -                continue;
  70.610 -            }
  70.611 -
  70.612 -            List<String> names = onlyNames.get(node);
  70.613 -            if (names != null) {
  70.614 -
  70.615 -                // TODO Handle commenting out portions of a line! An idea which
  70.616 -                // might work is to replace the whole import with a new import
  70.617 -                // that moves the commented out portions to the end!!
  70.618 -
  70.619 -                // Only delete/comment out a portion of the line
  70.620 -//                if (commentOut) {
  70.621 -// TODO
  70.622 -//                } else {
  70.623 -                // Determine offsets within the line
  70.624 -                List<OffsetRange> ranges = new ArrayList<>();
  70.625 -                try {
  70.626 -                    int start = lexRange.getStart();
  70.627 -                    int end = lexRange.getEnd();
  70.628 -                    if (end > doc.getLength()) {
  70.629 -                        end = doc.getLength();
  70.630 -                        if (start > doc.getLength()) {
  70.631 -                            start = doc.getLength();
  70.632 -                        }
  70.633 -                    }
  70.634 -                    String line = doc.getText(start, end - start);
  70.635 -                    for (String name : names) {
  70.636 -                        int index = line.indexOf(name);
  70.637 -                        if (index != -1) {
  70.638 -                            int nameEnd = index + name.length();
  70.639 -                            boolean removedComma = false;
  70.640 -                            for (int i = nameEnd; i < line.length(); i++) {
  70.641 -                                char c = line.charAt(i);
  70.642 -                                if (c == ',') {
  70.643 -                                    removedComma = true;
  70.644 -                                    nameEnd = i + 1;
  70.645 -                                    if (nameEnd < line.length() && line.charAt(nameEnd) == ' ') {
  70.646 -                                        // Include space after comma in deletion
  70.647 -                                        nameEnd++;
  70.648 -                                    }
  70.649 -                                    break;
  70.650 -                                } else if (c == ' ' || c == '\t') {
  70.651 -                                    continue;
  70.652 -                                } else {
  70.653 -                                    break;
  70.654 -                                }
  70.655 -                            }
  70.656 -                            if (!removedComma) {
  70.657 -                                // If I removed the last name on the line there is no
  70.658 -                                // comma at the end, so I should try removing one -before-
  70.659 -                                // the name instead
  70.660 -                                for (int i = index - 1; i >= 0; i--) {
  70.661 -                                    char c = line.charAt(i);
  70.662 -                                    if (c == ',') {
  70.663 -                                        index = i;
  70.664 -                                        break;
  70.665 -                                    } else if (c == ' ' || c == '\t') {
  70.666 -                                        continue;
  70.667 -                                    } else {
  70.668 -                                        break;
  70.669 -                                    }
  70.670 -                                }
  70.671 -                            }
  70.672 -                            OffsetRange remove = new OffsetRange(start + index, start + nameEnd);
  70.673 -
  70.674 -                            // Prevent overlaps
  70.675 -                            for (OffsetRange range : ranges) {
  70.676 -                                if (range.overlaps(remove)) {
  70.677 -                                    if (range.getStart() < remove.getStart()) {
  70.678 -                                        remove = new OffsetRange(range.getEnd(), Math.max(remove.getEnd(), range.getEnd()));
  70.679 -                                    } else {
  70.680 -                                        remove = new OffsetRange(Math.min(remove.getStart(), range.getStart()), range.getStart());
  70.681 -                                    }
  70.682 -                                }
  70.683 -                            }
  70.684 -
  70.685 -                            ranges.add(remove);
  70.686 -                        }
  70.687 -                    }
  70.688 -                    int prio = 0;
  70.689 -                    for (OffsetRange range : ranges) {
  70.690 -                        edits.replace(range.getStart(), range.getLength(), null, false, prio++);
  70.691 -                    }
  70.692 -                } catch (BadLocationException ex) {
  70.693 -                    Exceptions.printStackTrace(ex);
  70.694 -                }
  70.695 -//                }
  70.696 -            } else {
  70.697 -                int start = lexRange.getStart();
  70.698 -                if (commentOut) {
  70.699 -                    edits.replace(start, 0, "#", false, 0); // NOI18N
  70.700 -                } else {
  70.701 -                    int length = lexRange.getLength();
  70.702 -                    // See if this leaves an empty line and if so remove it
  70.703 -                    int endPos = lexRange.getEnd();
  70.704 -                    if (endPos < doc.getLength()) {
  70.705 -                        try {
  70.706 -                            char c = doc.getText(endPos, 1).charAt(0);
  70.707 -                            if (c == '\n') {
  70.708 -                                length++;
  70.709 -                            }
  70.710 -                        } catch (BadLocationException ex) {
  70.711 -                            Exceptions.printStackTrace(ex);
  70.712 -                        }
  70.713 -                    }
  70.714 -                    edits.replace(start, length, null, false, 0);
  70.715 -                }
  70.716 -            }
  70.717 -        }
  70.718 -    }
  70.719 -
  70.720 -    private OffsetRange getMainImportsRange() {
  70.721 -        // Compute editor range required
  70.722 -        int begin = Integer.MAX_VALUE;
  70.723 -        int end = Integer.MIN_VALUE;
  70.724 -        OffsetRange lexRange;
  70.725 -        if (mainImports.size() == 0) {
  70.726 -            if (mainImports.size() == 1) {
  70.727 -                OffsetRange astRange = PythonAstUtils.getRange(mainImports.get(0));
  70.728 -                lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
  70.729 -            } else {
  70.730 -                assert mainImports.size() == 0;
  70.731 -                begin = getImportsLexOffset(null);
  70.732 -                end = begin;
  70.733 -                lexRange = new OffsetRange(begin, end);
  70.734 -            }
  70.735 -        } else {
  70.736 -            for (PythonTree node : mainImports) {
  70.737 -                OffsetRange range = PythonAstUtils.getRange(node);
  70.738 -                if (range.getStart() < begin) {
  70.739 -                    begin = range.getStart();
  70.740 -                }
  70.741 -                if (range.getEnd() > end) {
  70.742 -                    end = range.getEnd();
  70.743 -                }
  70.744 -            }
  70.745 -            OffsetRange astReplace = new OffsetRange(begin, end);
  70.746 -            lexRange = PythonLexerUtils.getLexerOffsets(info, astReplace);
  70.747 -        }
  70.748 -
  70.749 -        return lexRange;
  70.750 -    }
  70.751 -
  70.752 -    public void rewriteMainImports(EditList edits, Collection<ImportEntry> newEntries, Set<ImportEntry> remove) {
  70.753 -        // Items to be deleted should be deleted after this
  70.754 -
  70.755 -        PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
  70.756 -
  70.757 -        // TODO:
  70.758 -        // Look for comments to preserve
  70.759 -        // Replace the entire editor block
  70.760 -        Set<ImportEntry> entries = new HashSet<>();
  70.761 -        int ordinal = 0;
  70.762 -        for (PythonTree node : mainImports) {
  70.763 -            if (node instanceof Import) {
  70.764 -                Import imp = (Import)node;
  70.765 -                // TODO - look up for at.getInternalName()!
  70.766 -                List<alias> names = imp.getInternalNames();
  70.767 -                if (names != null) {
  70.768 -                    for (alias at : names) {
  70.769 -                        ImportEntry importEntry = new ImportEntry(at.getInternalName(), at.getInternalAsname(), systemLibsFirst && index.isSystemModule(at.getInternalName()),
  70.770 -                                removeDuplicates ? null : imp, sortImports ? 0 : ordinal++);
  70.771 -                        if (!separateFromImps) {
  70.772 -                            importEntry.sortedFrom = false;
  70.773 -                        }
  70.774 -                        entries.add(importEntry);
  70.775 -                    }
  70.776 -                }
  70.777 -            } else {
  70.778 -                assert node instanceof ImportFrom;
  70.779 -                ImportFrom imp = (ImportFrom)node;
  70.780 -                List<alias> names = imp.getInternalNames();
  70.781 -                if (names != null && names.size() > 0) {
  70.782 -                    // TODO - look up for imp.getInternalModule()!
  70.783 -                    boolean isSystemLibrary = systemLibsFirst && index.isSystemModule(imp.getInternalModule());
  70.784 -                    for (alias at : names) {
  70.785 -                        ImportEntry importEntry = new ImportEntry(imp.getInternalModule(), at.getInternalName(), at.getInternalAsname(), isSystemLibrary,
  70.786 -                                removeDuplicates ? null : imp, sortImports ? 0 : ordinal++);
  70.787 -                        if (!separateFromImps) {
  70.788 -                            importEntry.sortedFrom = false;
  70.789 -                        }
  70.790 -                        entries.add(importEntry);
  70.791 -                    }
  70.792 -                }
  70.793 -            }
  70.794 -        }
  70.795 -
  70.796 -        // Add in entries discovered as needed by the import manager
  70.797 -        if (newEntries.size() > 0) {
  70.798 -            entries.addAll(newEntries);
  70.799 -        }
  70.800 -
  70.801 -        // Remove any items that needs to be removed
  70.802 -        if (remove.size() > 0) {
  70.803 -            entries.removeAll(remove);
  70.804 -        }
  70.805 -
  70.806 -        // Sort imports -- first by system/nonsystem, then alphabetically
  70.807 -        List<ImportEntry> sortedEntries = new ArrayList<>(entries);
  70.808 -        Collections.sort(sortedEntries);
  70.809 -
  70.810 -        // Write out existing imports
  70.811 -        StringBuilder sb = new StringBuilder();
  70.812 -        int size = sortedEntries.size();
  70.813 -        if (size > 0) {
  70.814 -            boolean prevSystem = sortedEntries.get(0).isSystem;
  70.815 -
  70.816 -            for (int i = 0; i < size; i++) {
  70.817 -                ImportEntry entry = sortedEntries.get(i);
  70.818 -                if (systemLibsFirst && entry.isSystem != prevSystem) {
  70.819 -                    prevSystem = entry.isSystem;
  70.820 -                    sb.append("\n"); // NOI18N Separate system and regular libs
  70.821 -                }
  70.822 -
  70.823 -                if (entry.isFromImport) {
  70.824 -                    int start = sb.length();
  70.825 -                    sb.append("from "); // NOI18N
  70.826 -                    sb.append(entry.module);
  70.827 -                    sb.append(" import "); // NOI18N
  70.828 -                    sb.append(entry.symbol);
  70.829 -                    if (entry.asName != null) {
  70.830 -                        sb.append(" as "); // NOI18N
  70.831 -                        sb.append(entry.asName);
  70.832 -                    }
  70.833 -
  70.834 -                    if (!splitImports) {
  70.835 -                        // Look ahead and combine subsequent entries
  70.836 -                        int lookahead = i + 1;
  70.837 -                        for (; lookahead < size; lookahead++) {
  70.838 -                            ImportEntry next = sortedEntries.get(lookahead);
  70.839 -                            if (next.isFromImport != entry.isFromImport ||
  70.840 -                                    !next.module.equals(entry.module)) {
  70.841 -                                break;
  70.842 -                            }
  70.843 -                            sb.append(", "); // NOI18N
  70.844 -
  70.845 -                            if (sb.length() - start > rightMargin && (rightMargin > 30)) {
  70.846 -                                sb.append("\\\n");
  70.847 -                                start = sb.length();
  70.848 -                                sb.append(IndentUtils.createIndentString(doc, IndentUtils.indentLevelSize(doc)));
  70.849 -                            }
  70.850 -
  70.851 -                            sb.append(next.symbol);
  70.852 -                            if (next.asName != null) {
  70.853 -                                sb.append(" as ");
  70.854 -                                sb.append(next.asName);
  70.855 -                            }
  70.856 -                        }
  70.857 -                        i = lookahead - 1;
  70.858 -                    }
  70.859 -                    sb.append("\n"); // NOI18N
  70.860 -                } else {
  70.861 -                    // Plain import
  70.862 -                    // We never combine imports
  70.863 -                    sb.append("import "); // NOI18N
  70.864 -                    sb.append(entry.module);
  70.865 -                    if (entry.asName != null) {
  70.866 -                        sb.append(" as "); // NOI18N
  70.867 -                        sb.append(entry.asName);
  70.868 -                    }
  70.869 -                    sb.append("\n"); // NOI18N
  70.870 -                }
  70.871 -            }
  70.872 -        }
  70.873 -
  70.874 -        // Write commented out deleted entries as well
  70.875 -        if (remove.size() > 0 && cleanup == ImportCleanupStyle.COMMENT_OUT) {
  70.876 -            size = remove.size();
  70.877 -            List<ImportEntry> sortedRemove = new ArrayList<>();
  70.878 -            sortedRemove.addAll(remove);
  70.879 -            Collections.sort(sortedRemove);
  70.880 -            for (ImportEntry entry : sortedRemove) {
  70.881 -                if (entry.isFromImport) {
  70.882 -                    sb.append("#from "); // NOI18N
  70.883 -                    sb.append(entry.module);
  70.884 -                    sb.append(" import "); // NOI18N
  70.885 -                    sb.append(entry.symbol);
  70.886 -                    if (entry.asName != null) {
  70.887 -                        sb.append(" as "); // NOI18N
  70.888 -                        sb.append(entry.asName);
  70.889 -                    }
  70.890 -                    sb.append("\n"); // NOI18N
  70.891 -                } else {
  70.892 -                    sb.append("#import "); // NOI18N
  70.893 -                    sb.append(entry.module);
  70.894 -                    if (entry.asName != null) {
  70.895 -                        sb.append(" as "); // NOI18N
  70.896 -                        sb.append(entry.asName);
  70.897 -                    }
  70.898 -                    sb.append("\n"); // NOI18N
  70.899 -                }
  70.900 -            }
  70.901 -        }
  70.902 -
  70.903 -        // Compute editor range required
  70.904 -        OffsetRange lexRange = getMainImportsRange();
  70.905 -
  70.906 -        // Replace final newline if it's there so we don't grow whitespace around the imports
  70.907 -        int lastNewlineDelta = 0;
  70.908 -        try {
  70.909 -            if (lexRange.getEnd() < doc.getLength() && doc.getText(lexRange.getEnd(), 1).charAt(0) == '\n') {
  70.910 -                lastNewlineDelta++;
  70.911 -            }
  70.912 -        } catch (BadLocationException ex) {
  70.913 -            Exceptions.printStackTrace(ex);
  70.914 -        }
  70.915 -
  70.916 -        edits.replace(lexRange.getStart(), lexRange.getLength() + lastNewlineDelta, sb.toString(), false, 0);
  70.917 -    }
  70.918 -
  70.919 -    /** Compute the location where the main import block should be located */
  70.920 -    public int getImportsLexOffset(String module) {
  70.921 -        int begin = 0;
  70.922 -
  70.923 -        // First try computing a position in the standard imports
  70.924 -        if (module != null) {
  70.925 -            PythonTree last = null;
  70.926 -            for (PythonTree node : mainImports) {
  70.927 -                boolean stop = false;
  70.928 -                if (node instanceof Import) {
  70.929 -                    Import imp = (Import)node;
  70.930 -                    List<alias> names = imp.getInternalNames();
  70.931 -                    if (names != null && names.size() > 0 &&
  70.932 -                            names.get(0).getInternalName().compareTo(module) >= 0) {
  70.933 -                        stop = true;
  70.934 -                    }
  70.935 -                } else {
  70.936 -                    assert node instanceof ImportFrom;
  70.937 -                    ImportFrom imp = (ImportFrom)node;
  70.938 -                    if (imp.getInternalModule().compareTo(module) >= 0) {
  70.939 -                        stop = true;
  70.940 -                    }
  70.941 -                }
  70.942 -
  70.943 -                if (stop) {
  70.944 -                    return PythonLexerUtils.getLexerOffsets(info,
  70.945 -                            PythonAstUtils.getRange(node)).getStart();
  70.946 -                }
  70.947 -
  70.948 -                last = node;
  70.949 -            }
  70.950 -
  70.951 -            if (last != null) {
  70.952 -                return PythonLexerUtils.getLexerOffsets(info,
  70.953 -                        PythonAstUtils.getRange(last)).getStart();
  70.954 -            }
  70.955 -        }
  70.956 -
  70.957 -        Str documentationNode = PythonAstUtils.getDocumentationNode(root);
  70.958 -        if (documentationNode != null) {
  70.959 -            int astEnd = documentationNode.getCharStopIndex();
  70.960 -            begin = PythonLexerUtils.getLexerOffset(info, astEnd);
  70.961 -            if (begin == -1) {
  70.962 -                begin = 0;
  70.963 -            } else {
  70.964 -                begin = Math.min(doc.getLength(), begin);
  70.965 -                try {
  70.966 -                    begin = Utilities.getRowEnd(doc, begin) + 1;
  70.967 -                    begin = Math.min(begin, doc.getLength());
  70.968 -                } catch (BadLocationException ex) {
  70.969 -                    Exceptions.printStackTrace(ex);
  70.970 -                    begin = 0;
  70.971 -                }
  70.972 -            }
  70.973 -        }
  70.974 -
  70.975 -        // TODO - I should even do a lexical lookup for this in case we're in an embedded scenario!
  70.976 -        return begin;
  70.977 -    }
  70.978 -
  70.979 -    /** Determine if the given module is imported (for the given symbol) */
  70.980 -    public boolean isImported(String module, String ident) {
  70.981 -        for (Import imp : imports) {
  70.982 -            List<alias> names = imp.getInternalNames();
  70.983 -            if (names != null) {
  70.984 -                for (alias at : names) {
  70.985 -                    if (module.equals(at.getInternalName()) && (ident == null || (ident.equals(module) || ident.equals(at.getInternalAsname())))) {
  70.986 -                        return true;
  70.987 -                    }
  70.988 -                }
  70.989 -            }
  70.990 -        }
  70.991 -
  70.992 -        for (ImportFrom from : importsFrom) {
  70.993 -            if (module.equals(from.getInternalModule())) {
  70.994 -                // Make sure -this- symbol hasn't been imported!
  70.995 -                if (ident != null) {
  70.996 -                    List<alias> names = from.getInternalNames();
  70.997 -                    if (names != null) {
  70.998 -                        for (alias at : names) {
  70.999 -                            if (at.getInternalAsname() == null) {
 70.1000 -                                // If you have "from module1 import Class1 as Class2", then
 70.1001 -                                // "Class1" is not already imported, and "Class2" is.
 70.1002 -                                if (ident.equals(at.getInternalName())) {
 70.1003 -                                    return true;
 70.1004 -                                }
 70.1005 -                            } else if (ident.equals(at.getInternalAsname())) {
 70.1006 -                                return true;
 70.1007 -                            }
 70.1008 -                        }
 70.1009 -                    }
 70.1010 -                }
 70.1011 -            }
 70.1012 -        }
 70.1013 -
 70.1014 -        return false;
 70.1015 -    }
 70.1016 -
 70.1017 -    public void ensureImported(String name, String ident, boolean packageImport, boolean useFqn, boolean warnIfExists) {
 70.1018 -        // TODO - look up the splitImports setting and add to existing import if possible...
 70.1019 -
 70.1020 -        if (PythonIndex.isBuiltinModule(name)) {
 70.1021 -            return;
 70.1022 -        }
 70.1023 -
 70.1024 -        // Test whether already imported
 70.1025 -        if (isImported(name, ident)) {
 70.1026 -            if (warnIfExists) {
 70.1027 -                Utilities.setStatusText(EditorRegistry.lastFocusedComponent(),
 70.1028 -                        NbBundle.getMessage(
 70.1029 -                        ImportManager.class,
 70.1030 -                        packageImport ? "MSG_PackageAlreadyImported" : "MSG_ClassAlreadyImported",
 70.1031 -                        name, ident));
 70.1032 -                Toolkit.getDefaultToolkit().beep();
 70.1033 -            }
 70.1034 -            return;
 70.1035 -        }
 70.1036 -
 70.1037 -        int begin = getImportsLexOffset(ident);
 70.1038 -        try {
 70.1039 -            // TODO - warp to the new import and let you edit the "AS" part??
 70.1040 -
 70.1041 -            if (useFqn || ident == null) {
 70.1042 -                doc.insertString(begin, "import " + name + "\n", null); // NOI18N
 70.1043 -            } else if (packageImport) {
 70.1044 -                //doc.insertString(begin, "import " + name + "\n", null); // NOI18N
 70.1045 -                doc.insertString(begin, "from " + name + " import *\n", null); // NOI18N
 70.1046 -            } else {
 70.1047 -                doc.insertString(begin, "from " + name + " import " + ident + "\n", null); // NOI18N
 70.1048 -            }
 70.1049 -        } catch (BadLocationException ble) {
 70.1050 -            Exceptions.printStackTrace(ble);
 70.1051 -        }
 70.1052 -    }
 70.1053 -}
    71.1 --- a/python.editor/src/org/netbeans/modules/python/editor/imports/ImportModulePanel.java	Sat Sep 12 23:03:15 2015 -0700
    71.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/imports/ImportModulePanel.java	Sun Sep 13 11:47:42 2015 +0200
    71.3 @@ -43,6 +43,7 @@
    71.4   */
    71.5  package org.netbeans.modules.python.editor.imports;
    71.6  
    71.7 +import org.netbeans.modules.python.source.ImportManager;
    71.8  import java.awt.Color;
    71.9  import java.awt.Component;
   71.10  import java.awt.Font;
   71.11 @@ -64,9 +65,9 @@
   71.12  import org.netbeans.editor.Utilities;
   71.13  import org.netbeans.modules.csl.api.ElementKind;
   71.14  import org.netbeans.modules.csl.spi.GsfUtilities;
   71.15 -import org.netbeans.modules.python.editor.PythonIndex;
   71.16 -import org.netbeans.modules.python.editor.PythonParserResult;
   71.17 -import org.netbeans.modules.python.editor.lexer.Call;
   71.18 +import org.netbeans.modules.python.source.PythonIndex;
   71.19 +import org.netbeans.modules.python.source.PythonParserResult;
   71.20 +import org.netbeans.modules.python.source.lexer.Call;
   71.21  import org.openide.util.Exceptions;
   71.22  import org.openide.util.ImageUtilities;
   71.23  import org.openide.util.NbBundle;
    72.1 --- a/python.editor/src/org/netbeans/modules/python/editor/layer.xml	Sat Sep 12 23:03:15 2015 -0700
    72.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/layer.xml	Sun Sep 13 11:47:42 2015 +0200
    72.3 @@ -7,11 +7,6 @@
    72.4              <folder name="x-python">
    72.5                  <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.python.editor.Bundle"/>
    72.6  
    72.7 -                <file name="language.instance">
    72.8 -                    <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.editor.lexer.PythonTokenId.language"/>
    72.9 -                    <attr name="instanceOf" stringvalue="org.netbeans.api.lexer.Language"/>
   72.10 -                </file>
   72.11 -
   72.12                  <folder name="Actions">
   72.13                      <file name="org-netbeans-modules-python-editor-imports-FixImportsAction.instance"/>
   72.14                      <file name="org-netbeans-modules-python-editor-imports-FastImportAction.instance"/>
   72.15 @@ -142,37 +137,6 @@
   72.16          </folder>
   72.17      </folder>
   72.18      
   72.19 -    <folder name="csl-hints">
   72.20 -        <folder name="text">
   72.21 -            <folder name="x-python">
   72.22 -                <folder name="hints">
   72.23 -                    <folder name="general">
   72.24 -                        <attr name="position" intvalue="100"/>
   72.25 -                        <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.python.editor.hints.Bundle"/>
   72.26 -                        <file name="org-netbeans-modules-python-editor-hints-NameRule.instance"/>
   72.27 -                        <file name="org-netbeans-modules-python-editor-hints-CreateDocString.instance"/>
   72.28 -                        <file name="org-netbeans-modules-python-editor-hints-AssignToVariable.instance"/>
   72.29 -                        <file name="org-netbeans-modules-python-editor-hints-SplitImports.instance"/>
   72.30 -                        <file name="org-netbeans-modules-python-editor-hints-RelativeImports.instance"/>
   72.31 -                        <file name="org-netbeans-modules-python-editor-hints-Deprecations.instance"/>
   72.32 -                        <file name="org-netbeans-modules-python-editor-hints-UnusedImports.instance"/>
   72.33 -                        <file name="org-netbeans-modules-python-editor-hints-UnusedDetector.instance"/>
   72.34 -                        <file name="org-netbeans-modules-python-editor-hints-UnresolvedDetector.instance"/>
   72.35 -                        <file name="org-netbeans-modules-python-editor-hints-UnresolvedClassComponents.instance"/>
   72.36 -                        <file name="org-netbeans-modules-python-editor-hints-AllAssignExists.instance"/>
   72.37 -                        <file name="org-netbeans-modules-python-editor-hints-AccessToProtected.instance"/>
   72.38 -                        <file name="org-netbeans-modules-python-editor-hints-AttributeDefinedOutsideInit.instance"/>
   72.39 -                        <file name="org-netbeans-modules-python-editor-hints-ClassCircularRedundancy.instance"/>
   72.40 -                    </folder>
   72.41 -                </folder>
   72.42 -                <folder name="selection">
   72.43 -                    <file name="org-netbeans-modules-python-editor-hints-SurroundWith.instance"/>
   72.44 -                    <file name="org-netbeans-modules-python-editor-hints-ExtractCode.instance"/>
   72.45 -                </folder>
   72.46 -            </folder>
   72.47 -        </folder>
   72.48 -    </folder>
   72.49 -    
   72.50      <folder name="CslPlugins">
   72.51          <folder name="text">
   72.52              <folder name="x-python">
   72.53 @@ -180,12 +144,6 @@
   72.54  <!--                    <attr name="instanceOf" stringvalue="org.netbeans.modules.gsf.api.GsfLanguage"/>-->
   72.55                      <attr name="instanceClass" stringvalue="org.netbeans.modules.python.editor.PythonLanguage"/>
   72.56                  </file>
   72.57 -                <file name="structure.instance">
   72.58 -                    <attr name="instanceClass" stringvalue="org.netbeans.modules.python.editor.PythonStructureScanner"/>
   72.59 -                </file>
   72.60 -                <file name="hints.instance">
   72.61 -                    <attr name="instanceClass" stringvalue="org.netbeans.modules.python.editor.hints.PythonHintsProvider"/>
   72.62 -                </file>
   72.63                  <file name="codecoverage"/>
   72.64              </folder>
   72.65          </folder>
   72.66 @@ -272,66 +230,6 @@
   72.67          </folder>
   72.68      </folder>
   72.69  
   72.70 -    <folder name="OptionsDialog">
   72.71 -        <folder name="PreviewExamples">
   72.72 -            <folder name="text">
   72.73 -                <file name="x-python" url="PythonExample.py"/>
   72.74 -            </folder>
   72.75 -        </folder>
   72.76 -        <folder name="Editor">
   72.77 -            <folder name="Hints">
   72.78 -                <attr name="position" intvalue="0"/>
   72.79 -                <folder name="text">
   72.80 -                    <folder name="x-python">
   72.81 -                        <file name="PythonHints.instance">
   72.82 -                            <attr name="instanceOf" stringvalue="org.netbeans.spi.options.OptionsPanelController"/>
   72.83 -                            <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.editor.PythonHintOptions.createStatic"/>
   72.84 -                        </file>
   72.85 -                    </folder>
   72.86 -                </folder>
   72.87 -            </folder>
   72.88 -            <folder name="Formatting">
   72.89 -                <attr name="position" intvalue="0"/>
   72.90 -                <folder name="text">
   72.91 -                    <folder name="x-python">
   72.92 -                        <file name="Imports.instance">
   72.93 -                            <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
   72.94 -                            <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.editor.options.FmtImports.getController"/>
   72.95 -                            <attr name="position" intvalue="150"/>
   72.96 -                        </file>
   72.97 -                      <!-- Not yet implemented
   72.98 -                      <file name="TabsAndIndents.instance">
   72.99 -                          <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  72.100 -                          <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.editor.options.FmtTabsIndents.getController"/>
  72.101 -                          <attr name="position" intvalue="100"/>
  72.102 -                      </file>
  72.103 -                      <file name="Alignment.instance">
  72.104 -                          <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  72.105 -                          <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.editor.options.FmtAlignment.getController"/>
  72.106 -                          <attr name="position" intvalue="200"/>
  72.107 -                      </file>
  72.108 -                      <file name="Wrapping.instance">
  72.109 -                          <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  72.110 -                          <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.editor.options.FmtWrapping.getController"/>
  72.111 -                          <attr name="position" intvalue="400"/>
  72.112 -                      </file>
  72.113 -                      <file name="BlankLines.instance">
  72.114 -                          <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  72.115 -                          <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.editor.options.FmtBlankLines.getController"/>
  72.116 -                          <attr name="position" intvalue="500"/>
  72.117 -                      </file>
  72.118 -                      -->
  72.119 -                        <file name="Spaces.instance">
  72.120 -                            <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  72.121 -                            <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.editor.options.FmtSpaces.getController"/>
  72.122 -                            <attr name="position" intvalue="600"/>
  72.123 -                        </file>
  72.124 -                    </folder>
  72.125 -                </folder>
  72.126 -            </folder>
  72.127 -        </folder>
  72.128 -    </folder>
  72.129 -
  72.130      <folder name="Templates">
  72.131          <folder name="Python">
  72.132              <attr name="position" intvalue="1403"/>
    73.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/Call.java	Sat Sep 12 23:03:15 2015 -0700
    73.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.3 @@ -1,322 +0,0 @@
    73.4 -/*
    73.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    73.6 - *
    73.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    73.8 - *
    73.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   73.10 - * Other names may be trademarks of their respective owners.
   73.11 - *
   73.12 - * The contents of this file are subject to the terms of either the GNU
   73.13 - * General Public License Version 2 only ("GPL") or the Common
   73.14 - * Development and Distribution License("CDDL") (collectively, the
   73.15 - * "License"). You may not use this file except in compliance with the
   73.16 - * License. You can obtain a copy of the License at
   73.17 - * http://www.netbeans.org/cddl-gplv2.html
   73.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   73.19 - * specific language governing permissions and limitations under the
   73.20 - * License.  When distributing the software, include this License Header
   73.21 - * Notice in each file and include the License file at
   73.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   73.23 - * particular file as subject to the "Classpath" exception as provided
   73.24 - * by Oracle in the GPL Version 2 section of the License file that
   73.25 - * accompanied this code. If applicable, add the following below the
   73.26 - * License Header, with the fields enclosed by brackets [] replaced by
   73.27 - * your own identifying information:
   73.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   73.29 - *
   73.30 - * Contributor(s):
   73.31 - *
   73.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   73.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   73.34 - * Microsystems, Inc. All Rights Reserved.
   73.35 - *
   73.36 - * If you wish your version of this file to be governed by only the CDDL
   73.37 - * or only the GPL Version 2, indicate your decision by adding
   73.38 - * "[Contributor] elects to include this software in this distribution
   73.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   73.40 - * single choice of license, a recipient has the option to distribute
   73.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   73.42 - * to extend the choice of license to its licensees as provided above.
   73.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   73.44 - * Version 2 license, then the option applies only if the new code is
   73.45 - * made subject to such option by the copyright holder.
   73.46 - */
   73.47 -package org.netbeans.modules.python.editor.lexer;
   73.48 -
   73.49 -import javax.swing.text.BadLocationException;
   73.50 -import javax.swing.text.Document;
   73.51 -import org.netbeans.api.annotations.common.NonNull;
   73.52 -
   73.53 -import org.netbeans.api.lexer.Token;
   73.54 -import org.netbeans.api.lexer.TokenHierarchy;
   73.55 -import org.netbeans.api.lexer.TokenId;
   73.56 -import org.netbeans.api.lexer.TokenSequence;
   73.57 -import org.netbeans.editor.BaseDocument;
   73.58 -import org.netbeans.editor.Utilities;
   73.59 -import org.openide.util.Exceptions;
   73.60 -
   73.61 -/**
   73.62 - * Class which represents a Call in the source
   73.63 - */
   73.64 -public class Call {
   73.65 -    public static final Call LOCAL = new Call(null, null, false, false);
   73.66 -    public static final Call NONE = new Call(null, null, false, false);
   73.67 -    public static final Call UNKNOWN = new Call(null, null, false, false);
   73.68 -    private final String type;
   73.69 -    private final String lhs;
   73.70 -    private final boolean isStatic;
   73.71 -    private final boolean methodExpected;
   73.72 -
   73.73 -    public Call(String type, String lhs, boolean isStatic, boolean methodExpected) {
   73.74 -        super();
   73.75 -        this.type = type;
   73.76 -        this.lhs = lhs;
   73.77 -        this.methodExpected = methodExpected;
   73.78 -        if (lhs == null) {
   73.79 -            lhs = type;
   73.80 -        }
   73.81 -        this.isStatic = isStatic;
   73.82 -    }
   73.83 -
   73.84 -    public String getType() {
   73.85 -        return type;
   73.86 -    }
   73.87 -
   73.88 -    public String getLhs() {
   73.89 -        return lhs;
   73.90 -    }
   73.91 -
   73.92 -    public boolean isStatic() {
   73.93 -        return isStatic;
   73.94 -    }
   73.95 -
   73.96 -    public boolean isSimpleIdentifier() {
   73.97 -        if (lhs == null) {
   73.98 -            return false;
   73.99 -        }
  73.100 -        // TODO - replace with the new PythonUtil validations
  73.101 -        for (int i = 0, n = lhs.length(); i < n; i++) {
  73.102 -            char c = lhs.charAt(i);
  73.103 -            if (Character.isJavaIdentifierPart(c)) {
  73.104 -                continue;
  73.105 -            }
  73.106 -            return false;
  73.107 -        }
  73.108 -        return true;
  73.109 -    }
  73.110 -
  73.111 -    @Override
  73.112 -    public String toString() {
  73.113 -        if (this == LOCAL) {
  73.114 -            return "LOCAL";
  73.115 -        } else if (this == NONE) {
  73.116 -            return "NONE";
  73.117 -        } else if (this == UNKNOWN) {
  73.118 -            return "UNKNOWN";
  73.119 -        } else {
  73.120 -            return "Call(" + type + "," + lhs + "," + isStatic + ")";
  73.121 -        }
  73.122 -    }
  73.123 -
  73.124 -    /** foo.| or foo.b|  -> we're expecting a method call. For Foo:: we don't know. */
  73.125 -    public boolean isMethodExpected() {
  73.126 -        return this.methodExpected;
  73.127 -    }
  73.128 -
  73.129 -    /**
  73.130 -     * Determine whether the given offset corresponds to a method call on another
  73.131 -     * object. This would happen in these cases:
  73.132 -     *    Foo::|, Foo::Bar::|, Foo.|, Foo.x|, foo.|, foo.x|
  73.133 -     * and not here:
  73.134 -     *   |, Foo|, foo|
  73.135 -     * The method returns the left hand side token, if any, such as "Foo", Foo::Bar",
  73.136 -     * and "foo". If not, it will return null.
  73.137 -     * Note that "self" and "super" are possible return values for the lhs, which mean
  73.138 -     * that you don't have a call on another object. Clients of this method should
  73.139 -     * handle that return value properly (I could return null here, but clients probably
  73.140 -     * want to distinguish self and super in this case so it's useful to return the info.)
  73.141 -     *
  73.142 -     * This method will also try to be smart such that if you have a block or array
  73.143 -     * call, it will return the relevant classnames (e.g. for [1,2].x| it returns "Array").
  73.144 -     */
  73.145 -    @SuppressWarnings("unchecked")
  73.146 -    @NonNull
  73.147 -    public static Call getCallType(BaseDocument doc, TokenHierarchy<Document> th, int offset) {
  73.148 -        TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(th, offset);
  73.149 -
  73.150 -        if (ts == null) {
  73.151 -            return Call.NONE;
  73.152 -        }
  73.153 -
  73.154 -        ts.move(offset);
  73.155 -
  73.156 -        boolean methodExpected = false;
  73.157 -
  73.158 -        if (!ts.moveNext() && !ts.movePrevious()) {
  73.159 -            return Call.NONE;
  73.160 -        }
  73.161 -
  73.162 -        if (ts.offset() == offset) {
  73.163 -            // We're looking at the offset to the RIGHT of the caret
  73.164 -            // position, which could be whitespace, e.g.
  73.165 -            //  "foo.x| " <-- looking at the whitespace
  73.166 -            ts.movePrevious();
  73.167 -        }
  73.168 -
  73.169 -        Token<? extends PythonTokenId> token = ts.token();
  73.170 -
  73.171 -        if (token != null) {
  73.172 -            TokenId id = token.id();
  73.173 -
  73.174 -            if (id == PythonTokenId.WHITESPACE) {
  73.175 -                return Call.LOCAL;
  73.176 -            }
  73.177 -
  73.178 -            // See if we're in the identifier - "x" in "foo.x"
  73.179 -            // I could also be a keyword in case the prefix happens to currently
  73.180 -            // match a keyword, such as "next"
  73.181 -            // However, if we're at the end of the document, x. will lex . as an
  73.182 -            // identifier of text ".", so handle this case specially
  73.183 -            if ((id == PythonTokenId.IDENTIFIER)/* || (id == PythonTokenId.CONSTANT)*/ ||
  73.184 -                    id.primaryCategory().equals("keyword")) {
  73.185 -                String tokenText = token.text().toString();
  73.186 -
  73.187 -                if (".".equals(tokenText)) {
  73.188 -                    // Special case - continue - we'll handle this part next
  73.189 -                    methodExpected = true;
  73.190 -                } else {
  73.191 -                    methodExpected = true;
  73.192 -
  73.193 -                    if (Character.isUpperCase(tokenText.charAt(0))) {
  73.194 -                        methodExpected = false;
  73.195 -                    }
  73.196 -
  73.197 -                    if (!ts.movePrevious()) {
  73.198 -                        return Call.LOCAL;
  73.199 -                    }
  73.200 -                }
  73.201 -
  73.202 -                token = ts.token();
  73.203 -                id = token.id();
  73.204 -            }
  73.205 -
  73.206 -            // If we're not in the identifier we need to be in the dot (in "foo.x").
  73.207 -            // I can't just check for tokens DOT and COLON3 because for unparseable source
  73.208 -            // (like "File.|") the lexer will return the "." as an identifier.
  73.209 -            if (id == PythonTokenId.DOT) {
  73.210 -                methodExpected = true;
  73.211 -            } else if (id == PythonTokenId.IDENTIFIER) {
  73.212 -                String t = token.text().toString();
  73.213 -
  73.214 -                if (t.equals(".")) {
  73.215 -                    methodExpected = true;
  73.216 -                } else {
  73.217 -                    return Call.LOCAL;
  73.218 -                }
  73.219 -            } else {
  73.220 -                return Call.LOCAL;
  73.221 -            }
  73.222 -
  73.223 -            int lastSeparatorOffset = ts.offset();
  73.224 -            int beginOffset = lastSeparatorOffset;
  73.225 -            int lineStart = 0;
  73.226 -
  73.227 -            try {
  73.228 -                if (offset > doc.getLength()) {
  73.229 -                    offset = doc.getLength();
  73.230 -                }
  73.231 -
  73.232 -                lineStart = Utilities.getRowStart(doc, offset);
  73.233 -            } catch (BadLocationException ble) {
  73.234 -                Exceptions.printStackTrace(ble);
  73.235 -            }
  73.236 -
  73.237 -            // Find the beginning of the expression. We'll go past keywords, identifiers
  73.238 -            // and dots or double-colons
  73.239 -            while (ts.movePrevious()) {
  73.240 -                // If we get to the previous line we're done
  73.241 -                if (ts.offset() < lineStart) {
  73.242 -                    break;
  73.243 -                }
  73.244 -
  73.245 -                token = ts.token();
  73.246 -                id = token.id();
  73.247 -
  73.248 -                String tokenText = null;
  73.249 -                if (id == PythonTokenId.ANY_KEYWORD || id == PythonTokenId.IDENTIFIER) {
  73.250 -                    tokenText = token.text().toString();
  73.251 -                }
  73.252 -
  73.253 -                if (id == PythonTokenId.WHITESPACE) {
  73.254 -                    break;
  73.255 -                } else if (id == PythonTokenId.RBRACKET) {
  73.256 -                    return new Call("ListType", null, false, methodExpected);
  73.257 -                } else if (id == PythonTokenId.RBRACE) {
  73.258 -                    return new Call("DictType", null, false, methodExpected);
  73.259 -                } else if ((id == PythonTokenId.STRING_END)/* || (id == PythonTokenId.QUOTED_STRING_END)*/) {
  73.260 -                    return new Call("StringType", null, false, methodExpected);
  73.261 -                } else if ((id == PythonTokenId.IDENTIFIER) && "True".equals(tokenText)) { // NOI18N
  73.262 -                    return new Call("BooleanType", null, false, methodExpected);
  73.263 -                } else if ((id == PythonTokenId.IDENTIFIER) && "False".equals(tokenText)) { // NOI18N
  73.264 -                    return new Call("BooleanType", null, false, methodExpected);
  73.265 -                } else if (((id == PythonTokenId.IDENTIFIER)) ||
  73.266 -                        id.primaryCategory().equals("keyword") || (id == PythonTokenId.DOT)) {
  73.267 -
  73.268 -                    // We're building up a potential expression such as "Test::Unit" so continue looking
  73.269 -                    beginOffset = ts.offset();
  73.270 -
  73.271 -                    continue;
  73.272 -                } else if ((id == PythonTokenId.LPAREN) || (id == PythonTokenId.LBRACE) ||
  73.273 -                        (id == PythonTokenId.LBRACKET)) {
  73.274 -                    // It's an expression for example within a parenthesis, e.g.
  73.275 -                    // yield(^File.join())
  73.276 -                    // in this case we can do top level completion
  73.277 -                    // TODO: There are probably more valid contexts here
  73.278 -                    break;
  73.279 -                } else if (id == PythonTokenId.ANY_OPERATOR) {
  73.280 -                    break;
  73.281 -                } else {
  73.282 -                    // Something else - such as "getFoo().x|" - at this point we don't know the type
  73.283 -                    // so we'll just return unknown
  73.284 -                    return Call.UNKNOWN;
  73.285 -                }
  73.286 -            }
  73.287 -
  73.288 -            if (beginOffset < lastSeparatorOffset) {
  73.289 -                try {
  73.290 -                    String lhs = doc.getText(beginOffset, lastSeparatorOffset - beginOffset);
  73.291 -
  73.292 -                    if (lhs.equals("super") || lhs.equals("self")) { // NOI18N
  73.293 -
  73.294 -                        return new Call(lhs, lhs, false, true);
  73.295 -                    } else if (Character.isUpperCase(lhs.charAt(0))) {
  73.296 -
  73.297 -//                        // Detect constructor calls of the form String.new.^
  73.298 -//                        if (lhs.endsWith(".new")) { // NOI18N
  73.299 -//                            // See if it looks like a type prior to that
  73.300 -//                            String type = lhs.substring(0, lhs.length()-4); // 4=".new".length()
  73.301 -//                            if (PythonUtils.isValidPythonModuleName(type)) {
  73.302 -//                                return new Call(type, lhs, false, methodExpected);
  73.303 -//                            }
  73.304 -//                        }
  73.305 -
  73.306 -                        String type = null;
  73.307 -//                        if (PythonUtils.isValidPythonModuleName(lhs)) {
  73.308 -                        type = lhs;
  73.309 -//                        }
  73.310 -
  73.311 -                        return new Call(type, lhs, true, methodExpected);
  73.312 -                    } else {
  73.313 -                        return new Call(null, lhs, false, methodExpected);
  73.314 -                    }
  73.315 -                } catch (BadLocationException ble) {
  73.316 -                    Exceptions.printStackTrace(ble);
  73.317 -                }
  73.318 -            } else {
  73.319 -                return Call.UNKNOWN;
  73.320 -            }
  73.321 -        }
  73.322 -
  73.323 -        return Call.LOCAL;
  73.324 -    }
  73.325 -}
    74.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/PythonCommentLexer.java	Sat Sep 12 23:03:15 2015 -0700
    74.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.3 @@ -1,229 +0,0 @@
    74.4 -/*
    74.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    74.6 - *
    74.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    74.8 - *
    74.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   74.10 - * Other names may be trademarks of their respective owners.
   74.11 - *
   74.12 - * The contents of this file are subject to the terms of either the GNU
   74.13 - * General Public License Version 2 only ("GPL") or the Common
   74.14 - * Development and Distribution License("CDDL") (collectively, the
   74.15 - * "License"). You may not use this file except in compliance with the
   74.16 - * License. You can obtain a copy of the License at
   74.17 - * http://www.netbeans.org/cddl-gplv2.html
   74.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   74.19 - * specific language governing permissions and limitations under the
   74.20 - * License.  When distributing the software, include this License Header
   74.21 - * Notice in each file and include the License file at
   74.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   74.23 - * particular file as subject to the "Classpath" exception as provided
   74.24 - * by Oracle in the GPL Version 2 section of the License file that
   74.25 - * accompanied this code. If applicable, add the following below the
   74.26 - * License Header, with the fields enclosed by brackets [] replaced by
   74.27 - * your own identifying information:
   74.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   74.29 - *
   74.30 - * Contributor(s):
   74.31 - *
   74.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   74.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   74.34 - * Microsystems, Inc. All Rights Reserved.
   74.35 - *
   74.36 - * If you wish your version of this file to be governed by only the CDDL
   74.37 - * or only the GPL Version 2, indicate your decision by adding
   74.38 - * "[Contributor] elects to include this software in this distribution
   74.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   74.40 - * single choice of license, a recipient has the option to distribute
   74.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   74.42 - * to extend the choice of license to its licensees as provided above.
   74.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   74.44 - * Version 2 license, then the option applies only if the new code is
   74.45 - * made subject to such option by the copyright holder.
   74.46 - */
   74.47 -package org.netbeans.modules.python.editor.lexer;
   74.48 -
   74.49 -import org.netbeans.api.lexer.Token;
   74.50 -import org.netbeans.spi.lexer.Lexer;
   74.51 -import org.netbeans.spi.lexer.LexerInput;
   74.52 -import org.netbeans.spi.lexer.LexerRestartInfo;
   74.53 -import org.netbeans.spi.lexer.TokenFactory;
   74.54 -
   74.55 -/**
   74.56 - * A lexer for python comments.
   74.57 - *
   74.58 - * Highlights TODO items and certain keywords (like @-param and @-type (without -)).
   74.59 - *
   74.60 - * @author Tor Norbye
   74.61 - */
   74.62 -public class PythonCommentLexer implements Lexer<PythonCommentTokenId> {
   74.63 -    private static final int EOF = LexerInput.EOF;
   74.64 -    private final LexerInput input;
   74.65 -    private final TokenFactory<PythonCommentTokenId> tokenFactory;
   74.66 -    private final boolean substituting;
   74.67 -
   74.68 -    private static enum State {
   74.69 -        INIT,
   74.70 -        /** We've just seen @type */
   74.71 -        SEEN_TYPE_KEY,
   74.72 -        /** We've just seen @type< > */
   74.73 -        SEEN_TYPE_WS,
   74.74 -        /** We've just seen @type <varname> */
   74.75 -        SEEN_NAME,
   74.76 -        /** We've just seen @type varname< > */
   74.77 -        SEEN_NAME_WS
   74.78 -    };
   74.79 -    private State state;
   74.80 -
   74.81 -    /**
   74.82 -     * A Lexer for Python strings
   74.83 -     * @param substituting If true, handle substitution rules for double quoted strings, otherwise
   74.84 -     *    single quoted strings.
   74.85 -     */
   74.86 -    public PythonCommentLexer(LexerRestartInfo<PythonCommentTokenId> info, boolean substituting) {
   74.87 -        this.input = info.input();
   74.88 -        this.tokenFactory = info.tokenFactory();
   74.89 -        this.substituting = substituting;
   74.90 -        state = (State)info.state();
   74.91 -        if (state == null) {
   74.92 -            state = State.INIT;
   74.93 -        }
   74.94 -    }
   74.95 -
   74.96 -    @Override
   74.97 -    public Object state() {
   74.98 -        return state;
   74.99 -    }
  74.100 -
  74.101 -    @Override
  74.102 -    public Token<PythonCommentTokenId> nextToken() {
  74.103 -        switch (state) {
  74.104 -        case SEEN_NAME:
  74.105 -        case SEEN_TYPE_KEY:
  74.106 -            while (true) {
  74.107 -                int ch = input.read();
  74.108 -                if (ch == ':' && state == State.SEEN_NAME && input.readLength() == 1) {
  74.109 -                    continue;
  74.110 -                }
  74.111 -                if (ch == EOF || !Character.isWhitespace(ch)) {
  74.112 -                    if (ch != EOF) {
  74.113 -                        input.backup(1);
  74.114 -                    }
  74.115 -                    if (input.readLength() > 0) {
  74.116 -                        state = (state == State.SEEN_TYPE_KEY) ? State.SEEN_TYPE_WS : State.SEEN_NAME_WS;
  74.117 -                        return tokenFactory.createToken(PythonCommentTokenId.SEPARATOR,
  74.118 -                                input.readLength());
  74.119 -                    } else {
  74.120 -                        return null;
  74.121 -                    }
  74.122 -                }
  74.123 -            }
  74.124 -
  74.125 -        case SEEN_NAME_WS:
  74.126 -        case SEEN_TYPE_WS:
  74.127 -            while (true) {
  74.128 -                int ch = input.read();
  74.129 -                if (ch == EOF || Character.isWhitespace(ch) || ch == ':') {
  74.130 -                    if (ch != EOF) {
  74.131 -                        input.backup(1);
  74.132 -                    }
  74.133 -                    if (input.readLength() > 0) {
  74.134 -                        State nextState;
  74.135 -                        PythonCommentTokenId id;
  74.136 -                        if (state == State.SEEN_TYPE_WS) {
  74.137 -                            nextState = State.SEEN_NAME;
  74.138 -                            id = PythonCommentTokenId.VARNAME;
  74.139 -                        } else {
  74.140 -                            nextState = State.INIT;
  74.141 -                            id = PythonCommentTokenId.TYPE;
  74.142 -                        }
  74.143 -                        state = nextState;
  74.144 -                        return tokenFactory.createToken(id, input.readLength());
  74.145 -                    } else if (ch == EOF) {
  74.146 -                        return null;
  74.147 -                    } else {
  74.148 -                        // Error - : without an actual var name
  74.149 -                        state = State.INIT;
  74.150 -                        return nextToken(); // recurse
  74.151 -                    }
  74.152 -                }
  74.153 -            }
  74.154 -        default:
  74.155 -        case INIT: {
  74.156 -
  74.157 -            int last = EOF;
  74.158 -            while (true) {
  74.159 -                int ch = input.read();
  74.160 -
  74.161 -                switch (ch) {
  74.162 -                case EOF:
  74.163 -                    if (input.readLength() > 0) {
  74.164 -                        return tokenFactory.createToken(PythonCommentTokenId.TEXT,
  74.165 -                                input.readLength());
  74.166 -                    } else {
  74.167 -                        return null;
  74.168 -                    }
  74.169 -
  74.170 -                case '@': {
  74.171 -                    // Is it "@type"
  74.172 -                    int initialReadLength = input.readLength();
  74.173 -                    if (input.read() == 't' && input.read() == 'y' && input.read() == 'p' && input.read() == 'e') {
  74.174 -                        if (input.readLength() > 5) {
  74.175 -                            input.backup(5);
  74.176 -                            // Finish this token such that we can do a dedicated token for the @type item.
  74.177 -                            return tokenFactory.createToken(PythonCommentTokenId.TEXT,
  74.178 -                                    input.readLength());
  74.179 -                        }
  74.180 -                        state = State.SEEN_TYPE_KEY;
  74.181 -                        return tokenFactory.createToken(PythonCommentTokenId.TYPEKEY,
  74.182 -                                input.readLength());
  74.183 -                    }
  74.184 -                    if (input.readLength() > initialReadLength) {
  74.185 -                        input.backup(input.readLength() - initialReadLength);
  74.186 -                    } else {
  74.187 -                        return tokenFactory.createToken(PythonCommentTokenId.TEXT,
  74.188 -                                input.readLength());
  74.189 -                    }
  74.190 -                }
  74.191 -                break;
  74.192 -
  74.193 -                case 'T': {
  74.194 -                    if (last == EOF || !Character.isLetter(last)) {
  74.195 -                        // Is it "\wTODO\w" ?
  74.196 -                        int initialReadLength = input.readLength();
  74.197 -                        if (input.read() == 'O' && input.read() == 'D' && input.read() == 'O') {
  74.198 -                            int peek = input.read();
  74.199 -                            input.backup(1);
  74.200 -                            if (peek == EOF || !Character.isLetter(peek)) {
  74.201 -                                if (input.readLength() > 4) {
  74.202 -                                    input.backup(4);
  74.203 -                                    // Finish this token such that we can do a dedicated token for the @type item.
  74.204 -                                    return tokenFactory.createToken(PythonCommentTokenId.TEXT,
  74.205 -                                            input.readLength());
  74.206 -                                }
  74.207 -                                return tokenFactory.createToken(PythonCommentTokenId.TODO,
  74.208 -                                        input.readLength());
  74.209 -                            }
  74.210 -                        }
  74.211 -                        if (input.readLength() > initialReadLength) {
  74.212 -                            input.backup(input.readLength() - initialReadLength);
  74.213 -                        } else {
  74.214 -                            return tokenFactory.createToken(PythonCommentTokenId.TEXT,
  74.215 -                                    input.readLength());
  74.216 -                        }
  74.217 -                    }
  74.218 -                }
  74.219 -                break;
  74.220 -                }
  74.221 -
  74.222 -                last = ch;
  74.223 -            }
  74.224 -
  74.225 -        }
  74.226 -        }
  74.227 -    }
  74.228 -
  74.229 -    @Override
  74.230 -    public void release() {
  74.231 -    }
  74.232 -}
    75.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/PythonCommentTokenId.java	Sat Sep 12 23:03:15 2015 -0700
    75.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.3 @@ -1,120 +0,0 @@
    75.4 -/*
    75.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    75.6 - *
    75.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    75.8 - *
    75.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   75.10 - * Other names may be trademarks of their respective owners.
   75.11 - *
   75.12 - * The contents of this file are subject to the terms of either the GNU
   75.13 - * General Public License Version 2 only ("GPL") or the Common
   75.14 - * Development and Distribution License("CDDL") (collectively, the
   75.15 - * "License"). You may not use this file except in compliance with the
   75.16 - * License. You can obtain a copy of the License at
   75.17 - * http://www.netbeans.org/cddl-gplv2.html
   75.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   75.19 - * specific language governing permissions and limitations under the
   75.20 - * License.  When distributing the software, include this License Header
   75.21 - * Notice in each file and include the License file at
   75.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   75.23 - * particular file as subject to the "Classpath" exception as provided
   75.24 - * by Oracle in the GPL Version 2 section of the License file that
   75.25 - * accompanied this code. If applicable, add the following below the
   75.26 - * License Header, with the fields enclosed by brackets [] replaced by
   75.27 - * your own identifying information:
   75.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   75.29 - *
   75.30 - * Contributor(s):
   75.31 - *
   75.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   75.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   75.34 - * Microsystems, Inc. All Rights Reserved.
   75.35 - *
   75.36 - * If you wish your version of this file to be governed by only the CDDL
   75.37 - * or only the GPL Version 2, indicate your decision by adding
   75.38 - * "[Contributor] elects to include this software in this distribution
   75.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   75.40 - * single choice of license, a recipient has the option to distribute
   75.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   75.42 - * to extend the choice of license to its licensees as provided above.
   75.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   75.44 - * Version 2 license, then the option applies only if the new code is
   75.45 - * made subject to such option by the copyright holder.
   75.46 - */
   75.47 -package org.netbeans.modules.python.editor.lexer;
   75.48 -
   75.49 -import java.util.Collection;
   75.50 -import java.util.EnumSet;
   75.51 -import java.util.Map;
   75.52 -
   75.53 -import org.netbeans.api.lexer.InputAttributes;
   75.54 -import org.netbeans.api.lexer.Language;
   75.55 -import org.netbeans.api.lexer.LanguagePath;
   75.56 -import org.netbeans.api.lexer.Token;
   75.57 -import org.netbeans.api.lexer.TokenId;
   75.58 -import org.netbeans.spi.lexer.LanguageEmbedding;
   75.59 -import org.netbeans.spi.lexer.LanguageHierarchy;
   75.60 -import org.netbeans.spi.lexer.Lexer;
   75.61 -import org.netbeans.spi.lexer.LexerRestartInfo;
   75.62 -
   75.63 -/**
   75.64 - *
   75.65 - * @author Tor Norbye
   75.66 - */
   75.67 -public enum PythonCommentTokenId implements TokenId {
   75.68 -    TEXT("comment"),
   75.69 -    KEYWORD("comment"),
   75.70 -    SEPARATOR("comment"),
   75.71 -    TYPEKEY("comment"),
   75.72 -    VARNAME("comment"),
   75.73 -    TYPE("comment"),
   75.74 -    TODO("comment");
   75.75 -    private final String primaryCategory;
   75.76 -
   75.77 -    PythonCommentTokenId() {
   75.78 -        this(null);
   75.79 -    }
   75.80 -
   75.81 -    PythonCommentTokenId(String primaryCategory) {
   75.82 -        this.primaryCategory = primaryCategory;
   75.83 -    }
   75.84 -
   75.85 -    @Override
   75.86 -    public String primaryCategory() {
   75.87 -        return primaryCategory;
   75.88 -    }
   75.89 -    public static final Language<PythonCommentTokenId> language =
   75.90 -            new LanguageHierarchy<PythonCommentTokenId>() {
   75.91 -                @Override
   75.92 -                protected Collection<PythonCommentTokenId> createTokenIds() {
   75.93 -                    return EnumSet.allOf(PythonCommentTokenId.class);
   75.94 -                }
   75.95 -
   75.96 -                @Override
   75.97 -                protected Map<String, Collection<PythonCommentTokenId>> createTokenCategories() {
   75.98 -                    return null; // no extra categories
   75.99 -                }
  75.100 -
  75.101 -                @Override
  75.102 -                protected Lexer<PythonCommentTokenId> createLexer(
  75.103 -                        LexerRestartInfo<PythonCommentTokenId> info) {
  75.104 -                    return new PythonCommentLexer(info, true);
  75.105 -                }
  75.106 -
  75.107 -                @Override
  75.108 -                protected LanguageEmbedding<?> embedding(
  75.109 -                        Token<PythonCommentTokenId> token, LanguagePath languagePath,
  75.110 -                        InputAttributes inputAttributes) {
  75.111 -                    return null; // No embedding
  75.112 -                }
  75.113 -
  75.114 -                @Override
  75.115 -                public String mimeType() {
  75.116 -                    return "text/x-python-comment"; // NOI18N
  75.117 -                }
  75.118 -            }.language();
  75.119 -
  75.120 -    public static Language<PythonCommentTokenId> language() {
  75.121 -        return language;
  75.122 -    }
  75.123 -}
    76.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/PythonLexer.java	Sat Sep 12 23:03:15 2015 -0700
    76.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.3 @@ -1,928 +0,0 @@
    76.4 -/*
    76.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    76.6 - *
    76.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    76.8 - *
    76.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   76.10 - * Other names may be trademarks of their respective owners.
   76.11 - *
   76.12 - * The contents of this file are subject to the terms of either the GNU
   76.13 - * General Public License Version 2 only ("GPL") or the Common
   76.14 - * Development and Distribution License("CDDL") (collectively, the
   76.15 - * "License"). You may not use this file except in compliance with the
   76.16 - * License. You can obtain a copy of the License at
   76.17 - * http://www.netbeans.org/cddl-gplv2.html
   76.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   76.19 - * specific language governing permissions and limitations under the
   76.20 - * License.  When distributing the software, include this License Header
   76.21 - * Notice in each file and include the License file at
   76.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   76.23 - * particular file as subject to the "Classpath" exception as provided
   76.24 - * by Oracle in the GPL Version 2 section of the License file that
   76.25 - * accompanied this code. If applicable, add the following below the
   76.26 - * License Header, with the fields enclosed by brackets [] replaced by
   76.27 - * your own identifying information:
   76.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   76.29 - *
   76.30 - * Contributor(s):
   76.31 - *
   76.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   76.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   76.34 - * Microsystems, Inc. All Rights Reserved.
   76.35 - *
   76.36 - * If you wish your version of this file to be governed by only the CDDL
   76.37 - * or only the GPL Version 2, indicate your decision by adding
   76.38 - * "[Contributor] elects to include this software in this distribution
   76.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   76.40 - * single choice of license, a recipient has the option to distribute
   76.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   76.42 - * to extend the choice of license to its licensees as provided above.
   76.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   76.44 - * Version 2 license, then the option applies only if the new code is
   76.45 - * made subject to such option by the copyright holder.
   76.46 - */
   76.47 -package org.netbeans.modules.python.editor.lexer;
   76.48 -
   76.49 -import org.netbeans.api.lexer.Token;
   76.50 -import org.netbeans.api.lexer.TokenUtilities;
   76.51 -import org.netbeans.spi.lexer.Lexer;
   76.52 -import org.netbeans.spi.lexer.LexerInput;
   76.53 -import org.netbeans.spi.lexer.LexerRestartInfo;
   76.54 -import org.netbeans.spi.lexer.TokenFactory;
   76.55 -
   76.56 -/**
   76.57 - * Lexer for Python.
   76.58 - *
   76.59 - * This is a hand written lexer for Python which recognizes the logical token types
   76.60 - * we care about within the IDE support.
   76.61 - *
   76.62 - * Initially, we were using Jython's lexer directly here. However, that had some
   76.63 - * problems:
   76.64 - *
   76.65 - * <ul>
   76.66 - *   <li>
   76.67 - *     In the IDE, we have to support incremental parsing. Not only is this a must
   76.68 - *     from a user performance perspective (typing a keystroke near the bottom of a
   76.69 - *     2,000 line file shouldn't cause complete re-lexing of the entire document), but
   76.70 - *     the NetBeans APIs require it; they restart the lexer on the nearest token
   76.71 - *     boundary.
   76.72 - *     ANTLR doesn't support incremental lexing. I looked into what it would take
   76.73 - *     to patch it to do so (as I have done for JRuby in the Ruby support), but
   76.74 - *     it (a) wasn't trivial, and (b) would require a LOT of data to be stored for
   76.75 - *     every token boundary.
   76.76 - *   </li>
   76.77 - *   <li>
   76.78 - *     Similarly, we need to put our lexer on top of a LexerInput, and it is not
   76.79 - *     particularly compatible with the way ANTLR handles input. We had an
   76.80 - *     adapter class for this which was jumping through various hoops to expose
   76.81 - *     the LexerInput as ANTLR input. However, it had some severe problems with
   76.82 - *     large inputs.
   76.83 - *   </li>
   76.84 - *   <li>
   76.85 - *     We need slightly different token divisions. For example, for matching bracket
   76.86 - *     purposes, we'd like to have strings split into string delimiters and the
   76.87 - *     string contents. Similarly, Jython did some things like coalesce all whitespace
   76.88 - *     around a newline into that newline token which causes some complications
   76.89 - *     for our token analysis.
   76.90 - *   </li>
   76.91 - *   <li>
   76.92 - *     For Ruby, I decided to use the JRuby lexer because JRuby lexing is very
   76.93 - *     difficult. They have a huge complicated class to do the lexing - and there's
   76.94 - *     no Ruby language spec.  Python on the other hand seems to have a very simple
   76.95 - *     lexing model, and a clear spec and grammar, so I don't feel worried that
   76.96 - *     our custom Python lexer is going to have a lot of corner case bugs.
   76.97 - *   </li>
   76.98 - * </ul>
   76.99 - *
  76.100 - * @author Tor Norbye
  76.101 - */
  76.102 -public final class PythonLexer implements Lexer<PythonTokenId> {
  76.103 -    public static final String COMMENT_CAT = "comment";
  76.104 -    public static final String KEYWORD_CAT = "keyword"; // NOI18N
  76.105 -    public static final String STRING_CAT = "string"; // NOI18N
  76.106 -    public static final String WHITESPACE_CAT = "whitespace"; // NOI18N
  76.107 -    public static final String OPERATOR_CAT = "operator"; // NOI18N
  76.108 -    public static final String SEPARATOR_CAT = "separator"; // NOI18N
  76.109 -    public static final String ERROR_CAT = "error"; // NOI18N
  76.110 -    public static final String NUMBER_CAT = "number"; // NOI18N
  76.111 -    public static final String IDENTIFIER_CAT = "identifier"; // NOI18N
  76.112 -    private static final int EOF = LexerInput.EOF;
  76.113 -    private final LexerInput input;
  76.114 -    private final TokenFactory<PythonTokenId> tokenFactory;
  76.115 -
  76.116 -    // Lexer state - preserved per token boundary
  76.117 -    private enum State {
  76.118 -        /** Normal state, same state as on entry into a Python file */
  76.119 -        INIT,
  76.120 -        /** We've processed the beginning string delimiter of a double-quoted short string */
  76.121 -        BEGIN_SHORTSTRING_DOUBLE,
  76.122 -        /** We've processed the beginning string delimiter of a single-quoted short string */
  76.123 -        BEGIN_SHORTSTRING_SINGLE,
  76.124 -        /** We've processed the beginning string delimiter of a double-quoted long string */
  76.125 -        BEGIN_LONGSTRING_DOUBLE,
  76.126 -        /** We've processed the beginning string delimiter of a singl-quoted long string */
  76.127 -        BEGIN_LONGSTRING_SINGLE,
  76.128 -        /** We've processed the string content in a double-quoted short string */
  76.129 -        END_SHORTSTRING_DOUBLE,
  76.130 -        /** We've processed the string content in a single-quoted short string */
  76.131 -        END_SHORTSTRING_SINGLE,
  76.132 -        /** We've processed the string content in a double-quoted long string */
  76.133 -        END_LONGSTRING_DOUBLE,
  76.134 -        /** We've processed the string content in a single-quoted long string */
  76.135 -        END_LONGSTRING_SINGLE,
  76.136 -    };
  76.137 -    private State state;
  76.138 -
  76.139 -    public PythonLexer(LexerRestartInfo<PythonTokenId> info) {
  76.140 -        this.input = info.input();
  76.141 -        this.tokenFactory = info.tokenFactory();
  76.142 -
  76.143 -        state = (State)info.state();
  76.144 -        if (state == null) {
  76.145 -            state = State.INIT;
  76.146 -        }
  76.147 -    }
  76.148 -
  76.149 -    @Override
  76.150 -    public Object state() {
  76.151 -        return state;
  76.152 -    }
  76.153 -
  76.154 -    private Token<PythonTokenId> createToken(PythonTokenId id, int tokenLength) {
  76.155 -        String fixedText = id.fixedText();
  76.156 -        return (fixedText != null) ? tokenFactory.getFlyweightToken(id, fixedText)
  76.157 -                : tokenFactory.createToken(id, tokenLength);
  76.158 -    }
  76.159 -
  76.160 -    @SuppressWarnings("fallthrough")
  76.161 -    @Override
  76.162 -    public Token<PythonTokenId> nextToken() {
  76.163 -        switch (state) {
  76.164 -        case INIT: {
  76.165 -            int ch = input.read();
  76.166 -            switch (ch) {
  76.167 -            case EOF:
  76.168 -                return null;
  76.169 -
  76.170 -            // Newline
  76.171 -            case '\n':
  76.172 -                assert input.readLength() == 1;
  76.173 -                return createToken(PythonTokenId.NEWLINE, 1);
  76.174 -
  76.175 -            // Whitespace
  76.176 -            case ' ':
  76.177 -            case '\t': {
  76.178 -                for (; ch != EOF; ch = input.read()) {
  76.179 -                    if (ch != ' ' && ch != '\t') {
  76.180 -                        break;
  76.181 -                    }
  76.182 -                }
  76.183 -                input.backup(1);
  76.184 -                return createToken(PythonTokenId.WHITESPACE, input.readLength());
  76.185 -            }
  76.186 -
  76.187 -            // Comment
  76.188 -            case '#': {
  76.189 -                ch = input.read();
  76.190 -                while (ch != EOF && ch != '\n') {
  76.191 -                    ch = input.read();
  76.192 -                }
  76.193 -                input.backup(1);
  76.194 -                return createToken(PythonTokenId.COMMENT, input.readLength());
  76.195 -            }
  76.196 -
  76.197 -            case '.': {
  76.198 -                assert input.readLength() == 1;
  76.199 -                int peek = input.read();
  76.200 -                input.backup(1);
  76.201 -                if (!Character.isDigit(peek)) {
  76.202 -                    return createToken(PythonTokenId.DOT, 1);
  76.203 -                } // else: Fallthrough to process the number!!
  76.204 -            } // FALLTHROUGH
  76.205 -            // FALLTHROUGH!!!!
  76.206 -
  76.207 -            // Number (integer, float, complex)
  76.208 -            case '0':
  76.209 -            case '1':
  76.210 -            case '2':
  76.211 -            case '3':
  76.212 -            case '4':
  76.213 -            case '5':
  76.214 -            case '6':
  76.215 -            case '7':
  76.216 -            case '8':
  76.217 -            case '9': {
  76.218 -                if (ch == '0') {
  76.219 -                    int peek = input.read();
  76.220 -                    if (peek == 'x' || peek == 'X') {
  76.221 -                        // Hex
  76.222 -                        ch = input.read();
  76.223 -                        while (ch != EOF) {
  76.224 -                            if (!(Character.isDigit(ch) ||
  76.225 -                                    (ch >= 'a' && ch <= 'f') ||
  76.226 -                                    (ch >= 'A' && ch <= 'F'))) {
  76.227 -                                break;
  76.228 -                            }
  76.229 -                            ch = input.read();
  76.230 -                        }
  76.231 -                        if (ch != 'l' && (ch != 'L')) {
  76.232 -                            input.backup(1);
  76.233 -                        }
  76.234 -                        return createToken(PythonTokenId.INT_LITERAL, input.readLength());
  76.235 -                    }
  76.236 -                    input.backup(1);
  76.237 -                }
  76.238 -                boolean isFloat = false;
  76.239 -                digitLoop:
  76.240 -                for (; ch != EOF; ch = input.read()) {
  76.241 -                    switch (ch) {
  76.242 -                    case '0':
  76.243 -                    case '1':
  76.244 -                    case '2':
  76.245 -                    case '3':
  76.246 -                    case '4':
  76.247 -                    case '5':
  76.248 -                    case '6':
  76.249 -                    case '7':
  76.250 -                    case '8':
  76.251 -                    case '9':
  76.252 -                        continue;
  76.253 -                    case '.':
  76.254 -                        isFloat = true;
  76.255 -                        continue;
  76.256 -                    case 'e': // Exponent
  76.257 -                    case 'E': {
  76.258 -                        int peek = input.read();
  76.259 -                        if (peek != '+' && peek != '-') {
  76.260 -                            input.backup(1);
  76.261 -                        }
  76.262 -                        ch = input.read();
  76.263 -                        while (ch != EOF) {
  76.264 -                            if (!Character.isDigit(ch)) {
  76.265 -                                break;
  76.266 -                            }
  76.267 -                            ch = input.read();
  76.268 -                        }
  76.269 -                        if (ch != 'j' && ch != 'J') {
  76.270 -                            input.backup(1);
  76.271 -                        }
  76.272 -                        return createToken(PythonTokenId.FLOAT_LITERAL, input.readLength());
  76.273 -                    }
  76.274 -                    case 'j': // Imaginary
  76.275 -                    case 'J':
  76.276 -                        isFloat = true;
  76.277 -                        break digitLoop;
  76.278 -                    case 'l': // Long
  76.279 -                    case 'L':
  76.280 -                        break digitLoop;
  76.281 -                    case EOF:
  76.282 -                    default:
  76.283 -                        input.backup(1);
  76.284 -                        break digitLoop;
  76.285 -
  76.286 -                    }
  76.287 -                }
  76.288 -
  76.289 -                return createToken(isFloat ? PythonTokenId.FLOAT_LITERAL : PythonTokenId.INT_LITERAL, input.readLength());
  76.290 -            }
  76.291 -
  76.292 -            // Operators and delimiters
  76.293 -            case '+': // +,+=
  76.294 -                if (input.read() != '=') {
  76.295 -                    input.backup(1);
  76.296 -                }
  76.297 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  76.298 -            case '-': // -,-=
  76.299 -                if (input.read() != '=') {
  76.300 -                    input.backup(1);
  76.301 -                }
  76.302 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  76.303 -            case '*': { // *,**,*=, **=
  76.304 -                int peek = input.read();
  76.305 -                if (peek == '=') {
  76.306 -                    // No need to back up, include it
  76.307 -                } else if (peek == '*') {
  76.308 -                    peek = input.read();
  76.309 -                    if (peek != '=') {
  76.310 -                        input.backup(1);
  76.311 -                    }
  76.312 -                } else {
  76.313 -                    input.backup(1);
  76.314 -                }
  76.315 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  76.316 -            }
  76.317 -            case '/': {
  76.318 -                // Look for /,//, /=, //=
  76.319 -                int peek = input.read();
  76.320 -                if (peek == '=') {
  76.321 -                    // No need to back up, include it
  76.322 -                } else if (peek == '/') {
  76.323 -                    peek = input.read();
  76.324 -                    if (peek != '=') {
  76.325 -                        input.backup(1);
  76.326 -                    }
  76.327 -                } else {
  76.328 -                    input.backup(1);
  76.329 -                }
  76.330 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  76.331 -            }
  76.332 -            case '%': { // Look for %,   %=
  76.333 -                if (input.read() != '=') {
  76.334 -                    input.backup(1);
  76.335 -                }
  76.336 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  76.337 -            }
  76.338 -            case '<': {
  76.339 -                // Look for <, <<, <=, <>, <<=
  76.340 -                int peek = input.read();
  76.341 -                if (peek == '=') {
  76.342 -                    // No need to back up, include it
  76.343 -                } else if (peek == '<') {
  76.344 -                    peek = input.read();
  76.345 -                    if (peek != '=') {
  76.346 -                        input.backup(1);
  76.347 -                    }
  76.348 -                } else if (peek != '>') {
  76.349 -                    input.backup(1);
  76.350 -                }
  76.351 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  76.352 -            }
  76.353 -            case '>': {
  76.354 -                // Look for >, >>, >=, >>=
  76.355 -                int peek = input.read();
  76.356 -                if (peek == '=') {
  76.357 -                    // No need to back up, include it
  76.358 -                } else if (peek == '>') {
  76.359 -                    peek = input.read();
  76.360 -                    if (peek != '=') {
  76.361 -                        input.backup(1);
  76.362 -                    }
  76.363 -                } else {
  76.364 -                    input.backup(1);
  76.365 -                }
  76.366 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  76.367 -            }
  76.368 -            case '&': { // Look for &,&=
  76.369 -                if (input.read() != '=') {
  76.370 -                    input.backup(1);
  76.371 -                }
  76.372 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  76.373 -            }
  76.374 -            case '|': { // Look for |, |=
  76.375 -                if (input.read() != '=') {
  76.376 -                    input.backup(1);
  76.377 -                }
  76.378 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  76.379 -            }
  76.380 -            case '^': { // ^,^=
  76.381 -                if (input.read() != '=') {
  76.382 -                    input.backup(1);
  76.383 -                }
  76.384 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  76.385 -            }
  76.386 -            case '=': {
  76.387 -                // Look for =,==
  76.388 -                if (input.read() != '=') {
  76.389 -                    input.backup(1);
  76.390 -                }
  76.391 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  76.392 -            }
  76.393 -            case '!': {
  76.394 -                // Look for !=
  76.395 -                if (input.read() != '=') {
  76.396 -                    input.backup(1);
  76.397 -                }
  76.398 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  76.399 -            }
  76.400 -            case '~':
  76.401 -            case '`':
  76.402 -            case ';':
  76.403 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  76.404 -
  76.405 -            case ':':
  76.406 -                assert input.readLength() == 1;
  76.407 -                return createToken(PythonTokenId.COLON, 1);
  76.408 -            case '(':
  76.409 -                assert input.readLength() == 1;
  76.410 -                return createToken(PythonTokenId.LPAREN, 1);
  76.411 -            case ')':
  76.412 -                assert input.readLength() == 1;
  76.413 -                return createToken(PythonTokenId.RPAREN, 1);
  76.414 -            case '[':
  76.415 -                assert input.readLength() == 1;
  76.416 -                return createToken(PythonTokenId.LBRACKET, 1);
  76.417 -            case ']':
  76.418 -                assert input.readLength() == 1;
  76.419 -                return createToken(PythonTokenId.RBRACKET, 1);
  76.420 -            case '{':
  76.421 -                assert input.readLength() == 1;
  76.422 -                return createToken(PythonTokenId.LBRACE, 1);
  76.423 -            case '}':
  76.424 -                assert input.readLength() == 1;
  76.425 -                return createToken(PythonTokenId.RBRACE, 1);
  76.426 -            case ',':
  76.427 -                assert input.readLength() == 1;
  76.428 -                return createToken(PythonTokenId.COMMA, 1);
  76.429 -            case '\\':
  76.430 -                assert input.readLength() == 1;
  76.431 -                return createToken(PythonTokenId.ESC, 1);
  76.432 -
  76.433 -            case '$':
  76.434 -            case '?':
  76.435 -                assert input.readLength() == 1;
  76.436 -                return createToken(PythonTokenId.ERROR, 1);
  76.437 -
  76.438 -            // String?
  76.439 -            case '\'':
  76.440 -            case '"': {
  76.441 -                int peek = input.read();
  76.442 -                if (peek != ch) {
  76.443 -                    input.backup(1);
  76.444 -                    assert input.readLength() == 1;
  76.445 -                    state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
  76.446 -                    return createToken(PythonTokenId.STRING_BEGIN, 1);
  76.447 -                }
  76.448 -                // We've seen two quotes... it's either an empty string,
  76.449 -                // or the beginning of a longstring
  76.450 -                int peek2 = input.read();
  76.451 -                if (peek2 == peek) {
  76.452 -                    // It's a longstring!
  76.453 -                    assert input.readLength() == 3;
  76.454 -                    state = (ch == '"') ? State.BEGIN_LONGSTRING_DOUBLE : State.BEGIN_LONGSTRING_SINGLE;
  76.455 -                    return createToken(PythonTokenId.STRING_BEGIN, 3);
  76.456 -                } else {
  76.457 -                    input.backup(2);
  76.458 -                    assert input.readLength() == 1;
  76.459 -                    state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
  76.460 -                    return createToken(PythonTokenId.STRING_BEGIN, 1);
  76.461 -                }
  76.462 -            }
  76.463 -            case '@': { // Decorator
  76.464 -                // Identifier or keyword?
  76.465 -                ch = input.read();
  76.466 -                if (Character.isJavaIdentifierStart(ch)) {
  76.467 -                    while (ch != EOF && Character.isJavaIdentifierPart(ch) && ch != '$') {
  76.468 -                        ch = input.read();
  76.469 -                    }
  76.470 -                    input.backup(1);
  76.471 -
  76.472 -                    return createToken(PythonTokenId.DECORATOR, input.readLength());
  76.473 -                }
  76.474 -                input.backup(1); // Remove the peeked char
  76.475 -
  76.476 -                assert input.readLength() == 1;
  76.477 -                return createToken(PythonTokenId.DECORATOR, 1);
  76.478 -            }
  76.479 -
  76.480 -            case 'r':
  76.481 -            case 'R':
  76.482 -            case 'u':
  76.483 -            case 'U': {
  76.484 -                // Digest the "u" and the "r" and position the input
  76.485 -                // before the following ' or "
  76.486 -                boolean isStringPrefix = false;
  76.487 -                int peek = input.read();
  76.488 -                if (ch == 'r' || ch == 'R') {
  76.489 -                    if (peek == '\'' || peek == '"') {
  76.490 -                        isStringPrefix = true;
  76.491 -                    }
  76.492 -                    input.backup(1);
  76.493 -                } else {
  76.494 -                    assert ch == 'u' || ch == 'U';
  76.495 -                    if (peek == 'r' || peek == 'R') {
  76.496 -                        int peek2 = input.read();
  76.497 -                        if (peek2 == '\'' || peek2 == '"') {
  76.498 -                            isStringPrefix = true;
  76.499 -                        }
  76.500 -                        input.backup(1);
  76.501 -                    } else if (peek == '\'' || peek == '"') {
  76.502 -                        isStringPrefix = true;
  76.503 -                        input.backup(1);
  76.504 -                    }
  76.505 -                    if (!isStringPrefix) {
  76.506 -                        input.backup(1);
  76.507 -                    }
  76.508 -                }
  76.509 -                if (isStringPrefix) {
  76.510 -                    ch = input.read();
  76.511 -                    assert ch == '\'' || ch == '"';
  76.512 -
  76.513 -                    peek = input.read();
  76.514 -                    if (peek != ch) {
  76.515 -                        input.backup(1);
  76.516 -                        state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
  76.517 -                        return createToken(PythonTokenId.STRING_BEGIN, input.readLength());
  76.518 -                    }
  76.519 -                    // We've seen two quotes... it's either an empty string,
  76.520 -                    // or the beginning of a longstring
  76.521 -                    int peek2 = input.read();
  76.522 -                    if (peek2 == peek) {
  76.523 -                        // It's a longstring!
  76.524 -                        state = (ch == '"') ? State.BEGIN_LONGSTRING_DOUBLE : State.BEGIN_LONGSTRING_SINGLE;
  76.525 -                        return createToken(PythonTokenId.STRING_BEGIN, input.readLength());
  76.526 -                    } else {
  76.527 -                        input.backup(2);
  76.528 -                        state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
  76.529 -                        return createToken(PythonTokenId.STRING_BEGIN, input.readLength());
  76.530 -                    }
  76.531 -                }// else: FALLTHROUGH!!! The "u" or "r" is probably an identifier prefix!!
  76.532 -            }
  76.533 -            // Fallthrough...
  76.534 -
  76.535 -            default: {
  76.536 -                // Identifier or keyword?
  76.537 -                if (Character.isJavaIdentifierStart(ch)) {
  76.538 -                    while (ch != EOF && Character.isJavaIdentifierPart(ch) && ch != '$') {
  76.539 -                        ch = input.read();
  76.540 -                    }
  76.541 -                    input.backup(1);
  76.542 -
  76.543 -                    // See if it's a keyword
  76.544 -                    PythonTokenId pid = getKeywordToken(input.readText());
  76.545 -                    if (pid != null) {
  76.546 -                        return createToken(pid, input.readLength());
  76.547 -                    } else {
  76.548 -                        return createToken(PythonTokenId.IDENTIFIER, input.readLength());
  76.549 -                    }
  76.550 -                }
  76.551 -
  76.552 -                assert input.readLength() == 1;
  76.553 -                return createToken(PythonTokenId.ANY_OPERATOR, 1);
  76.554 -            }
  76.555 -            }
  76.556 -        }
  76.557 -
  76.558 -        case BEGIN_LONGSTRING_SINGLE:
  76.559 -        case BEGIN_LONGSTRING_DOUBLE: {
  76.560 -            // In a long string. Look for the end.
  76.561 -            int ch = input.read();
  76.562 -            if (ch == EOF) {
  76.563 -                return null;
  76.564 -            }
  76.565 -            int term = (state == State.BEGIN_LONGSTRING_DOUBLE) ? '"' : '\'';
  76.566 -            while (ch != EOF) {
  76.567 -                if (ch == '\\') {
  76.568 -                    // It's an escape - read escaped char
  76.569 -                    input.read();
  76.570 -                } else if (ch == term) {
  76.571 -                    int peek = input.read();
  76.572 -                    if (peek == term) {
  76.573 -                        int peek2 = input.read();
  76.574 -                        if (peek2 == term) {
  76.575 -                            // Found the end
  76.576 -                            if (input.readLength() == 3) {
  76.577 -                                // Empty string - go straight to closed state
  76.578 -                                state = State.INIT;
  76.579 -                                return createToken(PythonTokenId.STRING_END, input.readLength());
  76.580 -                            }
  76.581 -                            input.backup(3);
  76.582 -                            if (state == State.BEGIN_LONGSTRING_DOUBLE) {
  76.583 -                                state = State.END_LONGSTRING_DOUBLE;
  76.584 -                            } else {
  76.585 -                                assert state == State.BEGIN_LONGSTRING_SINGLE;
  76.586 -                                state = State.END_LONGSTRING_SINGLE;
  76.587 -                            }
  76.588 -                            return createToken(PythonTokenId.STRING_LITERAL, input.readLength());
  76.589 -                        }
  76.590 -                        input.backup(1);
  76.591 -                    }
  76.592 -                    input.backup(1);
  76.593 -                }
  76.594 -                ch = input.read();
  76.595 -            }
  76.596 -            // Literal not terminated
  76.597 -            state = State.INIT;
  76.598 -            return createToken(PythonTokenId.ERROR, input.readLength());
  76.599 -        }
  76.600 -        case BEGIN_SHORTSTRING_SINGLE:
  76.601 -        case BEGIN_SHORTSTRING_DOUBLE: {
  76.602 -            // In a short string. Look for the end.
  76.603 -            int ch = input.read();
  76.604 -            if (ch == EOF) {
  76.605 -                return null;
  76.606 -            }
  76.607 -            int term = (state == State.BEGIN_SHORTSTRING_DOUBLE) ? '"' : '\'';
  76.608 -            while (ch != EOF) {
  76.609 -                if (ch == '\\') {
  76.610 -                    // It's an escape - read escaped char
  76.611 -                    input.read();
  76.612 -                } else if (ch == '\n') {
  76.613 -                    // Literal not terminated
  76.614 -                    state = State.INIT;
  76.615 -                    return createToken(PythonTokenId.ERROR, input.readLength());
  76.616 -                } else if (ch == term) {
  76.617 -                    if (input.readLength() == 1) {
  76.618 -                        // It's an empty string! Skip straight to the end state
  76.619 -                        state = State.INIT;
  76.620 -                        return createToken(PythonTokenId.STRING_END, input.readLength());
  76.621 -                    }
  76.622 -                    input.backup(1);
  76.623 -                    if (state == State.BEGIN_SHORTSTRING_DOUBLE) {
  76.624 -                        state = State.END_SHORTSTRING_DOUBLE;
  76.625 -                    } else {
  76.626 -                        assert state == State.BEGIN_SHORTSTRING_SINGLE;
  76.627 -                        state = State.END_SHORTSTRING_SINGLE;
  76.628 -                    }
  76.629 -                    return createToken(PythonTokenId.STRING_LITERAL, input.readLength());
  76.630 -                }
  76.631 -                ch = input.read();
  76.632 -            }
  76.633 -            // Literal not terminated
  76.634 -            state = State.INIT;
  76.635 -            return createToken(PythonTokenId.ERROR, input.readLength());
  76.636 -        }
  76.637 -
  76.638 -        case END_LONGSTRING_SINGLE:
  76.639 -        case END_LONGSTRING_DOUBLE: {
  76.640 -            // In a long string. Look for the end.
  76.641 -            int ch = input.read();
  76.642 -            if (ch == EOF) {
  76.643 -                return null;
  76.644 -            }
  76.645 -            int term = (state == State.END_LONGSTRING_DOUBLE) ? '"' : '\'';
  76.646 -            while (ch != EOF) {
  76.647 -                if (ch == term) {
  76.648 -                    int peek = input.read();
  76.649 -                    if (peek == term) {
  76.650 -                        int peek2 = input.read();
  76.651 -                        if (peek2 == term) {
  76.652 -                            // Found the end
  76.653 -                            state = State.INIT;
  76.654 -                            return createToken(PythonTokenId.STRING_END, input.readLength());
  76.655 -                        }
  76.656 -                        input.backup(1);
  76.657 -                    }
  76.658 -                    input.backup(1);
  76.659 -                }
  76.660 -                ch = input.read();
  76.661 -            }
  76.662 -            // Literal not terminated
  76.663 -            state = State.INIT;
  76.664 -            return createToken(PythonTokenId.ERROR, input.readLength());
  76.665 -        }
  76.666 -        case END_SHORTSTRING_SINGLE:
  76.667 -        case END_SHORTSTRING_DOUBLE: {
  76.668 -            // In a short string. Look for the end.
  76.669 -            int ch = input.read();
  76.670 -            if (ch == EOF) {
  76.671 -                return null;
  76.672 -            }
  76.673 -            int term = (state == State.END_SHORTSTRING_DOUBLE) ? '"' : '\'';
  76.674 -            if (ch == term) {
  76.675 -                state = State.INIT;
  76.676 -                return createToken(PythonTokenId.STRING_END, input.readLength());
  76.677 -            }
  76.678 -            state = State.INIT;
  76.679 -            return createToken(PythonTokenId.ERROR, input.readLength());
  76.680 -        }
  76.681 -
  76.682 -        default:
  76.683 -            assert false : state;
  76.684 -        }
  76.685 -
  76.686 -        return null;
  76.687 -    }
  76.688 -
  76.689 -    @Override
  76.690 -    public void release() {
  76.691 -    }
  76.692 -
  76.693 -    private PythonTokenId getKeywordToken(CharSequence s) {
  76.694 -        int length = s.length();
  76.695 -        if (length < 2) {
  76.696 -            return null;
  76.697 -        }
  76.698 -
  76.699 -        if (s.toString().endsWith("Error")) {
  76.700 -            return PythonTokenId.ERROR;
  76.701 -        }
  76.702 -
  76.703 -        char c1 = s.charAt(0);
  76.704 -        char c2 = s.charAt(1);
  76.705 -
  76.706 -        switch (c1) {
  76.707 -        case 'a': // and, as, assert, async, await
  76.708 -            switch (c2) {
  76.709 -            case 'n': // and
  76.710 -                if (TokenUtilities.textEquals(s, "and")) { // NOI18N
  76.711 -                    return PythonTokenId.ANY_KEYWORD;
  76.712 -                }
  76.713 -                break;
  76.714 -            case 's':  // as, assert, async
  76.715 -                if (length == 2) { // as
  76.716 -                    return PythonTokenId.ANY_KEYWORD;
  76.717 -                }
  76.718 -                if (length == 6 && TokenUtilities.textEquals(s, "assert")) { // NOI18N
  76.719 -                    return PythonTokenId.ANY_KEYWORD;
  76.720 -                }
  76.721 -                if (length == 5 && TokenUtilities.textEquals(s, "async")) { // NOI18N
  76.722 -                    return PythonTokenId.ANY_KEYWORD;
  76.723 -                }
  76.724 -                break;
  76.725 -            case 'w': // await
  76.726 -                if (length == 5 && TokenUtilities.textEquals(s, "await")) { // NOI18N
  76.727 -                    return PythonTokenId.ANY_KEYWORD;
  76.728 -                }
  76.729 -            }
  76.730 -            break;
  76.731 -        case 'b': // break, bytes
  76.732 -            if (length == 5 && TokenUtilities.textEquals(s, "break")) { // NOI18N
  76.733 -                return PythonTokenId.ANY_KEYWORD;
  76.734 -            } else if (length == 5 && TokenUtilities.textEquals(s, "bytes")) { // NOI18N
  76.735 -                return PythonTokenId.STD_SYMBOLS;
  76.736 -            }
  76.737 -            break;
  76.738 -        case 'c': // class, continue
  76.739 -            switch (c2) {
  76.740 -            case 'l': // class
  76.741 -                if (length == 5 && TokenUtilities.textEquals(s, "class")) { // NOI18N
  76.742 -                    return PythonTokenId.CLASS;
  76.743 -                }
  76.744 -                break;
  76.745 -            case 'o':  // continue
  76.746 -                if (length == 8 && TokenUtilities.textEquals(s, "continue")) { // NOI18N
  76.747 -                    return PythonTokenId.ANY_KEYWORD;
  76.748 -                }
  76.749 -                break;
  76.750 -            }
  76.751 -            break;
  76.752 -        case 'd': // def, del
  76.753 -            if (c2 == 'e' && length == 3) { // def, del
  76.754 -                char c3 = s.charAt(2);
  76.755 -                if (c3 == 'f') { // def
  76.756 -                    return PythonTokenId.DEF;
  76.757 -                } else if (c3 == 'l') { // del
  76.758 -                    return PythonTokenId.ANY_KEYWORD;
  76.759 -                }
  76.760 -            }
  76.761 -            break;
  76.762 -        case 'e': // elif, else, except, exec
  76.763 -            switch (c2) {
  76.764 -            case 'l': // elif, else
  76.765 -                if (length == 4) {
  76.766 -                    if (TokenUtilities.textEquals(s, "elif")) { // NOI18N
  76.767 -                        return PythonTokenId.ELIF;
  76.768 -                    }
  76.769 -                    if (TokenUtilities.textEquals(s, "else")) { // NOI18N
  76.770 -                        return PythonTokenId.ELSE;
  76.771 -                    }
  76.772 -                }
  76.773 -                break;
  76.774 -            case 'n': // enumerate
  76.775 -                if (length == 9 && TokenUtilities.textEquals(s, "enumerate")) { // NOI18N
  76.776 -                    return PythonTokenId.STD_SYMBOLS;
  76.777 -                }
  76.778 -            case 'x': // except, exec
  76.779 -                if (length == 4 && TokenUtilities.textEquals(s, "exec")) { // NOI18N
  76.780 -                    return PythonTokenId.ANY_KEYWORD;
  76.781 -                }
  76.782 -                if (length == 6 && TokenUtilities.textEquals(s, "except")) { // NOI18N
  76.783 -                    return PythonTokenId.EXCEPT;
  76.784 -                }
  76.785 -                break;
  76.786 -            }
  76.787 -            break;
  76.788 -        case 'f': // finally,for,from
  76.789 -            switch (c2) {
  76.790 -            case 'i': // finally
  76.791 -                if (length == 7 && TokenUtilities.textEquals(s, "finally")) { // NOI18N
  76.792 -                    return PythonTokenId.FINALLY;
  76.793 -                }
  76.794 -                break;
  76.795 -            case 'o': // for
  76.796 -                if (length == 3 && TokenUtilities.textEquals(s, "for")) { // NOI18N
  76.797 -                    return PythonTokenId.ANY_KEYWORD;
  76.798 -                }
  76.799 -                break;
  76.800 -            case 'r': // from
  76.801 -                if (length == 4 && TokenUtilities.textEquals(s, "from")) { // NOI18N
  76.802 -                    return PythonTokenId.FROM;
  76.803 -                }
  76.804 -                break;
  76.805 -            case 'l':
  76.806 -                if (length == 5 && TokenUtilities.textEquals(s, "float")) {
  76.807 -                    return PythonTokenId.STD_SYMBOLS;
  76.808 -                }
  76.809 -            }
  76.810 -            break;
  76.811 -        case 'g': // global
  76.812 -            if (length == 6 && TokenUtilities.textEquals(s, "global")) { // NOI18N
  76.813 -                return PythonTokenId.ANY_KEYWORD;
  76.814 -            }
  76.815 -            break;
  76.816 -        case 'i': // if,import,in,is, int
  76.817 -            if (length == 2) {
  76.818 -                switch (c2) {
  76.819 -                case 'f': // if
  76.820 -                    return PythonTokenId.IF;
  76.821 -                case 'n': // in
  76.822 -                    if (length == 2 && TokenUtilities.textEquals(s, "in")) { //NOI18N
  76.823 -                        return PythonTokenId.ANY_KEYWORD;
  76.824 -                    }
  76.825 -                case 's': // is
  76.826 -                    return PythonTokenId.ANY_KEYWORD;
  76.827 -                }
  76.828 -            } else if (c2 == 'm' && length == 6 && TokenUtilities.textEquals(s, "import")) { // NOI18N
  76.829 -                // import
  76.830 -                return PythonTokenId.IMPORT;
  76.831 -            } else if (length == 3 && TokenUtilities.textEquals(s, "int")) { // NOI18N
  76.832 -                return PythonTokenId.STD_SYMBOLS;
  76.833 -            } else if (length == 10 && TokenUtilities.textEquals(s, "isinstance")) { // NOI18N
  76.834 -                return PythonTokenId.STD_SYMBOLS;
  76.835 -            }
  76.836 -            break;
  76.837 -        case 'l': // lambda, len, list
  76.838 -            if (length == 6 && TokenUtilities.textEquals(s, "lambda")) { // NOI18N
  76.839 -                return PythonTokenId.ANY_KEYWORD;
  76.840 -            } else if (length == 3 && TokenUtilities.textEquals(s, "len")) { // NOI18N
  76.841 -                return PythonTokenId.STD_SYMBOLS;
  76.842 -            } else if (length == 4 && TokenUtilities.textEquals(s, "list")) { // NOI18N
  76.843 -                return PythonTokenId.STD_SYMBOLS;
  76.844 -            }
  76.845 -            break;
  76.846 -        case 'n': // not
  76.847 -            if (length == 3 && TokenUtilities.textEquals(s, "not")) { // NOI18N
  76.848 -                return PythonTokenId.ANY_KEYWORD;
  76.849 -            }
  76.850 -            break;
  76.851 -        case 'o': // or, object
  76.852 -            if (length == 2 && TokenUtilities.textEquals(s, "or")) { // NOI18N
  76.853 -                return PythonTokenId.ANY_KEYWORD;
  76.854 -            } else if (length == 6 && TokenUtilities.textEquals(s, "object")) { // NOI18N
  76.855 -                return PythonTokenId.STD_SYMBOLS;
  76.856 -            }
  76.857 -            break;
  76.858 -        case 'p': // pass,print
  76.859 -            if (c2 == 'a') { // pass
  76.860 -                if (length == 4 && TokenUtilities.textEquals(s, "pass")) { // NOI18N
  76.861 -                    return PythonTokenId.PASS;
  76.862 -                }
  76.863 -            } else if (c2 == 'r') { // print
  76.864 -                if (length == 5 && TokenUtilities.textEquals(s, "print")) { // NOI18N
  76.865 -                    return PythonTokenId.ANY_KEYWORD;
  76.866 -                }
  76.867 -            }
  76.868 -            break;
  76.869 -        case 'r': // raise,return
  76.870 -            if (c2 == 'a') { // raise
  76.871 -                if (length == 5 && TokenUtilities.textEquals(s, "raise")) { // NOI18N
  76.872 -                    return PythonTokenId.RAISE;
  76.873 -                }
  76.874 -            } else if (c2 == 'e') { // return
  76.875 -                if (length == 6 && TokenUtilities.textEquals(s, "return")) { // NOI18N
  76.876 -                    return PythonTokenId.RETURN;
  76.877 -                }
  76.878 -            }
  76.879 -            break;
  76.880 -        case 's': // self, set, str, super
  76.881 -            if (length == 4 && TokenUtilities.textEquals(s, "self")) { // NOI18N
  76.882 -                return PythonTokenId.ANY_KEYWORD;
  76.883 -            } else if (length == 3 && TokenUtilities.textEquals(s, "set")) { // NOI18N
  76.884 -                return PythonTokenId.STD_SYMBOLS;
  76.885 -            } else if (length == 3 && TokenUtilities.textEquals(s, "str")) { // NOI18N
  76.886 -                return PythonTokenId.STD_SYMBOLS;
  76.887 -            } else if (length == 5 && TokenUtilities.textEquals(s, "super")) { // NOI18N
  76.888 -                return PythonTokenId.ANY_KEYWORD;
  76.889 -            }
  76.890 -        case 't': // try, tuple, type
  76.891 -            if (length == 3 && TokenUtilities.textEquals(s, "try")) { // NOI18N
  76.892 -                return PythonTokenId.TRY;
  76.893 -            } else if (length == 5 && TokenUtilities.textEquals(s, "tuple")) { // NOI18N
  76.894 -                return PythonTokenId.STD_SYMBOLS;
  76.895 -            } else if (length == 4 && TokenUtilities.textEquals(s, "type")) { // NOI18N
  76.896 -                return PythonTokenId.STD_SYMBOLS;
  76.897 -            }
  76.898 -            break;
  76.899 -        case 'w': // while,with
  76.900 -            if (c2 == 'h') { // while
  76.901 -                if (length == 5 && TokenUtilities.textEquals(s, "while")) { // NOI18N
  76.902 -                    return PythonTokenId.ANY_KEYWORD;
  76.903 -                }
  76.904 -            } else if (c2 == 'i') { // with
  76.905 -                if (length == 4 && TokenUtilities.textEquals(s, "with")) { // NOI18N
  76.906 -                    return PythonTokenId.ANY_KEYWORD;
  76.907 -                }
  76.908 -            }
  76.909 -            break;
  76.910 -        case 'y': // yield
  76.911 -            if (length == 5 && TokenUtilities.textEquals(s, "yield")) { // NOI18N
  76.912 -                return PythonTokenId.ANY_KEYWORD;
  76.913 -            }
  76.914 -            break;
  76.915 -        case 'F': // False
  76.916 -            if (length == 5 && TokenUtilities.textEquals(s, "False")) { // NOI18N
  76.917 -                return PythonTokenId.FALSE;
  76.918 -            }
  76.919 -        case 'N': // None
  76.920 -            if (length == 4 && TokenUtilities.textEquals(s, "None")) { // NOI18N
  76.921 -                return PythonTokenId.NONE;
  76.922 -            }
  76.923 -        case 'T': // True
  76.924 -            if (length == 4 && TokenUtilities.textEquals(s, "True")) { // NOI18N
  76.925 -                return PythonTokenId.TRUE;
  76.926 -            }
  76.927 -        }
  76.928 -
  76.929 -        return null;
  76.930 -    }
  76.931 -}
    77.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/PythonLexerUtils.java	Sat Sep 12 23:03:15 2015 -0700
    77.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.3 @@ -1,558 +0,0 @@
    77.4 -/*
    77.5 - * To change this template, choose Tools | Templates
    77.6 - * and open the template in the editor.
    77.7 - */
    77.8 -package org.netbeans.modules.python.editor.lexer;
    77.9 -
   77.10 -import java.util.Arrays;
   77.11 -import java.util.List;
   77.12 -import java.util.regex.Matcher;
   77.13 -import java.util.regex.Pattern;
   77.14 -import javax.swing.text.BadLocationException;
   77.15 -import javax.swing.text.Document;
   77.16 -import org.netbeans.api.lexer.Token;
   77.17 -import org.netbeans.api.lexer.TokenHierarchy;
   77.18 -import org.netbeans.api.lexer.TokenId;
   77.19 -import org.netbeans.api.lexer.TokenSequence;
   77.20 -import org.netbeans.editor.BaseDocument;
   77.21 -import org.netbeans.editor.Utilities;
   77.22 -import org.netbeans.modules.csl.api.OffsetRange;
   77.23 -import org.netbeans.modules.python.editor.PythonParserResult;
   77.24 -import org.openide.filesystems.FileUtil;
   77.25 -import org.openide.loaders.DataObject;
   77.26 -import org.openide.util.Exceptions;
   77.27 -import org.python.antlr.PythonTree;
   77.28 -
   77.29 -/**
   77.30 - * Utility functions around the Python lexer
   77.31 - * 
   77.32 - * @author Tor Norbye
   77.33 - */
   77.34 -public class PythonLexerUtils {
   77.35 -    /**
   77.36 -     * Try to produce a more accurate location for the given name in the given import statement, located
   77.37 -     * at the lexRange provided
   77.38 -     */
   77.39 -    public static OffsetRange getImportNameOffset(BaseDocument doc, OffsetRange lexRange, PythonTree node, String name) {
   77.40 -        int docLength = doc.getLength();
   77.41 -        int start = Math.min(docLength, lexRange.getStart());
   77.42 -        int end = Math.min(docLength, lexRange.getEnd());
   77.43 -        try {
   77.44 -            String s = doc.getText(start, end - start);
   77.45 -
   77.46 -            Pattern p = Pattern.compile(".*import\\s+\\b(" + name + ")\\b.*");
   77.47 -            Matcher m = p.matcher(s);
   77.48 -            if (m.matches()) {
   77.49 -                int offset = start + m.start(1);
   77.50 -                return new OffsetRange(offset, offset + name.length());
   77.51 -            }
   77.52 -
   77.53 -            // Lame
   77.54 -            int searchIndex = s.indexOf("import ");
   77.55 -            if (searchIndex == -1) {
   77.56 -                searchIndex = 0;
   77.57 -            } else {
   77.58 -                searchIndex += 7;
   77.59 -            }
   77.60 -            int match = s.indexOf(name, searchIndex + 7);
   77.61 -            if (match != -1) {
   77.62 -                int offset = start + match;
   77.63 -                return new OffsetRange(offset, offset + name.length());
   77.64 -            }
   77.65 -
   77.66 -        // Give up - use the whole range
   77.67 -        } catch (BadLocationException ex) {
   77.68 -            Exceptions.printStackTrace(ex);
   77.69 -        }
   77.70 -
   77.71 -        return lexRange;
   77.72 -    }
   77.73 -
   77.74 -    /** For a possibly generated offset in an AST, return the corresponding lexing/true document offset */
   77.75 -    public static int getLexerOffset(PythonParserResult result, int astOffset) {
   77.76 -        return result.getSnapshot().getOriginalOffset(astOffset);
   77.77 -    }
   77.78 -
   77.79 -    public static OffsetRange getLexerOffsets(PythonParserResult result, OffsetRange astRange) {
   77.80 -        if (result != null) {
   77.81 -            int rangeStart = astRange.getStart();
   77.82 -            int start = result.getSnapshot().getOriginalOffset(rangeStart);
   77.83 -            if (start == rangeStart) {
   77.84 -                return astRange;
   77.85 -            } else if (start == -1) {
   77.86 -                return OffsetRange.NONE;
   77.87 -            } else {
   77.88 -                // Assumes the translated range maintains size
   77.89 -                return new OffsetRange(start, start + astRange.getLength());
   77.90 -            }
   77.91 -        }
   77.92 -
   77.93 -        return astRange;
   77.94 -    }
   77.95 -
   77.96 -    /**
   77.97 -     * Narrow a given lexical offset range to the closest AST-relevant offsets.
   77.98 -     * This means it will pass over things like comments and whitespace.
   77.99 -     * @param doc The document containing the range
  77.100 -     * @param range The start/end lexical range we want to narrow
  77.101 -     * @return An OffsetRange where the offsets begin and end at AST-relevant tokens
  77.102 -     */
  77.103 -    public static OffsetRange narrow(BaseDocument doc, OffsetRange range, boolean skipComments) {
  77.104 -        try {
  77.105 -            doc.readLock(); // For token hiearchy use
  77.106 -            // For token hiearchy use
  77.107 -            int start = range.getStart();
  77.108 -            TokenSequence<? extends PythonTokenId> ts = getPythonSequence(doc, start);
  77.109 -            if (ts != null) {
  77.110 -                int delta = ts.move(start);
  77.111 -                while (ts.moveNext()) {
  77.112 -                    Token<? extends PythonTokenId> token = ts.token();
  77.113 -                    PythonTokenId id = token.id();
  77.114 -                    if (id != PythonTokenId.NEWLINE && (!skipComments || id != PythonTokenId.COMMENT) && id != PythonTokenId.WHITESPACE) {
  77.115 -                        if (delta != 0) {
  77.116 -                            return OffsetRange.NONE;
  77.117 -                        }
  77.118 -                        start = ts.offset();
  77.119 -                        break;
  77.120 -                    } else {
  77.121 -                        delta = 0;
  77.122 -                    }
  77.123 -                }
  77.124 -            }
  77.125 -            int end = range.getEnd();
  77.126 -            ts = getPositionedSequence(doc, end);
  77.127 -            if (ts != null) {
  77.128 -                int delta = ts.move(end);
  77.129 -                while (delta > 0 ? ts.moveNext() : ts.movePrevious()) {
  77.130 -                    Token<? extends PythonTokenId> token = ts.token();
  77.131 -                    PythonTokenId id = token.id();
  77.132 -                    if (id != PythonTokenId.NEWLINE && (!skipComments || id != PythonTokenId.COMMENT) && id != PythonTokenId.WHITESPACE) {
  77.133 -                        if (delta != 0) {
  77.134 -                            return OffsetRange.NONE;
  77.135 -                        }
  77.136 -                        end = ts.offset() + token.length();
  77.137 -                        break;
  77.138 -                    } else {
  77.139 -                        delta = 0;
  77.140 -                    }
  77.141 -                }
  77.142 -            }
  77.143 -
  77.144 -            if (end < start) {
  77.145 -                return OffsetRange.NONE;
  77.146 -            }
  77.147 -
  77.148 -            return new OffsetRange(start, end);
  77.149 -        } finally {
  77.150 -            doc.readUnlock();
  77.151 -        }
  77.152 -    }
  77.153 -
  77.154 -    /** Find the ruby token sequence (in case it's embedded in something else at the top level */
  77.155 -    @SuppressWarnings("unchecked")
  77.156 -    public static TokenSequence<? extends PythonTokenId> getPythonSequence(BaseDocument doc, int offset) {
  77.157 -        TokenHierarchy<Document> th = TokenHierarchy.get((Document)doc);
  77.158 -        return getPythonSequence(th, offset);
  77.159 -    }
  77.160 -
  77.161 -    @SuppressWarnings("unchecked")
  77.162 -    public static TokenSequence<? extends PythonTokenId> getPythonSequence(TokenHierarchy<Document> th, int offset) {
  77.163 -        TokenSequence<? extends PythonTokenId> ts = th.tokenSequence(PythonTokenId.language());
  77.164 -
  77.165 -        if (ts == null) {
  77.166 -            // Possibly an embedding scenario such as an RHTML file
  77.167 -            // First try with backward bias true
  77.168 -            List<TokenSequence<?>> list = th.embeddedTokenSequences(offset, true);
  77.169 -
  77.170 -            for (TokenSequence t : list) {
  77.171 -                if (t.language() == PythonTokenId.language()) {
  77.172 -                    ts = t;
  77.173 -
  77.174 -                    break;
  77.175 -                }
  77.176 -            }
  77.177 -
  77.178 -            if (ts == null) {
  77.179 -                list = th.embeddedTokenSequences(offset, false);
  77.180 -
  77.181 -                for (TokenSequence t : list) {
  77.182 -                    if (t.language() == PythonTokenId.language()) {
  77.183 -                        ts = t;
  77.184 -
  77.185 -                        break;
  77.186 -                    }
  77.187 -                }
  77.188 -            }
  77.189 -        }
  77.190 -
  77.191 -        return ts;
  77.192 -    }
  77.193 -
  77.194 -    public static TokenSequence<? extends PythonTokenId> getPositionedSequence(BaseDocument doc, int offset) {
  77.195 -        return getPositionedSequence(doc, offset, true);
  77.196 -    }
  77.197 -
  77.198 -    public static TokenSequence<? extends PythonTokenId> getPositionedSequence(BaseDocument doc, int offset, boolean lookBack) {
  77.199 -        TokenSequence<? extends PythonTokenId> ts = getPythonSequence(doc, offset);
  77.200 -
  77.201 -        if (ts != null) {
  77.202 -            try {
  77.203 -                ts.move(offset);
  77.204 -            } catch (AssertionError e) {
  77.205 -                DataObject dobj = (DataObject)doc.getProperty(Document.StreamDescriptionProperty);
  77.206 -
  77.207 -                if (dobj != null) {
  77.208 -                    Exceptions.attachMessage(e, FileUtil.getFileDisplayName(dobj.getPrimaryFile()));
  77.209 -                }
  77.210 -
  77.211 -                throw e;
  77.212 -            }
  77.213 -
  77.214 -            if (!lookBack && !ts.moveNext()) {
  77.215 -                return null;
  77.216 -            } else if (lookBack && !ts.moveNext() && !ts.movePrevious()) {
  77.217 -                return null;
  77.218 -            }
  77.219 -
  77.220 -            /* TODO - allow Python inside strings
  77.221 -            if (ts.token().id() == PythonTokenId.STRING_LITERAL) {
  77.222 -            TokenSequence<? extends PythonStringTokenId> ets = ts.embedded(PythonStringTokenId.language());
  77.223 -            if (ets != null) {
  77.224 -            ets.move(offset);
  77.225 -            if ((!lookBack && ets.moveNext()) || (lookBack && ets.movePrevious())) {
  77.226 -            TokenSequence<?extends PythonTokenId> epts = ets.embedded(PythonTokenId.language());
  77.227 -            if (epts != null) {
  77.228 -            epts.move(offset);
  77.229 -            if (!lookBack && !epts.moveNext()) {
  77.230 -            return null;
  77.231 -            } else if (lookBack && !epts.moveNext() && !epts.movePrevious()) {
  77.232 -            return null;
  77.233 -            }
  77.234 -            return epts;
  77.235 -            }
  77.236 -            }
  77.237 -            }
  77.238 -            }
  77.239 -             */
  77.240 -
  77.241 -            return ts;
  77.242 -        }
  77.243 -
  77.244 -        return null;
  77.245 -    }
  77.246 -
  77.247 -    public static Token<? extends PythonTokenId> getToken(BaseDocument doc, int offset) {
  77.248 -        TokenSequence<? extends PythonTokenId> ts = getPositionedSequence(doc, offset);
  77.249 -
  77.250 -        if (ts != null) {
  77.251 -            return ts.token();
  77.252 -        }
  77.253 -
  77.254 -        return null;
  77.255 -    }
  77.256 -
  77.257 -    public static char getTokenChar(BaseDocument doc, int offset) {
  77.258 -        Token<? extends PythonTokenId> token = getToken(doc, offset);
  77.259 -
  77.260 -        if (token != null) {
  77.261 -            String text = token.text().toString();
  77.262 -
  77.263 -            if (text.length() > 0) { // Usually true, but I could have gotten EOF right?
  77.264 -
  77.265 -                return text.charAt(0);
  77.266 -            }
  77.267 -        }
  77.268 -
  77.269 -        return 0;
  77.270 -    }
  77.271 -
  77.272 -    public static Token<? extends PythonTokenId> findNextNonWsNonComment(TokenSequence<? extends PythonTokenId> ts) {
  77.273 -        return findNext(ts, Arrays.asList(PythonTokenId.WHITESPACE, PythonTokenId.NEWLINE, PythonTokenId.COMMENT));
  77.274 -    }
  77.275 -
  77.276 -    public static Token<? extends PythonTokenId> findPreviousNonWsNonComment(TokenSequence<? extends PythonTokenId> ts) {
  77.277 -        return findPrevious(ts, Arrays.asList(PythonTokenId.WHITESPACE, PythonTokenId.NEWLINE, PythonTokenId.COMMENT));
  77.278 -    }
  77.279 -
  77.280 -    public static Token<? extends PythonTokenId> findNext(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> ignores) {
  77.281 -        if (ignores.contains(ts.token().id())) {
  77.282 -            while (ts.moveNext() && ignores.contains(ts.token().id())) {
  77.283 -            }
  77.284 -        }
  77.285 -        return ts.token();
  77.286 -    }
  77.287 -
  77.288 -    public static Token<? extends PythonTokenId> findNextIncluding(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> includes) {
  77.289 -        while (ts.moveNext() && !includes.contains(ts.token().id())) {
  77.290 -        }
  77.291 -        return ts.token();
  77.292 -    }
  77.293 -
  77.294 -    public static Token<? extends PythonTokenId> findPreviousIncluding(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> includes) {
  77.295 -        while (ts.movePrevious() && !includes.contains(ts.token().id())) {
  77.296 -        }
  77.297 -        return ts.token();
  77.298 -    }
  77.299 -
  77.300 -    public static Token<? extends PythonTokenId> findPrevious(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> ignores) {
  77.301 -        if (ignores.contains(ts.token().id())) {
  77.302 -            while (ts.movePrevious() && ignores.contains(ts.token().id())) {
  77.303 -            }
  77.304 -        }
  77.305 -        return ts.token();
  77.306 -    }
  77.307 -
  77.308 -    static boolean skipParenthesis(TokenSequence<? extends PythonTokenId> ts) {
  77.309 -        return skipParenthesis(ts, false);
  77.310 -    }
  77.311 -
  77.312 -    /**
  77.313 -     * Tries to skip parenthesis
  77.314 -     */
  77.315 -    public static boolean skipParenthesis(TokenSequence<? extends PythonTokenId> ts, boolean back) {
  77.316 -        int balance = 0;
  77.317 -
  77.318 -        Token<? extends PythonTokenId> token = ts.token();
  77.319 -        if (token == null) {
  77.320 -            return false;
  77.321 -        }
  77.322 -
  77.323 -        TokenId id = token.id();
  77.324 -
  77.325 -        if (id == PythonTokenId.WHITESPACE || id == PythonTokenId.NEWLINE) {
  77.326 -            while ((back ? ts.movePrevious() : ts.moveNext()) && (ts.token().id() == PythonTokenId.WHITESPACE || ts.token().id() == PythonTokenId.NEWLINE)) {
  77.327 -            }
  77.328 -        }
  77.329 -
  77.330 -        // if current token is not left parenthesis
  77.331 -        if (ts.token().id() != (back ? PythonTokenId.RPAREN : PythonTokenId.LPAREN)) {
  77.332 -            return false;
  77.333 -        }
  77.334 -
  77.335 -        do {
  77.336 -            token = ts.token();
  77.337 -            id = token.id();
  77.338 -
  77.339 -            if (id == (back ? PythonTokenId.RPAREN : PythonTokenId.LPAREN)) {
  77.340 -                balance++;
  77.341 -            } else if (id == (back ? PythonTokenId.LPAREN : PythonTokenId.RPAREN)) {
  77.342 -                if (balance == 0) {
  77.343 -                    return false;
  77.344 -                } else if (balance == 1) {
  77.345 -                    //int length = ts.offset() + token.length();
  77.346 -                    if (back) {
  77.347 -                        ts.movePrevious();
  77.348 -                    } else {
  77.349 -                        ts.moveNext();
  77.350 -                    }
  77.351 -                    return true;
  77.352 -                }
  77.353 -
  77.354 -                balance--;
  77.355 -            }
  77.356 -        } while (back ? ts.movePrevious() : ts.moveNext());
  77.357 -
  77.358 -        return false;
  77.359 -    }
  77.360 -
  77.361 -    /** Search forwards in the token sequence until a token of type <code>down</code> is found */
  77.362 -    public static OffsetRange findFwd(BaseDocument doc, TokenSequence<? extends PythonTokenId> ts, TokenId up,
  77.363 -            TokenId down) {
  77.364 -        int balance = 0;
  77.365 -
  77.366 -        while (ts.moveNext()) {
  77.367 -            Token<? extends PythonTokenId> token = ts.token();
  77.368 -            TokenId id = token.id();
  77.369 -
  77.370 -            if (id == up) {
  77.371 -                balance++;
  77.372 -            } else if (id == down) {
  77.373 -                if (balance == 0) {
  77.374 -                    return new OffsetRange(ts.offset(), ts.offset() + token.length());
  77.375 -                }
  77.376 -
  77.377 -                balance--;
  77.378 -            }
  77.379 -        }
  77.380 -
  77.381 -        return OffsetRange.NONE;
  77.382 -    }
  77.383 -
  77.384 -    /** Search backwards in the token sequence until a token of type <code>up</code> is found */
  77.385 -    public static OffsetRange findBwd(BaseDocument doc, TokenSequence<? extends PythonTokenId> ts, TokenId up,
  77.386 -            TokenId down) {
  77.387 -        int balance = 0;
  77.388 -
  77.389 -        while (ts.movePrevious()) {
  77.390 -            Token<? extends PythonTokenId> token = ts.token();
  77.391 -            TokenId id = token.id();
  77.392 -
  77.393 -            if (id == up) {
  77.394 -                if (balance == 0) {
  77.395 -                    return new OffsetRange(ts.offset(), ts.offset() + token.length());
  77.396 -                }
  77.397 -
  77.398 -                balance++;
  77.399 -            } else if (id == down) {
  77.400 -                balance--;
  77.401 -            }
  77.402 -        }
  77.403 -
  77.404 -        return OffsetRange.NONE;
  77.405 -    }
  77.406 -
  77.407 -    /** Compute the balance of begin/end tokens on the line */
  77.408 -    public static int getLineBalance(BaseDocument doc, int offset, TokenId up, TokenId down) {
  77.409 -        try {
  77.410 -            int begin = Utilities.getRowStart(doc, offset);
  77.411 -            int end = Utilities.getRowEnd(doc, offset);
  77.412 -
  77.413 -            TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(doc, begin);
  77.414 -            if (ts == null) {
  77.415 -                return 0;
  77.416 -            }
  77.417 -
  77.418 -            ts.move(begin);
  77.419 -
  77.420 -            if (!ts.moveNext()) {
  77.421 -                return 0;
  77.422 -            }
  77.423 -
  77.424 -            int balance = 0;
  77.425 -
  77.426 -            do {
  77.427 -                Token<? extends PythonTokenId> token = ts.token();
  77.428 -                TokenId id = token.id();
  77.429 -
  77.430 -                if (id == up) {
  77.431 -                    balance++;
  77.432 -                } else if (id == down) {
  77.433 -                    balance--;
  77.434 -                }
  77.435 -            } while (ts.moveNext() && (ts.offset() <= end));
  77.436 -
  77.437 -            return balance;
  77.438 -        } catch (BadLocationException ble) {
  77.439 -            Exceptions.printStackTrace(ble);
  77.440 -
  77.441 -            return 0;
  77.442 -        }
  77.443 -    }
  77.444 -
  77.445 -    /**
  77.446 -     * The same as braceBalance but generalized to any pair of matching
  77.447 -     * tokens.
  77.448 -     * @param open the token that increses the count
  77.449 -     * @param close the token that decreses the count
  77.450 -     */
  77.451 -    public static int getTokenBalance(BaseDocument doc, TokenId open, TokenId close, int offset)
  77.452 -            throws BadLocationException {
  77.453 -        TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(doc, 0);
  77.454 -        if (ts == null) {
  77.455 -            return 0;
  77.456 -        }
  77.457 -
  77.458 -        // XXX Why 0? Why not offset?
  77.459 -        ts.moveIndex(0);
  77.460 -
  77.461 -        if (!ts.moveNext()) {
  77.462 -            return 0;
  77.463 -        }
  77.464 -
  77.465 -        int balance = 0;
  77.466 -
  77.467 -        do {
  77.468 -            Token t = ts.token();
  77.469 -
  77.470 -            if (t.id() == open) {
  77.471 -                balance++;
  77.472 -            } else if (t.id() == close) {
  77.473 -                balance--;
  77.474 -            }
  77.475 -        } while (ts.moveNext());
  77.476 -
  77.477 -        return balance;
  77.478 -    }
  77.479 -
  77.480 -    /**
  77.481 -     * Return true iff the line for the given offset is a JavaScript comment line.
  77.482 -     * This will return false for lines that contain comments (even when the
  77.483 -     * offset is within the comment portion) but also contain code.
  77.484 -     */
  77.485 -    public static boolean isCommentOnlyLine(BaseDocument doc, int offset)
  77.486 -            throws BadLocationException {
  77.487 -        int begin = Utilities.getRowFirstNonWhite(doc, offset);
  77.488 -
  77.489 -        if (begin == -1) {
  77.490 -            return false; // whitespace only
  77.491 -        }
  77.492 -
  77.493 -        Token<? extends PythonTokenId> token = PythonLexerUtils.getToken(doc, begin);
  77.494 -        if (token != null) {
  77.495 -            return token.id() == PythonTokenId.COMMENT;
  77.496 -        }
  77.497 -
  77.498 -        return false;
  77.499 -    }
  77.500 -
  77.501 -    /**
  77.502 -     * Back up to the first space character prior to the given offset - as long as
  77.503 -     * it's on the same line!  If there's only leading whitespace on the line up
  77.504 -     * to the lex offset, return the offset itself
  77.505 -     * @todo Rewrite this now that I have a separate newline token, EOL, that I can
  77.506 -     *   break on - no need to call Utilities.getRowStart.
  77.507 -     */
  77.508 -    public static int findSpaceBegin(BaseDocument doc, int lexOffset) {
  77.509 -        TokenSequence ts = getPythonSequence(doc, lexOffset);
  77.510 -        if (ts == null) {
  77.511 -            return lexOffset;
  77.512 -        }
  77.513 -        boolean allowPrevLine = false;
  77.514 -        int lineStart;
  77.515 -        try {
  77.516 -            lineStart = Utilities.getRowStart(doc, Math.min(lexOffset, doc.getLength()));
  77.517 -            int prevLast = lineStart - 1;
  77.518 -            if (lineStart > 0) {
  77.519 -                prevLast = Utilities.getRowLastNonWhite(doc, lineStart - 1);
  77.520 -                if (prevLast != -1) {
  77.521 -                    char c = doc.getText(prevLast, 1).charAt(0);
  77.522 -                    if (c == ',') {
  77.523 -                        // Arglist continuation? // TODO : check lexing
  77.524 -                        allowPrevLine = true;
  77.525 -                    }
  77.526 -                }
  77.527 -            }
  77.528 -            if (!allowPrevLine) {
  77.529 -                int firstNonWhite = Utilities.getRowFirstNonWhite(doc, lineStart);
  77.530 -                if (lexOffset <= firstNonWhite || firstNonWhite == -1) {
  77.531 -                    return lexOffset;
  77.532 -                }
  77.533 -            } else {
  77.534 -                // Make lineStart so small that Math.max won't cause any problems
  77.535 -                int firstNonWhite = Utilities.getRowFirstNonWhite(doc, lineStart);
  77.536 -                if (prevLast >= 0 && (lexOffset <= firstNonWhite || firstNonWhite == -1)) {
  77.537 -                    return prevLast + 1;
  77.538 -                }
  77.539 -                lineStart = 0;
  77.540 -            }
  77.541 -        } catch (BadLocationException ble) {
  77.542 -            Exceptions.printStackTrace(ble);
  77.543 -            return lexOffset;
  77.544 -        }
  77.545 -        ts.move(lexOffset);
  77.546 -        if (ts.moveNext()) {
  77.547 -            if (lexOffset > ts.offset()) {
  77.548 -                // We're in the middle of a token
  77.549 -                return Math.max((ts.token().id() == PythonTokenId.WHITESPACE) ? ts.offset() : lexOffset, lineStart);
  77.550 -            }
  77.551 -            while (ts.movePrevious()) {
  77.552 -                Token token = ts.token();
  77.553 -                if (token.id() != PythonTokenId.WHITESPACE) {
  77.554 -                    return Math.max(ts.offset() + token.length(), lineStart);
  77.555 -                }
  77.556 -            }
  77.557 -        }
  77.558 -
  77.559 -        return lexOffset;
  77.560 -    }
  77.561 -}
    78.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/PythonStringLexer.java	Sat Sep 12 23:03:15 2015 -0700
    78.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.3 @@ -1,292 +0,0 @@
    78.4 -/*
    78.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    78.6 - *
    78.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    78.8 - *
    78.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   78.10 - * Other names may be trademarks of their respective owners.
   78.11 - *
   78.12 - * The contents of this file are subject to the terms of either the GNU
   78.13 - * General Public License Version 2 only ("GPL") or the Common
   78.14 - * Development and Distribution License("CDDL") (collectively, the
   78.15 - * "License"). You may not use this file except in compliance with the
   78.16 - * License. You can obtain a copy of the License at
   78.17 - * http://www.netbeans.org/cddl-gplv2.html
   78.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   78.19 - * specific language governing permissions and limitations under the
   78.20 - * License.  When distributing the software, include this License Header
   78.21 - * Notice in each file and include the License file at
   78.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   78.23 - * particular file as subject to the "Classpath" exception as provided
   78.24 - * by Oracle in the GPL Version 2 section of the License file that
   78.25 - * accompanied this code. If applicable, add the following below the
   78.26 - * License Header, with the fields enclosed by brackets [] replaced by
   78.27 - * your own identifying information:
   78.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   78.29 - *
   78.30 - * Contributor(s):
   78.31 - *
   78.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   78.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   78.34 - * Microsystems, Inc. All Rights Reserved.
   78.35 - *
   78.36 - * If you wish your version of this file to be governed by only the CDDL
   78.37 - * or only the GPL Version 2, indicate your decision by adding
   78.38 - * "[Contributor] elects to include this software in this distribution
   78.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   78.40 - * single choice of license, a recipient has the option to distribute
   78.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   78.42 - * to extend the choice of license to its licensees as provided above.
   78.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   78.44 - * Version 2 license, then the option applies only if the new code is
   78.45 - * made subject to such option by the copyright holder.
   78.46 - */
   78.47 -package org.netbeans.modules.python.editor.lexer;
   78.48 -
   78.49 -import org.netbeans.api.lexer.Token;
   78.50 -import org.netbeans.spi.lexer.Lexer;
   78.51 -import org.netbeans.spi.lexer.LexerInput;
   78.52 -import org.netbeans.spi.lexer.LexerRestartInfo;
   78.53 -import org.netbeans.spi.lexer.TokenFactory;
   78.54 -
   78.55 -/**
   78.56 - * A lexer for python strings. Highlights escape sequences, and recognizes
   78.57 - * doctest sections and highlights these as well.
   78.58 - *   http://docs.python.org/lib/module-doctest.html
   78.59 - *
   78.60 - * @todo Track whether strings are raw or not, and don't do escape sequence
   78.61 - *  highlighting in raw strings
   78.62 - *
   78.63 - * @author Tor Norbye
   78.64 - */
   78.65 -public class PythonStringLexer implements Lexer<PythonStringTokenId> {
   78.66 -    private static final int EOF = LexerInput.EOF;
   78.67 -    private final LexerInput input;
   78.68 -    private final TokenFactory<PythonStringTokenId> tokenFactory;
   78.69 -    private final boolean substituting;
   78.70 -
   78.71 -    /**
   78.72 -     * A Lexer for Python strings
   78.73 -     * @param substituting If true, handle substitution rules for double quoted strings, otherwise
   78.74 -     *    single quoted strings.
   78.75 -     */
   78.76 -    public PythonStringLexer(LexerRestartInfo<PythonStringTokenId> info, boolean substituting) {
   78.77 -        this.input = info.input();
   78.78 -        this.tokenFactory = info.tokenFactory();
   78.79 -        this.substituting = substituting;
   78.80 -        assert (info.state() == null); // passed argument always null
   78.81 -    }
   78.82 -
   78.83 -    @Override
   78.84 -    public Object state() {
   78.85 -        return null;
   78.86 -    }
   78.87 -
   78.88 -    @Override
   78.89 -    public Token<PythonStringTokenId> nextToken() {
   78.90 -        boolean inWord = false;
   78.91 -        while (true) {
   78.92 -            int ch = input.read();
   78.93 -
   78.94 -            switch (ch) {
   78.95 -            case EOF:
   78.96 -
   78.97 -                if (input.readLength() > 0) {
   78.98 -                    return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
   78.99 -                            input.readLength());
  78.100 -                } else {
  78.101 -                    return null;
  78.102 -                }
  78.103 -
  78.104 -            case '>':
  78.105 -                // Look for doctest:  \n, whitespace, >>>{embedded python}\n
  78.106 -                int initialReadLength = input.readLength();
  78.107 -                input.read();
  78.108 -                if (ch == '>') {
  78.109 -                    ch = input.read();
  78.110 -                    if (ch == '>') {
  78.111 -                        if (input.readLength() > 3) {
  78.112 -                            input.backup(3);
  78.113 -                            // Finish this token such that we can do a dedicated token for the ">>>" line.
  78.114 -                            return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
  78.115 -                                    input.readLength());
  78.116 -                        }
  78.117 -                        // Find end...
  78.118 -                        boolean nonempty = false;
  78.119 -                        while (true) {
  78.120 -                            ch = input.read();
  78.121 -                            if (ch == EOF) {
  78.122 -                                break;
  78.123 -                            } else if (ch == '\n') {
  78.124 -                                if (nonempty) {
  78.125 -                                    input.backup(1); // Don't include the \n
  78.126 -                                    return tokenFactory.createToken(PythonStringTokenId.EMBEDDED_PYTHON,
  78.127 -                                            input.readLength());
  78.128 -
  78.129 -                                }
  78.130 -                                break;
  78.131 -                            } else if (!Character.isWhitespace(ch)) {
  78.132 -                                nonempty = true;
  78.133 -                            }
  78.134 -                        }
  78.135 -                    }
  78.136 -                }
  78.137 -                if (input.readLength() > initialReadLength) {
  78.138 -                    input.backup(input.readLength() - initialReadLength);
  78.139 -                } else {
  78.140 -                    return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
  78.141 -                            input.readLength());
  78.142 -                }
  78.143 -                break;
  78.144 -
  78.145 -            case '\\':
  78.146 -
  78.147 -                if (input.readLength() > 1) { // already read some text
  78.148 -                    input.backup(1);
  78.149 -
  78.150 -                    return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
  78.151 -                            input.readLength());
  78.152 -                }
  78.153 -
  78.154 -                ch = input.read();
  78.155 -                if (ch == EOF) {
  78.156 -                    return tokenFactory.createToken(PythonStringTokenId.STRING_INVALID,
  78.157 -                            input.readLength());
  78.158 -                } else {
  78.159 -                    return tokenFactory.createToken(PythonStringTokenId.STRING_ESCAPE,
  78.160 -                            input.readLength());
  78.161 -                }
  78.162 -
  78.163 -            case 'f': // ftp:
  78.164 -            case 'm': // mailto:
  78.165 -            case 'w': // www.
  78.166 -            case 'h': { // http links. TODO: link:, ftp:, mailto:, and www.
  78.167 -
  78.168 -                if (inWord) {
  78.169 -                    break;
  78.170 -                }
  78.171 -
  78.172 -                int originalLength = input.readLength();
  78.173 -                boolean foundLinkBegin = false;
  78.174 -
  78.175 -                if (ch == 'h') { // http:
  78.176 -
  78.177 -                    if (input.read() == 't') {
  78.178 -                        if (input.read() == 't') {
  78.179 -                            if (input.read() == 'p') {
  78.180 -                                int r = input.read();
  78.181 -                                if (r == ':') {
  78.182 -                                    foundLinkBegin = true;
  78.183 -                                } else if (r == 's') {
  78.184 -                                    if (input.read() == ':') {
  78.185 -                                        foundLinkBegin = true;
  78.186 -                                    } else {
  78.187 -                                        input.backup(5);
  78.188 -                                    }
  78.189 -                                } else {
  78.190 -                                    input.backup(4);
  78.191 -                                }
  78.192 -                            } else {
  78.193 -                                input.backup(3);
  78.194 -                            }
  78.195 -                        } else {
  78.196 -                            input.backup(2);
  78.197 -                        }
  78.198 -                    } else {
  78.199 -                        input.backup(1);
  78.200 -                    }
  78.201 -                } else if (ch == 'f') { // ftp:
  78.202 -
  78.203 -                    if (input.read() == 't') {
  78.204 -                        if (input.read() == 'p') {
  78.205 -                            if (input.read() == ':') {
  78.206 -                                foundLinkBegin = true;
  78.207 -                            } else {
  78.208 -                                input.backup(3);
  78.209 -                            }
  78.210 -                        } else {
  78.211 -                            input.backup(2);
  78.212 -                        }
  78.213 -                    } else {
  78.214 -                        input.backup(1);
  78.215 -                    }
  78.216 -                } else if (ch == 'm') { // mailto:
  78.217 -
  78.218 -                    if (input.read() == 'a') {
  78.219 -                        if (input.read() == 'i') {
  78.220 -                            if (input.read() == 'l') {
  78.221 -                                if (input.read() == 't') {
  78.222 -                                    if (input.read() == 'o') {
  78.223 -                                        if (input.read() == ':') {
  78.224 -                                            foundLinkBegin = true;
  78.225 -                                        } else {
  78.226 -                                            input.backup(6);
  78.227 -                                        }
  78.228 -                                    } else {
  78.229 -                                        input.backup(5);
  78.230 -                                    }
  78.231 -                                } else {
  78.232 -                                    input.backup(4);
  78.233 -                                }
  78.234 -                            } else {
  78.235 -                                input.backup(3);
  78.236 -                            }
  78.237 -                        } else {
  78.238 -                            input.backup(2);
  78.239 -                        }
  78.240 -                    } else {
  78.241 -                        input.backup(1);
  78.242 -                    }
  78.243 -                } else if (ch == 'w') { // www.
  78.244 -
  78.245 -                    if (input.read() == 'w') {
  78.246 -                        if (input.read() == 'w') {
  78.247 -                            if (input.read() == '.') {
  78.248 -                                foundLinkBegin = true;
  78.249 -                            } else {
  78.250 -                                input.backup(3);
  78.251 -                            }
  78.252 -                        } else {
  78.253 -                            input.backup(2);
  78.254 -                        }
  78.255 -                    } else {
  78.256 -                        input.backup(1);
  78.257 -                    }
  78.258 -                }
  78.259 -
  78.260 -                if (foundLinkBegin) {
  78.261 -                    while (ch != EOF) {
  78.262 -                        ch = input.read();
  78.263 -
  78.264 -                        if ((ch == ']') || (ch == ')') || Character.isWhitespace(ch) ||
  78.265 -                                (ch == '\'') || (ch == '"')) {
  78.266 -                            input.backup(1);
  78.267 -
  78.268 -                            break;
  78.269 -                        }
  78.270 -                    }
  78.271 -
  78.272 -                    if (originalLength > 1) {
  78.273 -                        input.backup(input.readLengthEOF() - originalLength + 1);
  78.274 -
  78.275 -                        return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
  78.276 -                                input.readLength());
  78.277 -                    }
  78.278 -
  78.279 -                    if (input.readLength() > 2) {
  78.280 -                        return tokenFactory.createToken(PythonStringTokenId.URL,
  78.281 -                                input.readLength());
  78.282 -                    }
  78.283 -                }
  78.284 -                break;
  78.285 -            }
  78.286 -            }
  78.287 -
  78.288 -            inWord = Character.isJavaIdentifierPart(ch);
  78.289 -        }
  78.290 -    }
  78.291 -
  78.292 -    @Override
  78.293 -    public void release() {
  78.294 -    }
  78.295 -}
    79.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/PythonStringTokenId.java	Sat Sep 12 23:03:15 2015 -0700
    79.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.3 @@ -1,125 +0,0 @@
    79.4 -/*
    79.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    79.6 - *
    79.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    79.8 - *
    79.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   79.10 - * Other names may be trademarks of their respective owners.
   79.11 - *
   79.12 - * The contents of this file are subject to the terms of either the GNU
   79.13 - * General Public License Version 2 only ("GPL") or the Common
   79.14 - * Development and Distribution License("CDDL") (collectively, the
   79.15 - * "License"). You may not use this file except in compliance with the
   79.16 - * License. You can obtain a copy of the License at
   79.17 - * http://www.netbeans.org/cddl-gplv2.html
   79.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   79.19 - * specific language governing permissions and limitations under the
   79.20 - * License.  When distributing the software, include this License Header
   79.21 - * Notice in each file and include the License file at
   79.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   79.23 - * particular file as subject to the "Classpath" exception as provided
   79.24 - * by Oracle in the GPL Version 2 section of the License file that
   79.25 - * accompanied this code. If applicable, add the following below the
   79.26 - * License Header, with the fields enclosed by brackets [] replaced by
   79.27 - * your own identifying information:
   79.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   79.29 - *
   79.30 - * Contributor(s):
   79.31 - *
   79.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   79.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   79.34 - * Microsystems, Inc. All Rights Reserved.
   79.35 - *
   79.36 - * If you wish your version of this file to be governed by only the CDDL
   79.37 - * or only the GPL Version 2, indicate your decision by adding
   79.38 - * "[Contributor] elects to include this software in this distribution
   79.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   79.40 - * single choice of license, a recipient has the option to distribute
   79.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   79.42 - * to extend the choice of license to its licensees as provided above.
   79.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   79.44 - * Version 2 license, then the option applies only if the new code is
   79.45 - * made subject to such option by the copyright holder.
   79.46 - */
   79.47 -package org.netbeans.modules.python.editor.lexer;
   79.48 -
   79.49 -import java.util.Collection;
   79.50 -import java.util.EnumSet;
   79.51 -import java.util.Map;
   79.52 -
   79.53 -import org.netbeans.api.lexer.InputAttributes;
   79.54 -import org.netbeans.api.lexer.Language;
   79.55 -import org.netbeans.api.lexer.LanguagePath;
   79.56 -import org.netbeans.api.lexer.Token;
   79.57 -import org.netbeans.api.lexer.TokenId;
   79.58 -import org.netbeans.api.lexer.TokenUtilities;
   79.59 -import org.netbeans.spi.lexer.LanguageEmbedding;
   79.60 -import org.netbeans.spi.lexer.LanguageHierarchy;
   79.61 -import org.netbeans.spi.lexer.Lexer;
   79.62 -import org.netbeans.spi.lexer.LexerRestartInfo;
   79.63 -
   79.64 -/**
   79.65 - *
   79.66 - * @author Tor Norbye
   79.67 - */
   79.68 -public enum PythonStringTokenId implements TokenId {
   79.69 -    STRING_TEXT("string"),
   79.70 -    STRING_ESCAPE("string-escape"),
   79.71 -    STRING_INVALID("string-escape-invalid"),
   79.72 -    URL("url"),
   79.73 -    EMBEDDED_PYTHON("string");
   79.74 -    private final String primaryCategory;
   79.75 -
   79.76 -    PythonStringTokenId() {
   79.77 -        this(null);
   79.78 -    }
   79.79 -
   79.80 -    PythonStringTokenId(String primaryCategory) {
   79.81 -        this.primaryCategory = primaryCategory;
   79.82 -    }
   79.83 -
   79.84 -    @Override
   79.85 -    public String primaryCategory() {
   79.86 -        return primaryCategory;
   79.87 -    }
   79.88 -    public static final Language<PythonStringTokenId> language =
   79.89 -            new LanguageHierarchy<PythonStringTokenId>() {
   79.90 -                @Override
   79.91 -                protected Collection<PythonStringTokenId> createTokenIds() {
   79.92 -                    return EnumSet.allOf(PythonStringTokenId.class);
   79.93 -                }
   79.94 -
   79.95 -                @Override
   79.96 -                protected Map<String, Collection<PythonStringTokenId>> createTokenCategories() {
   79.97 -                    return null; // no extra categories
   79.98 -                }
   79.99 -
  79.100 -                @Override
  79.101 -                protected Lexer<PythonStringTokenId> createLexer(
  79.102 -                        LexerRestartInfo<PythonStringTokenId> info) {
  79.103 -                    return new PythonStringLexer(info, true);
  79.104 -                }
  79.105 -
  79.106 -                @Override
  79.107 -                protected LanguageEmbedding<?> embedding(
  79.108 -                        Token<PythonStringTokenId> token, LanguagePath languagePath,
  79.109 -                        InputAttributes inputAttributes) {
  79.110 -                    PythonStringTokenId id = token.id();
  79.111 -
  79.112 -                    if (id == EMBEDDED_PYTHON && token.text() != null) {
  79.113 -                        return LanguageEmbedding.create(PythonTokenId.language(), 3, 0); // 3: Exlude ">>>" prefix
  79.114 -                    }
  79.115 -
  79.116 -                    return null; // No embedding
  79.117 -                }
  79.118 -
  79.119 -                @Override
  79.120 -                public String mimeType() {
  79.121 -                    return "text/x-python-string"; // NOI18N
  79.122 -                }
  79.123 -            }.language();
  79.124 -
  79.125 -    public static Language<PythonStringTokenId> language() {
  79.126 -        return language;
  79.127 -    }
  79.128 -}
    80.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/PythonTokenId.java	Sat Sep 12 23:03:15 2015 -0700
    80.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.3 @@ -1,206 +0,0 @@
    80.4 -/*
    80.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    80.6 - *
    80.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    80.8 - *
    80.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   80.10 - * Other names may be trademarks of their respective owners.
   80.11 - *
   80.12 - * The contents of this file are subject to the terms of either the GNU
   80.13 - * General Public License Version 2 only ("GPL") or the Common
   80.14 - * Development and Distribution License("CDDL") (collectively, the
   80.15 - * "License"). You may not use this file except in compliance with the
   80.16 - * License. You can obtain a copy of the License at
   80.17 - * http://www.netbeans.org/cddl-gplv2.html
   80.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   80.19 - * specific language governing permissions and limitations under the
   80.20 - * License.  When distributing the software, include this License Header
   80.21 - * Notice in each file and include the License file at
   80.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   80.23 - * particular file as subject to the "Classpath" exception as provided
   80.24 - * by Oracle in the GPL Version 2 section of the License file that
   80.25 - * accompanied this code. If applicable, add the following below the
   80.26 - * License Header, with the fields enclosed by brackets [] replaced by
   80.27 - * your own identifying information:
   80.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   80.29 - *
   80.30 - * Contributor(s):
   80.31 - *
   80.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   80.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   80.34 - * Microsystems, Inc. All Rights Reserved.
   80.35 - *
   80.36 - * If you wish your version of this file to be governed by only the CDDL
   80.37 - * or only the GPL Version 2, indicate your decision by adding
   80.38 - * "[Contributor] elects to include this software in this distribution
   80.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   80.40 - * single choice of license, a recipient has the option to distribute
   80.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   80.42 - * to extend the choice of license to its licensees as provided above.
   80.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   80.44 - * Version 2 license, then the option applies only if the new code is
   80.45 - * made subject to such option by the copyright holder.
   80.46 - */
   80.47 -package org.netbeans.modules.python.editor.lexer;
   80.48 -
   80.49 -import java.util.Collection;
   80.50 -import java.util.EnumSet;
   80.51 -import java.util.HashMap;
   80.52 -import java.util.Map;
   80.53 -import org.netbeans.api.lexer.InputAttributes;
   80.54 -import org.netbeans.api.lexer.Language;
   80.55 -import org.netbeans.api.lexer.LanguagePath;
   80.56 -import org.netbeans.api.lexer.Token;
   80.57 -import org.netbeans.api.lexer.TokenId;
   80.58 -import org.netbeans.modules.python.api.PythonMIMEResolver;
   80.59 -import org.netbeans.modules.python.editor.PythonUtils;
   80.60 -import org.netbeans.spi.lexer.LanguageEmbedding;
   80.61 -import org.netbeans.spi.lexer.LanguageHierarchy;
   80.62 -import org.netbeans.spi.lexer.Lexer;
   80.63 -import org.netbeans.spi.lexer.LexerInput;
   80.64 -import org.netbeans.spi.lexer.LexerRestartInfo;
   80.65 -
   80.66 -import org.netbeans.spi.lexer.TokenFactory;
   80.67 -import org.openide.filesystems.FileObject;
   80.68 -import static org.netbeans.modules.python.editor.lexer.PythonLexer.*;
   80.69 -
   80.70 -/**
   80.71 - * @todo add the rest of the tokens
   80.72 - *
   80.73 - * @author Martin Adamek
   80.74 - * @author alley
   80.75 - */
   80.76 -public enum PythonTokenId implements TokenId {
   80.77 -    ERROR(null, ERROR_CAT),
   80.78 -    IDENTIFIER(null, IDENTIFIER_CAT),
   80.79 -    INT_LITERAL(null, NUMBER_CAT),
   80.80 -    FLOAT_LITERAL(null, NUMBER_CAT),
   80.81 -    STRING_LITERAL(null, STRING_CAT),
   80.82 -    WHITESPACE(null, WHITESPACE_CAT),
   80.83 -    NEWLINE(null, WHITESPACE_CAT),
   80.84 -    DECORATOR(null, OPERATOR_CAT), // NOI18N
   80.85 -    //    CONTINUED_LINE(null, WHITESPACE_CAT), // NOI18N
   80.86 -    COMMENT(null, COMMENT_CAT),
   80.87 -    STD_SYMBOLS(null, KEYWORD_CAT), // NOI18N
   80.88 -    LPAREN("(", SEPARATOR_CAT), // NOI18N
   80.89 -    RPAREN(")", SEPARATOR_CAT), // NOI18N
   80.90 -    LBRACE("{", SEPARATOR_CAT), // NOI18N
   80.91 -    RBRACE("}", SEPARATOR_CAT), // NOI18N
   80.92 -    LBRACKET("[", SEPARATOR_CAT), // NOI18N
   80.93 -    RBRACKET("]", SEPARATOR_CAT), // NOI18N
   80.94 -    STRING_BEGIN(null, STRING_CAT),
   80.95 -    STRING_END(null, STRING_CAT),
   80.96 -    // Cheating: out of laziness just map all keywords returning from Jython
   80.97 -    // into a single KEYWORD token; eventually we will have separate tokens
   80.98 -    // for each here such that the various helper methods for formatting,
   80.99 -    // smart indent, brace matching etc. can refer to specific keywords
  80.100 -    ANY_KEYWORD(null, KEYWORD_CAT),
  80.101 -    ANY_OPERATOR(null, OPERATOR_CAT),
  80.102 -    DEF("def", KEYWORD_CAT), // NOI18N
  80.103 -    CLASS("class", KEYWORD_CAT), // NOI18N
  80.104 -    IF("if", KEYWORD_CAT), // NOI18N
  80.105 -    ELSE("else", KEYWORD_CAT), // NOI18N
  80.106 -    ELIF("elif", KEYWORD_CAT), // NOI18N
  80.107 -    RAISE("raise", KEYWORD_CAT), // NOI18N
  80.108 -    PASS("pass", KEYWORD_CAT), // NOI18N
  80.109 -    RETURN("return", KEYWORD_CAT), // NOI18N
  80.110 -    EXCEPT("except", KEYWORD_CAT), // NOI18N
  80.111 -    FINALLY("finally", KEYWORD_CAT), // NOI18N
  80.112 -    IMPORT("import", KEYWORD_CAT), // NOI18N
  80.113 -    FROM("from", KEYWORD_CAT), // NOI18N
  80.114 -    TRUE("True", KEYWORD_CAT), // NOI18N
  80.115 -    FALSE("False", KEYWORD_CAT), // NOI18N
  80.116 -    NONE("None", KEYWORD_CAT), // NOI18N
  80.117 -    TRY("try", KEYWORD_CAT), // NOI18N
  80.118 -    DOT(".", OPERATOR_CAT), // NOI18N
  80.119 -    COMMA(",", OPERATOR_CAT), // NOI18N
  80.120 -    COLON(":", OPERATOR_CAT), // NOI18N
  80.121 -    ESC("\\", OPERATOR_CAT), // NOI18N
  80.122 -
  80.123 -    // Non-unary operators which indicate a line continuation if used at the end of a line
  80.124 -    NONUNARY_OP(null, OPERATOR_CAT);
  80.125 -    private final String fixedText;
  80.126 -    private final String primaryCategory;
  80.127 -
  80.128 -    PythonTokenId(String fixedText, String primaryCategory) {
  80.129 -        this.fixedText = fixedText;
  80.130 -        this.primaryCategory = primaryCategory;
  80.131 -    }
  80.132 -
  80.133 -    @Override
  80.134 -    public String primaryCategory() {
  80.135 -        return primaryCategory;
  80.136 -    }
  80.137 -
  80.138 -    public String fixedText() {
  80.139 -        return fixedText;
  80.140 -    }
  80.141 -    private static final Language<PythonTokenId> language =
  80.142 -            new LanguageHierarchy<PythonTokenId>() {
  80.143 -                @Override
  80.144 -                protected String mimeType() {
  80.145 -                    return PythonMIMEResolver.PYTHON_MIME_TYPE;
  80.146 -                }
  80.147 -
  80.148 -                @Override
  80.149 -                protected Collection<PythonTokenId> createTokenIds() {
  80.150 -                    return EnumSet.allOf(PythonTokenId.class);
  80.151 -                }
  80.152 -
  80.153 -                @Override
  80.154 -                protected Map<String, Collection<PythonTokenId>> createTokenCategories() {
  80.155 -                    Map<String, Collection<PythonTokenId>> cats =
  80.156 -                            new HashMap<>();
  80.157 -                    return cats;
  80.158 -                }
  80.159 -
  80.160 -                @Override
  80.161 -                protected Lexer<PythonTokenId> createLexer(LexerRestartInfo<PythonTokenId> info) {
  80.162 -                    FileObject fileObject = (FileObject)info.getAttributeValue(FileObject.class);
  80.163 -                    final TokenFactory<PythonTokenId> tokenFactory = info.tokenFactory();
  80.164 -                    final LexerInput input = info.input();
  80.165 -                    // Lex .rst files just as literal strings
  80.166 -                    if (fileObject != null && PythonUtils.isRstFile(fileObject)) {
  80.167 -                        return new Lexer<PythonTokenId>() {
  80.168 -                            @Override
  80.169 -                            public Token<PythonTokenId> nextToken() {
  80.170 -                                if (input.read() == LexerInput.EOF) {
  80.171 -                                    return null;
  80.172 -                                }
  80.173 -                                while (input.read() != LexerInput.EOF) {
  80.174 -                                    ;
  80.175 -                                }
  80.176 -                                return tokenFactory.createToken(PythonTokenId.STRING_LITERAL, input.readLength());
  80.177 -                            }
  80.178 -
  80.179 -                            @Override
  80.180 -                            public Object state() {
  80.181 -                                return null;
  80.182 -                            }
  80.183 -
  80.184 -                            @Override
  80.185 -                            public void release() {
  80.186 -                            }
  80.187 -                        };
  80.188 -                    }
  80.189 -                    return new PythonLexer(info);
  80.190 -                }
  80.191 -
  80.192 -                @Override
  80.193 -                protected LanguageEmbedding<?> embedding(Token<PythonTokenId> token,
  80.194 -                        LanguagePath languagePath, InputAttributes inputAttributes) {
  80.195 -                    PythonTokenId id = token.id();
  80.196 -                    if (id == STRING_LITERAL) {
  80.197 -                        return LanguageEmbedding.create(PythonStringTokenId.language, 0, 0);
  80.198 -                    } else if (id == COMMENT) {
  80.199 -                        return LanguageEmbedding.create(PythonCommentTokenId.language(), 1, 0);
  80.200 -                    }
  80.201 -
  80.202 -                    return null; // No embedding
  80.203 -                }
  80.204 -            }.language();
  80.205 -
  80.206 -    public static Language<PythonTokenId> language() {
  80.207 -        return language;
  80.208 -    }
  80.209 -}
    81.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/Bundle.properties	Sat Sep 12 23:03:15 2015 -0700
    81.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.3 @@ -1,284 +0,0 @@
    81.4 -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    81.5 -#
    81.6 -# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    81.7 -#
    81.8 -# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    81.9 -# Other names may be trademarks of their respective owners.
   81.10 -#
   81.11 -# The contents of this file are subject to the terms of either the GNU
   81.12 -# General Public License Version 2 only ("GPL") or the Common
   81.13 -# Development and Distribution License("CDDL") (collectively, the
   81.14 -# "License"). You may not use this file except in compliance with the
   81.15 -# License. You can obtain a copy of the License at
   81.16 -# http://www.netbeans.org/cddl-gplv2.html
   81.17 -# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   81.18 -# specific language governing permissions and limitations under the
   81.19 -# License.  When distributing the software, include this License Header
   81.20 -# Notice in each file and include the License file at
   81.21 -# nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   81.22 -# particular file as subject to the "Classpath" exception as provided
   81.23 -# by Oracle in the GPL Version 2 section of the License file that
   81.24 -# accompanied this code. If applicable, add the following below the
   81.25 -# License Header, with the fields enclosed by brackets [] replaced by
   81.26 -# your own identifying information:
   81.27 -# "Portions Copyrighted [year] [name of copyright owner]"
   81.28 -#
   81.29 -# Contributor(s):
   81.30 -#
   81.31 -# The Original Software is NetBeans. The Initial Developer of the Original
   81.32 -# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   81.33 -# Microsystems, Inc. All Rights Reserved.
   81.34 -#
   81.35 -# If you wish your version of this file to be governed by only the CDDL
   81.36 -# or only the GPL Version 2, indicate your decision by adding
   81.37 -# "[Contributor] elects to include this software in this distribution
   81.38 -# under the [CDDL or GPL Version 2] license." If you do not indicate a
   81.39 -# single choice of license, a recipient has the option to distribute
   81.40 -# your version of this file under either the CDDL, the GPL Version 2 or
   81.41 -# to extend the choice of license to its licensees as provided above.
   81.42 -# However, if you add GPL Version 2 code and therefore, elected the GPL
   81.43 -# Version 2 license, then the option applies only if the new code is
   81.44 -# made subject to such option by the copyright holder.
   81.45 -
   81.46 -# Formating options
   81.47 -
   81.48 -LBL_TabsAndIndents=Tabs and Indents
   81.49 -LBL_CodeGeneration=Code Generation
   81.50 -LBL_Alignment=Alignment
   81.51 -LBL_Wrapping=Wrapping
   81.52 -LBL_BlankLines=Blank Lines
   81.53 -LBL_Spaces=Spaces
   81.54 -LBL_Imports=Imports
   81.55 -
   81.56 -LBL_bp_SAME_LINE=Same Line
   81.57 -LBL_bp_NEW_LINE=New Line
   81.58 -LBL_bp_NEW_LINE_HALF_INDENTED=New Line Half Indented
   81.59 -LBL_bp_NEW_LINE_INDENTED= New Line Indented
   81.60 -    
   81.61 -LBL_bg_GENERATE=Generate
   81.62 -LBL_bg_LEAVE_ALONE=Leave Alone
   81.63 -LBL_bg_ELIMINATE=Eliminate
   81.64 -       
   81.65 -LBL_wrp_WRAP_ALWAYS=Always
   81.66 -LBL_wrp_WRAP_IF_LONG=If Long
   81.67 -LBL_wrp_WRAP_NEVER=Never
   81.68 -
   81.69 -LBL_imp_COMMENT_OUT=Comment Out
   81.70 -LBL_imp_LEAVE_ALONE=Leave Alone
   81.71 -LBL_imp_DELETE=Delete
   81.72 -
   81.73 -LBL_ExpandTabToSpaces=&Expand Tab to Spaces
   81.74 -LBL_TabSize=&Tab Size:
   81.75 -LBL_IndentSize=&Indentation Size:
   81.76 -LBL_ContinuationIndentSize=&Continuation Indentation Size:
   81.77 -LBL_LabelIndent=&Label Indentation\:
   81.78 -LBL_AbsoluteLabelIndent=&Absolute Label Indentation
   81.79 -LBL_IndentTopLevelClassMemberts=Indent Top Level Class &Members
   81.80 -LBL_AddLeadingStarInComment=Add Leading Star In Comment
   81.81 -LBL_RightMargin=&Right Margin:
   81.82 -
   81.83 -LBL_Naming=Naming\:
   81.84 -LBL_PreferLongerNames=Prefer Longer Names
   81.85 -LBL_Prefix=Prefix
   81.86 -LBL_Suffix=Suffix
   81.87 -LBL_Field=Field\:
   81.88 -LBL_StaticField=Static Field\:
   81.89 -LBL_Parameter=Parameter\:
   81.90 -LBL_LocalVariable=Local Variable\:
   81.91 -LBL_Misc=Misc\:
   81.92 -LBL_QualifyFieldAccess=Qualify Field Access
   81.93 -LBL_UseIsForBooleanGetters=Use Is For Boolean Getters
   81.94 -LBL_AddOverrideAnnotation=Add Override Annotation
   81.95 -LBL_FinalMofier=Final Modifier\:
   81.96 -LBL_ParametersFinal=Make Generated Parameters Final
   81.97 -LBL_LocalVariablesFinal=Make Generated Local variables Final
   81.98 -LBL_ImportOredering=Import Ordering\:
   81.99 -LBL_ImportUp=Move Up
  81.100 -LBL_ImportDown=Move Down
  81.101 -LBL_blBeforePackage=Before &Package\:
  81.102 -LBL_blAfterPackage=After P&ackage\:
  81.103 -LBL_blBeforeImports=Before &Imports\:
  81.104 -LBL_blAfterImports=After I&mports\:
  81.105 -LBL_blBeforeClass=Before &Class\:
  81.106 -LBL_blAfterClass=After C&lass\:
  81.107 -LBL_blAfterClassHeader=After Class &Header\:
  81.108 -LBL_blBeforeFields=Before &Field\:
  81.109 -LBL_blAfterFields=After Fi&eld\:
  81.110 -LBL_blBeforeMethods=Before &Method\:
  81.111 -LBL_blAfterMethods=After Me&thod\:
  81.112 -
  81.113 -LBL_BeforeKeywords=Before Keywords
  81.114 -LBL_spaceBeforeWhile="while"
  81.115 -LBL_spaceBeforeElse="else"
  81.116 -LBL_spaceBeforeCatch="catch"
  81.117 -LBL_spaceBeforeFinally="finally"
  81.118 -
  81.119 -LBL_BeforeParentheses=Before Parentheses
  81.120 -LBL_spaceBeforeMethodDeclParen=Method Declaration
  81.121 -LBL_spaceBeforeMethodCallParen=Method Call
  81.122 -LBL_spaceBeforeIfParen="if"
  81.123 -LBL_spaceBeforeForParen="for"
  81.124 -LBL_spaceBeforeWhileParen="while"
  81.125 -LBL_spaceBeforeCatchParen="catch"
  81.126 -LBL_spaceBeforeSwitchParen="switch"
  81.127 -LBL_spaceBeforeSynchronizedParen="synchronized"
  81.128 -LBL_spaceBeforeAnnotationParen=Annotation Parameters
  81.129 -
  81.130 -LBL_AroundOperators=Around Operators
  81.131 -LBL_spaceAroundUnaryOps=Unary Operators
  81.132 -LBL_spaceAroundBinaryOps=Binary Operators
  81.133 -LBL_spaceAroundTernaryOps=Ternary Operators
  81.134 -LBL_spaceAroundAssignOps=Assignment Operators
  81.135 -
  81.136 -LBL_BeforeLeftBraces=Before Left Braces
  81.137 -LBL_spaceBeforeClassDeclLeftBrace=Class Declaration
  81.138 -LBL_spaceBeforeMethodDeclLeftBrace=Method Declaration
  81.139 -LBL_spaceBeforeIfLeftBrace="if"
  81.140 -LBL_spaceBeforeElseLeftBrace="else"
  81.141 -LBL_spaceBeforeWhileLeftBrace="while"
  81.142 -LBL_spaceBeforeForLeftBrace="for"
  81.143 -LBL_spaceBeforeDoLeftBrace="do"
  81.144 -LBL_spaceBeforeSwitchLeftBrace="switch"
  81.145 -LBL_spaceBeforeTryLeftBrace="try"
  81.146 -LBL_spaceBeforeCatchLeftBrace="catch"
  81.147 -LBL_spaceBeforeFinallyLeftBrace="finally"
  81.148 -LBL_spaceBeforeSynchronizedLeftBrace="synchronized"
  81.149 -LBL_spaceBeforeStaticInitLeftBrace=Static Initializer
  81.150 -LBL_spaceBeforeArrayInitLeftBrace=Array Initializer
  81.151 -
  81.152 -LBL_WithinParentheses=Within Parentheses
  81.153 -LBL_spaceWithinParens=Parentheses
  81.154 -LBL_spaceWithinMethodDeclParens=Method Declaration
  81.155 -LBL_spaceWithinMethodCallParens=Method Call
  81.156 -LBL_spaceWithinIfParens="if"
  81.157 -LBL_spaceWithinForParens="for"
  81.158 -LBL_spaceWithinWhileParens="while"
  81.159 -LBL_spaceWithinSwitchParens="switch"
  81.160 -LBL_spaceWithinCatchParens="catch"
  81.161 -LBL_spaceWithinSynchronizedParens="synchronized"
  81.162 -LBL_spaceWithinTypeCastParens=Type Cast
  81.163 -LBL_spaceWithinAnnotationParens=Annotation
  81.164 -LBL_spaceWithinBraces=Braces
  81.165 -LBL_spaceWithinArrayInitBrackets=Array Initializer Brackets
  81.166 -
  81.167 -LBL_Other=Other
  81.168 -LBL_spaceBeforeComma=Before Comma
  81.169 -LBL_spaceAfterComma=After Comma
  81.170 -LBL_spaceBeforeSemi=Before Semicolon
  81.171 -LBL_spaceAfterSemi=After Semicolon
  81.172 -LBL_spaceBeforeColon=Before Colon
  81.173 -LBL_spaceAfterColon=After Colon
  81.174 -LBL_spaceAfterTypeCast=After Type Cast
  81.175 -LBL_wrp_extendsImplementsKeyword=&Extends/Implements Keyword\: 
  81.176 -LBL_wrp_extendsImplementsList=E&xtends/Implements List\:
  81.177 -LBL_wrp_methodParameters=Method &Parameters\:
  81.178 -LBL_wrp_throwsKeyword=&Throws Keyword\:
  81.179 -LBL_wrp_throwsList=Th&rows List\:
  81.180 -LBL_wrp_methodCallArgs=Method Call &Arguments\:
  81.181 -LBL_wrp_annotationArgs=Annotation Arg&uments\:
  81.182 -LBL_wrp_chainedMethodCalls=C&hained Method Calls\:
  81.183 -LBL_wrp_arrayInit=Array Initiali&zer\:
  81.184 -LBL_wrp_for=&For\:
  81.185 -LBL_wrp_forStatement=F&or Statement\:
  81.186 -LBL_wrp_ifStatement=&If Statement\:
  81.187 -LBL_wrp_whileStatement=&While Statement\:
  81.188 -LBL_wrp_doWhileStatement=&Do ... While Statement
  81.189 -LBL_wrp_assert=&Assert\:
  81.190 -LBL_wrp_enumConstants=Enum &Constants\:
  81.191 -LBL_wrp_annotations=A&nnotations\:
  81.192 -LBL_wrp_binaryOps=&Binary Operators\:
  81.193 -LBL_wrp_ternaryOps=Ternar&y Operators\:
  81.194 -LBL_wrp_assignOps=Assi&gnment Operators\:
  81.195 -
  81.196 -LBL_br_bracesPlacement=Braces Placement
  81.197 -LBL_br_bracesGeneration=Braces Generation
  81.198 -LBL_al_newLines=New Lines
  81.199 -LBL_al_multilineAlignment=Multiline Alignment
  81.200 -LBL_nl_Else="&else"
  81.201 -LBL_nl_While="w&hile"
  81.202 -LBL_nl_Catch="c&atch"
  81.203 -LBL_nl_Finally="finall&y"
  81.204 -LBL_nl_Modifiers=after modifie&rs
  81.205 -LBL_am_MethodParams=Method &Parameters
  81.206 -LBL_am_CallArgs=Method Call Arg&uments
  81.207 -LBL_am_AnnotationArgs=&Annotation Arguments
  81.208 -LBL_an_Implements=I&mplements List
  81.209 -LBL_am_Throws=&Throws List
  81.210 -LBL_am_Paren=Parenthesize&d
  81.211 -LBL_am_BinaryOp=&Binary Operators
  81.212 -LBL_am_TernaryOp=Ter&nary Operators
  81.213 -LBL_am_Assign=Assi&gnment
  81.214 -LBL_am_For=&For
  81.215 -LBL_am_ArrayInit=Array Initiali&zer
  81.216 -
  81.217 -LBL_IndentCasesFromSwitch=Indent Case Statements In &Switch
  81.218 -
  81.219 -# Following entries (marked) as samples are used as examples in the formating
  81.220 -# options. It is highly discourage to localize them unless absolutely necessary.
  81.221 -
  81.222 -SAMPLE_Default=public class ClassA extends Object implements InterfaceA, InterfaceB, InterfaceC
  81.223 -SAMPLE_TabsIndents=public class ClassA extends Object implements InterfaceA, InterfaceB, InterfaceC {
  81.224 -SAMPLE_AlignBraces=@Anno(paramA="a Value", paramB="bValue")\n
  81.225 -SAMPLE_Wrapping=@Anno(paramA="a Value", paramB="bValue")
  81.226 -SAMPLE_BlankLines=package org.netbeans.samples;
  81.227 -
  81.228 -SAMPLE_Imports=\
  81.229 -# Copyright 2008\n\
  81.230 -"""My Module"""\n\
  81.231 -\n\
  81.232 -import sys\n\
  81.233 -import wsgiref.handlers\n\
  81.234 -from google.appengine.ext.webapp.util import run_wsgi_app\n\
  81.235 -from google.appengine.ext import webapp\n\
  81.236 -from google.appengine.ext import db\n\
  81.237 -import os\n\
  81.238 -\n\
  81.239 -\n\
  81.240 -from google.appengine.api import users\n\
  81.241 -import google.appengine.api.test\n\
  81.242 -from google.appengine.api import users\n\
  81.243 -\n\
  81.244 -from google.appengine.api import users\n\
  81.245 -from google.appengine.api import users\n\
  81.246 -import string\n\
  81.247 -from google.appengine.ext.webapp import template as FooBar\n\
  81.248 -from google.appengine.ext.webapp.util import login_required\n\
  81.249 -import random\n\
  81.250 -import datetime\n
  81.251 -
  81.252 -#\n\
  81.253 -#new_str = swapcase("foo")
  81.254 -
  81.255 -
  81.256 -# Newlines on the following line since space prefixes are ignored by the .properties loader
  81.257 -SAMPLE_Spaces=\
  81.258 -def func( arg1 ,arg2 ,\
  81.259 -\n  arg3 = 3,  arg  =  4):\
  81.260 -\n\
  81.261 -\n  if pos!=-1 and optval[ pos-1 ].isspace():\
  81.262 -\n      x=5+2\
  81.263 -\n\
  81.264 -\nmodeDict = { 'r':'rb','w':'wb', \\\
  81.265 -\n   'a' : 'r+b' }\
  81.266 -\nx = 2; y=3 ; z    =      5\n
  81.267 -
  81.268 -
  81.269 -nlFinallyCheckBox1.text="finall&y"
  81.270 -
  81.271 -
  81.272 -AN_Preview=Preview
  81.273 -AD_Preview=Preview
  81.274 -FmtImports.formatImportsCb.text=Organize Imports during formatting
  81.275 -FmtImports.removeDuplicateCb.text=Remove Duplicate Imports
  81.276 -FmtImports.systemLibsCb.text=Separate out system libraries
  81.277 -FmtImports.onePerLineCb.text=Prefer one import per line
  81.278 -FmtImports.cleanupLabel.text=Unused imports:
  81.279 -FmtImports.preferSymbols.text=Prefer symbol imports
  81.280 -FmtImports.sortImportsCb.text=Sort Alphabetically
  81.281 -FmtSpaces.addAroundOp.text=Add spaces around operators
  81.282 -FmtSpaces.removeInParam.text=But remove in parameter assignments
  81.283 -FmtSpaces.removeInParen.text=Remove spaces inside ( ), { }, and [ ]
  81.284 -FmtSpaces.addAfterComma.text=Add spaces after commas
  81.285 -FmtSpaces.removeBeforeSep.text=Remove spaces before separators ( : , ; )
  81.286 -FmtSpaces.collapseSpacesCb.text=Collapse multiple spaces
  81.287 -FmtImports.sepFromImpCb.text=Separate "from" and "import" statements
    82.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/CodeStyle.java	Sat Sep 12 23:03:15 2015 -0700
    82.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.3 @@ -1,737 +0,0 @@
    82.4 -/*
    82.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    82.6 - *
    82.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    82.8 - *
    82.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   82.10 - * Other names may be trademarks of their respective owners.
   82.11 - *
   82.12 - * The contents of this file are subject to the terms of either the GNU
   82.13 - * General Public License Version 2 only ("GPL") or the Common
   82.14 - * Development and Distribution License("CDDL") (collectively, the
   82.15 - * "License"). You may not use this file except in compliance with the
   82.16 - * License. You can obtain a copy of the License at
   82.17 - * http://www.netbeans.org/cddl-gplv2.html
   82.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   82.19 - * specific language governing permissions and limitations under the
   82.20 - * License.  When distributing the software, include this License Header
   82.21 - * Notice in each file and include the License file at
   82.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   82.23 - * particular file as subject to the "Classpath" exception as provided
   82.24 - * by Oracle in the GPL Version 2 section of the License file that
   82.25 - * accompanied this code. If applicable, add the following below the
   82.26 - * License Header, with the fields enclosed by brackets [] replaced by
   82.27 - * your own identifying information:
   82.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   82.29 - *
   82.30 - * Contributor(s):
   82.31 - *
   82.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   82.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   82.34 - * Microsystems, Inc. All Rights Reserved.
   82.35 - *
   82.36 - * If you wish your version of this file to be governed by only the CDDL
   82.37 - * or only the GPL Version 2, indicate your decision by adding
   82.38 - * "[Contributor] elects to include this software in this distribution
   82.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   82.40 - * single choice of license, a recipient has the option to distribute
   82.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   82.42 - * to extend the choice of license to its licensees as provided above.
   82.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   82.44 - * Version 2 license, then the option applies only if the new code is
   82.45 - * made subject to such option by the copyright holder.
   82.46 - */
   82.47 -package org.netbeans.modules.python.editor.options;
   82.48 -
   82.49 -import java.util.prefs.Preferences;
   82.50 -import javax.swing.text.Document;
   82.51 -import org.netbeans.modules.editor.indent.spi.CodeStylePreferences;
   82.52 -
   82.53 -import org.openide.filesystems.FileObject;
   82.54 -import static org.netbeans.modules.python.editor.options.FmtOptions.*;
   82.55 -
   82.56 -/** 
   82.57 - *  XXX make sure the getters get the defaults from somewhere
   82.58 - *  XXX add support for profiles
   82.59 - *  XXX get the preferences node from somewhere else in odrer to be able not to
   82.60 - *      use the getters and to be able to write to it.
   82.61 - * 
   82.62 - * @author Dusan Balek
   82.63 - */
   82.64 -public final class CodeStyle {
   82.65 -    static {
   82.66 -        FmtOptions.codeStyleProducer = new Producer();
   82.67 -    }
   82.68 -    private Preferences preferences;
   82.69 -
   82.70 -    private CodeStyle(Preferences preferences) {
   82.71 -        this.preferences = preferences;
   82.72 -    }
   82.73 -
   82.74 -//    /**
   82.75 -//     * Gets <code>CodeStyle</code> for files in the given project.
   82.76 -//     *
   82.77 -//     * <p>Please see the other two <code>getDefault</code> methods as they are
   82.78 -//     * the preferred way of getting <code>CodeStyle</code>.
   82.79 -//     *
   82.80 -//     * @param project The project to get the <code>CodeStyle</code> for.
   82.81 -//     * @return The current code style that would be used by documents opened
   82.82 -//     *   from files belonging to the <code>project</code>.
   82.83 -//     *
   82.84 -//     * @deprecated Please use {@link #getDefault(javax.swing.text.Document)}
   82.85 -//     *   or {@link #getDefault(org.openide.filesystems.FileObject)} respectively.
   82.86 -//     */
   82.87 -//    @Deprecated
   82.88 -//    public static CodeStyle getDefault(Project project) {
   82.89 -//        return getDefault(project.getProjectDirectory());
   82.90 -//    }
   82.91 -    /**
   82.92 -     * Gets <code>CodeStyle</code> for the given file. If you have a document
   82.93 -     * instance you should use the {@link #getDefault(javax.swing.text.Document)}
   82.94 -     * method.
   82.95 -     * 
   82.96 -     * @param file The file to get the <code>CodeStyle</code> for.
   82.97 -     * @return The current code style that would be used by a document if the
   82.98 -     *   <code>file</code> were opened in the editor.
   82.99 -     *
  82.100 -     * @since 0.39
  82.101 -     */
  82.102 -    public synchronized static CodeStyle getDefault(FileObject file) {
  82.103 -        Preferences prefs = CodeStylePreferences.get(file).getPreferences();
  82.104 -        return FmtOptions.codeStyleProducer.create(prefs);
  82.105 -    }
  82.106 -
  82.107 -    /**
  82.108 -     * Gets <code>CodeStyle</code> for the given document. This is the preferred
  82.109 -     * method of getting <code>CodeStyle</code>. If you don't have a document
  82.110 -     * you can use {@link #getDefault(org.openide.filesystems.FileObject)} method instead.
  82.111 -     *
  82.112 -     * @param doc The document to get the <code>CodeStyle</code> for.
  82.113 -     * @return The current code style used by a document. This is the code style that
  82.114 -     *   will be used when formatting the document or generating new code.
  82.115 -     * 
  82.116 -     * @since 0.39
  82.117 -     */
  82.118 -    public synchronized static CodeStyle getDefault(Document doc) {
  82.119 -        Preferences prefs = CodeStylePreferences.get(doc).getPreferences();
  82.120 -        return FmtOptions.codeStyleProducer.create(prefs);
  82.121 -    }
  82.122 -
  82.123 -    // General tabs and indents ------------------------------------------------
  82.124 -    public boolean expandTabToSpaces() {
  82.125 -//        System.out.println("~~~ expand-tabs=" + preferences.get(SimpleValueNames.EXPAND_TABS, null));
  82.126 -        return preferences.getBoolean(expandTabToSpaces, getDefaultAsBoolean(expandTabToSpaces));
  82.127 -    }
  82.128 -
  82.129 -    public int getTabSize() {
  82.130 -//        System.out.println("~~~ tab-size=" + preferences.get(SimpleValueNames.TAB_SIZE, null));
  82.131 -        return preferences.getInt(tabSize, getDefaultAsInt(tabSize));
  82.132 -    }
  82.133 -
  82.134 -    public int getIndentSize() {
  82.135 -//        System.out.println("~~~ indent-shift-width=" + preferences.get(SimpleValueNames.INDENT_SHIFT_WIDTH, null));
  82.136 -        int indentLevel = preferences.getInt(indentSize, getDefaultAsInt(indentSize));
  82.137 -
  82.138 -        if (indentLevel <= 0) {
  82.139 -//            System.out.println("~~~ expand-tabs=" + preferences.get(SimpleValueNames.EXPAND_TABS, null));
  82.140 -            boolean expandTabs = preferences.getBoolean(expandTabToSpaces, getDefaultAsBoolean(expandTabToSpaces));
  82.141 -            if (expandTabs) {
  82.142 -//                System.out.println("~~~ spaces-per-tab=" + preferences.get(SimpleValueNames.SPACES_PER_TAB, null));
  82.143 -                indentLevel = preferences.getInt(spacesPerTab, getDefaultAsInt(spacesPerTab));
  82.144 -            } else {
  82.145 -//                System.out.println("~~~ tab-size=" + preferences.get(SimpleValueNames.TAB_SIZE, null));
  82.146 -                indentLevel = preferences.getInt(tabSize, getDefaultAsInt(tabSize));
  82.147 -            }
  82.148 -        }
  82.149 -
  82.150 -        return indentLevel;
  82.151 -    }
  82.152 -
  82.153 -    public int getContinuationIndentSize() {
  82.154 -        return preferences.getInt(continuationIndentSize, getDefaultAsInt(continuationIndentSize));
  82.155 -    }
  82.156 -
  82.157 -    public int getLabelIndent() {
  82.158 -        return preferences.getInt(labelIndent, getDefaultAsInt(labelIndent));
  82.159 -    }
  82.160 -
  82.161 -    public boolean absoluteLabelIndent() {
  82.162 -        return preferences.getBoolean(absoluteLabelIndent, getDefaultAsBoolean(absoluteLabelIndent));
  82.163 -    }
  82.164 -
  82.165 -    public boolean indentTopLevelClassMembers() {
  82.166 -        return preferences.getBoolean(indentTopLevelClassMembers, getDefaultAsBoolean(indentTopLevelClassMembers));
  82.167 -    }
  82.168 -
  82.169 -    public boolean indentCasesFromSwitch() {
  82.170 -        return preferences.getBoolean(indentCasesFromSwitch, getDefaultAsBoolean(indentCasesFromSwitch));
  82.171 -    }
  82.172 -
  82.173 -    public int getRightMargin() {
  82.174 -        return preferences.getInt(rightMargin, getDefaultAsInt(rightMargin));
  82.175 -    }
  82.176 -
  82.177 -    /*
  82.178 -    public boolean addLeadingStarInComment() {
  82.179 -    return preferences.getBoolean(addLeadingStarInComment, getDefaultAsBoolean(addLeadingStarInComment));
  82.180 -    }
  82.181 -
  82.182 -    // Code generation ---------------------------------------------------------
  82.183 -    
  82.184 -    public boolean preferLongerNames() {
  82.185 -    return preferences.getBoolean(preferLongerNames, getDefaultAsBoolean(preferLongerNames));
  82.186 -    }
  82.187 -
  82.188 -    public String getFieldNamePrefix() {
  82.189 -    return preferences.get(fieldNamePrefix, getDefaultAsString(fieldNamePrefix));
  82.190 -    }
  82.191 -
  82.192 -    public String getFieldNameSuffix() {
  82.193 -    return preferences.get(fieldNameSuffix, getDefaultAsString(fieldNameSuffix));
  82.194 -    }
  82.195 -
  82.196 -    public String getStaticFieldNamePrefix() {
  82.197 -    return preferences.get(staticFieldNamePrefix, getDefaultAsString(staticFieldNamePrefix));
  82.198 -    }
  82.199 -
  82.200 -    public String getStaticFieldNameSuffix() {
  82.201 -    return preferences.get(staticFieldNameSuffix, getDefaultAsString(staticFieldNameSuffix));
  82.202 -    }
  82.203 -
  82.204 -    public String getParameterNamePrefix() {
  82.205 -    return preferences.get(parameterNamePrefix, getDefaultAsString(parameterNamePrefix));
  82.206 -    }
  82.207 -
  82.208 -    public String getParameterNameSuffix() {
  82.209 -    return preferences.get(parameterNameSuffix, getDefaultAsString(parameterNameSuffix));
  82.210 -    }
  82.211 -
  82.212 -    public String getLocalVarNamePrefix() {
  82.213 -    return preferences.get(localVarNamePrefix, getDefaultAsString(localVarNamePrefix));
  82.214 -    }
  82.215 -
  82.216 -    public String getLocalVarNameSuffix() {
  82.217 -    return preferences.get(localVarNameSuffix, getDefaultAsString(localVarNameSuffix));
  82.218 -    }
  82.219 -
  82.220 -    public boolean qualifyFieldAccess() {
  82.221 -    return preferences.getBoolean(qualifyFieldAccess, getDefaultAsBoolean(qualifyFieldAccess));
  82.222 -    }
  82.223 -
  82.224 -    public boolean useIsForBooleanGetters() {
  82.225 -    return preferences.getBoolean(useIsForBooleanGetters, getDefaultAsBoolean(useIsForBooleanGetters));
  82.226 -    }
  82.227 -
  82.228 -    public boolean addOverrideAnnotation() {
  82.229 -    return preferences.getBoolean(addOverrideAnnotation, getDefaultAsBoolean(addOverrideAnnotation));
  82.230 -    }
  82.231 -
  82.232 -    public boolean makeLocalVarsFinal() {
  82.233 -    return preferences.getBoolean(makeLocalVarsFinal, getDefaultAsBoolean(makeLocalVarsFinal));
  82.234 -    }
  82.235 -
  82.236 -    // Alignment ----------------------------------------------------
  82.237 -    
  82.238 -    public boolean alignMultilineMethodParams() {
  82.239 -    return preferences.getBoolean(alignMultilineMethodParams, getDefaultAsBoolean(alignMultilineMethodParams));
  82.240 -    }
  82.241 -
  82.242 -    public boolean alignMultilineCallArgs() {
  82.243 -    return preferences.getBoolean(alignMultilineCallArgs, getDefaultAsBoolean(alignMultilineCallArgs));
  82.244 -    }
  82.245 -
  82.246 -    public boolean alignMultilineAnnotationArgs() {
  82.247 -    return preferences.getBoolean(alignMultilineAnnotationArgs, getDefaultAsBoolean(alignMultilineAnnotationArgs));
  82.248 -    }
  82.249 -
  82.250 -    public boolean alignMultilineImplements() {
  82.251 -    return preferences.getBoolean(alignMultilineImplements, getDefaultAsBoolean(alignMultilineImplements));
  82.252 -    }
  82.253 -
  82.254 -    public boolean alignMultilineThrows() {
  82.255 -    return preferences.getBoolean(alignMultilineThrows, getDefaultAsBoolean(alignMultilineThrows));
  82.256 -    }
  82.257 -
  82.258 -    public boolean alignMultilineParenthesized() {
  82.259 -    return preferences.getBoolean(alignMultilineParenthesized, getDefaultAsBoolean(alignMultilineParenthesized));
  82.260 -    }
  82.261 -
  82.262 -    public boolean alignMultilineBinaryOp() {
  82.263 -    return preferences.getBoolean(alignMultilineBinaryOp, getDefaultAsBoolean(alignMultilineBinaryOp));
  82.264 -    }
  82.265 -
  82.266 -    public boolean alignMultilineTernaryOp() {
  82.267 -    return preferences.getBoolean(alignMultilineTernaryOp, getDefaultAsBoolean(alignMultilineTernaryOp));
  82.268 -    }
  82.269 -
  82.270 -    public boolean alignMultilineAssignment() {
  82.271 -    return preferences.getBoolean(alignMultilineAssignment, getDefaultAsBoolean(alignMultilineAssignment));
  82.272 -    }
  82.273 -
  82.274 -    public boolean alignMultilineFor() {
  82.275 -    return preferences.getBoolean(alignMultilineFor, getDefaultAsBoolean(alignMultilineFor));
  82.276 -    }
  82.277 -
  82.278 -    public boolean alignMultilineArrayInit() {
  82.279 -    return preferences.getBoolean(alignMultilineArrayInit, getDefaultAsBoolean(alignMultilineArrayInit));
  82.280 -    }
  82.281 -
  82.282 -    public boolean placeElseOnNewLine() {
  82.283 -    return preferences.getBoolean(placeElseOnNewLine, getDefaultAsBoolean(placeElseOnNewLine));
  82.284 -    }
  82.285 -
  82.286 -    public boolean placeWhileOnNewLine() {
  82.287 -    return preferences.getBoolean(placeWhileOnNewLine, getDefaultAsBoolean(placeWhileOnNewLine));
  82.288 -    }
  82.289 -
  82.290 -    public boolean placeCatchOnNewLine() {
  82.291 -    return preferences.getBoolean(placeCatchOnNewLine, getDefaultAsBoolean(placeCatchOnNewLine));
  82.292 -    }
  82.293 -
  82.294 -    public boolean placeFinallyOnNewLine() {
  82.295 -    return preferences.getBoolean(placeFinallyOnNewLine, getDefaultAsBoolean(placeFinallyOnNewLine));
  82.296 -    }
  82.297 -    
  82.298 -    public boolean placeNewLineAfterModifiers() {
  82.299 -    return preferences.getBoolean(placeNewLineAfterModifiers, getDefaultAsBoolean(placeNewLineAfterModifiers));
  82.300 -    }
  82.301 -
  82.302 -    // Wrapping ----------------------------------------------------------------
  82.303 -    
  82.304 -    public WrapStyle wrapExtendsImplementsKeyword() {
  82.305 -    String wrap = preferences.get(wrapExtendsImplementsKeyword, getDefaultAsString(wrapExtendsImplementsKeyword));
  82.306 -    return WrapStyle.valueOf(wrap);
  82.307 -    }
  82.308 -
  82.309 -    public WrapStyle wrapExtendsImplementsList() {
  82.310 -    String wrap = preferences.get(wrapExtendsImplementsList, getDefaultAsString(wrapExtendsImplementsList));
  82.311 -    return WrapStyle.valueOf(wrap);
  82.312 -    }
  82.313 -
  82.314 -    public WrapStyle wrapMethodParams() {
  82.315 -    String wrap = preferences.get(wrapMethodParams, getDefaultAsString(wrapMethodParams));
  82.316 -    return WrapStyle.valueOf(wrap);
  82.317 -    }
  82.318 -
  82.319 -    public WrapStyle wrapThrowsKeyword() {
  82.320 -    String wrap = preferences.get(wrapThrowsKeyword, getDefaultAsString(wrapThrowsKeyword));
  82.321 -    return WrapStyle.valueOf(wrap);
  82.322 -    }
  82.323 -
  82.324 -    public WrapStyle wrapThrowsList() {
  82.325 -    String wrap = preferences.get(wrapThrowsList, getDefaultAsString(wrapThrowsList));
  82.326 -    return WrapStyle.valueOf(wrap);
  82.327 -    }
  82.328 -
  82.329 -    public WrapStyle wrapMethodCallArgs() {
  82.330 -    String wrap = preferences.get(wrapMethodCallArgs, getDefaultAsString(wrapMethodCallArgs));
  82.331 -    return WrapStyle.valueOf(wrap);
  82.332 -    }
  82.333 -
  82.334 -    public WrapStyle wrapAnnotationArgs() {
  82.335 -    String wrap = preferences.get(wrapAnnotationArgs, getDefaultAsString(wrapAnnotationArgs));
  82.336 -    return WrapStyle.valueOf(wrap);
  82.337 -    }
  82.338 -
  82.339 -    public WrapStyle wrapChainedMethodCalls() {
  82.340 -    String wrap = preferences.get(wrapChainedMethodCalls, getDefaultAsString(wrapChainedMethodCalls));
  82.341 -    return WrapStyle.valueOf(wrap);
  82.342 -    }
  82.343 -
  82.344 -    public WrapStyle wrapArrayInit() {
  82.345 -    String wrap = preferences.get(wrapArrayInit, getDefaultAsString(wrapArrayInit));
  82.346 -    return WrapStyle.valueOf(wrap);
  82.347 -    }
  82.348 -
  82.349 -    public WrapStyle wrapFor() {
  82.350 -    String wrap = preferences.get(wrapFor, getDefaultAsString(wrapFor));
  82.351 -    return WrapStyle.valueOf(wrap);
  82.352 -    }
  82.353 -
  82.354 -    public WrapStyle wrapForStatement() {
  82.355 -    String wrap = preferences.get(wrapForStatement, getDefaultAsString(wrapForStatement));
  82.356 -    return WrapStyle.valueOf(wrap);
  82.357 -    }
  82.358 -
  82.359 -    public WrapStyle wrapIfStatement() {
  82.360 -    String wrap = preferences.get(wrapIfStatement, getDefaultAsString(wrapIfStatement));
  82.361 -    return WrapStyle.valueOf(wrap);
  82.362 -    }
  82.363 -
  82.364 -    public WrapStyle wrapWhileStatement() {
  82.365 -    String wrap = preferences.get(wrapWhileStatement, getDefaultAsString(wrapWhileStatement));
  82.366 -    return WrapStyle.valueOf(wrap);
  82.367 -    }
  82.368 -
  82.369 -    public WrapStyle wrapDoWhileStatement() {
  82.370 -    String wrap = preferences.get(wrapDoWhileStatement, getDefaultAsString(wrapDoWhileStatement));
  82.371 -    return WrapStyle.valueOf(wrap);
  82.372 -    }
  82.373 -
  82.374 -    public WrapStyle wrapAssert() {
  82.375 -    String wrap = preferences.get(wrapAssert, getDefaultAsString(wrapAssert));
  82.376 -    return WrapStyle.valueOf(wrap);
  82.377 -    }
  82.378 -
  82.379 -    public WrapStyle wrapEnumConstants() {
  82.380 -    String wrap = preferences.get(wrapEnumConstants, getDefaultAsString(wrapEnumConstants));
  82.381 -    return WrapStyle.valueOf(wrap);
  82.382 -    }
  82.383 -
  82.384 -    public WrapStyle wrapAnnotations() {
  82.385 -    String wrap = preferences.get(wrapAnnotations, getDefaultAsString(wrapAnnotations));
  82.386 -    return WrapStyle.valueOf(wrap);
  82.387 -    }
  82.388 -
  82.389 -    public WrapStyle wrapBinaryOps() {
  82.390 -    String wrap = preferences.get(wrapBinaryOps, getDefaultAsString(wrapBinaryOps));
  82.391 -    return WrapStyle.valueOf(wrap);
  82.392 -    }
  82.393 -
  82.394 -    public WrapStyle wrapTernaryOps() {
  82.395 -    String wrap = preferences.get(wrapTernaryOps, getDefaultAsString(wrapTernaryOps));
  82.396 -    return WrapStyle.valueOf(wrap);
  82.397 -    }
  82.398 -
  82.399 -    public WrapStyle wrapAssignOps() {
  82.400 -    String wrap = preferences.get(wrapAssignOps, getDefaultAsString(wrapAssignOps));
  82.401 -    return WrapStyle.valueOf(wrap);
  82.402 -    }
  82.403 -
  82.404 -    // Blank lines -------------------------------------------------------------
  82.405 -    
  82.406 -    public int getBlankLinesBeforePackage() {
  82.407 -    return preferences.getInt(blankLinesBeforePackage, getDefaultAsInt(blankLinesBeforePackage));
  82.408 -    }
  82.409 -
  82.410 -    public int getBlankLinesAfterPackage() {
  82.411 -    return preferences.getInt(blankLinesAfterPackage, getDefaultAsInt(blankLinesAfterPackage));
  82.412 -    }
  82.413 -
  82.414 -    public int getBlankLinesBeforeImports() {
  82.415 -    return preferences.getInt(blankLinesBeforeImports, getDefaultAsInt(blankLinesBeforeImports));
  82.416 -    }
  82.417 -
  82.418 -    public int getBlankLinesAfterImports() {
  82.419 -    return preferences.getInt(blankLinesAfterImports, getDefaultAsInt(blankLinesAfterImports));
  82.420 -    }
  82.421 -
  82.422 -    public int getBlankLinesBeforeClass() {
  82.423 -    return preferences.getInt(blankLinesBeforeClass, getDefaultAsInt(blankLinesBeforeClass));
  82.424 -    }
  82.425 -
  82.426 -    public int getBlankLinesAfterClass() {
  82.427 -    return preferences.getInt(blankLinesAfterClass, getDefaultAsInt(blankLinesAfterClass));
  82.428 -    }
  82.429 -
  82.430 -    public int getBlankLinesAfterClassHeader() {
  82.431 -    return preferences.getInt(blankLinesAfterClassHeader, getDefaultAsInt(blankLinesAfterClassHeader));
  82.432 -    }
  82.433 -
  82.434 -    public int getBlankLinesBeforeFields() {
  82.435 -    return preferences.getInt(blankLinesBeforeFields, getDefaultAsInt(blankLinesBeforeFields));
  82.436 -    }
  82.437 -
  82.438 -    public int getBlankLinesAfterFields() {
  82.439 -    return preferences.getInt(blankLinesAfterFields, getDefaultAsInt(blankLinesAfterFields));
  82.440 -    }
  82.441 -
  82.442 -    public int getBlankLinesBeforeMethods() {
  82.443 -    return preferences.getInt(blankLinesBeforeMethods, getDefaultAsInt(blankLinesBeforeMethods));
  82.444 -    }
  82.445 -
  82.446 -    public int getBlankLinesAfterMethods() {
  82.447 -    return preferences.getInt(blankLinesAfterMethods, getDefaultAsInt(blankLinesAfterMethods));
  82.448 -    }
  82.449 -
  82.450 -    // Spaces ------------------------------------------------------------------
  82.451 -    
  82.452 -    public boolean spaceBeforeWhile() {
  82.453 -    return preferences.getBoolean(spaceBeforeWhile, getDefaultAsBoolean(spaceBeforeWhile));
  82.454 -    }
  82.455 -
  82.456 -    public boolean spaceBeforeElse() {
  82.457 -    return preferences.getBoolean(spaceBeforeElse, getDefaultAsBoolean(spaceBeforeElse));
  82.458 -    }
  82.459 -
  82.460 -    public boolean spaceBeforeCatch() {
  82.461 -    return preferences.getBoolean(spaceBeforeCatch, getDefaultAsBoolean(spaceBeforeCatch));
  82.462 -    }
  82.463 -
  82.464 -    public boolean spaceBeforeFinally() {
  82.465 -    return preferences.getBoolean(spaceBeforeFinally, getDefaultAsBoolean(spaceBeforeFinally));
  82.466 -    }
  82.467 -
  82.468 -    public boolean spaceBeforeMethodDeclParen() {
  82.469 -    return preferences.getBoolean(spaceBeforeMethodDeclParen, getDefaultAsBoolean(spaceBeforeMethodDeclParen));
  82.470 -    }
  82.471 -
  82.472 -    public boolean spaceBeforeMethodCallParen() {
  82.473 -    return preferences.getBoolean(spaceBeforeMethodCallParen, getDefaultAsBoolean(spaceBeforeMethodCallParen));
  82.474 -    }
  82.475 -
  82.476 -    public boolean spaceBeforeIfParen() {
  82.477 -    return preferences.getBoolean(spaceBeforeIfParen, getDefaultAsBoolean(spaceBeforeIfParen));
  82.478 -    }
  82.479 -
  82.480 -    public boolean spaceBeforeForParen() {
  82.481 -    return preferences.getBoolean(spaceBeforeForParen, getDefaultAsBoolean(spaceBeforeForParen));
  82.482 -    }
  82.483 -
  82.484 -    public boolean spaceBeforeWhileParen() {
  82.485 -    return preferences.getBoolean(spaceBeforeWhileParen, getDefaultAsBoolean(spaceBeforeWhileParen));
  82.486 -    }
  82.487 -
  82.488 -    public boolean spaceBeforeCatchParen() {
  82.489 -    return preferences.getBoolean(spaceBeforeCatchParen, getDefaultAsBoolean(spaceBeforeCatchParen));
  82.490 -    }
  82.491 -
  82.492 -    public boolean spaceBeforeSwitchParen() {
  82.493 -    return preferences.getBoolean(spaceBeforeSwitchParen, getDefaultAsBoolean(spaceBeforeSwitchParen));
  82.494 -    }
  82.495 -
  82.496 -    public boolean spaceBeforeSynchronizedParen() {
  82.497 -    return preferences.getBoolean(spaceBeforeSynchronizedParen, getDefaultAsBoolean(spaceBeforeSynchronizedParen));
  82.498 -    }
  82.499 -
  82.500 -    public boolean spaceBeforeAnnotationParen() {
  82.501 -    return preferences.getBoolean(spaceBeforeAnnotationParen, getDefaultAsBoolean(spaceBeforeAnnotationParen));
  82.502 -    }
  82.503 -
  82.504 -    public boolean spaceAroundUnaryOps() {
  82.505 -    return preferences.getBoolean(spaceAroundUnaryOps, getDefaultAsBoolean(spaceAroundUnaryOps));
  82.506 -    }
  82.507 -
  82.508 -    public boolean spaceAroundBinaryOps() {
  82.509 -    return preferences.getBoolean(spaceAroundBinaryOps, getDefaultAsBoolean(spaceAroundBinaryOps));
  82.510 -    }
  82.511 -
  82.512 -    public boolean spaceAroundTernaryOps() {
  82.513 -    return preferences.getBoolean(spaceAroundTernaryOps, getDefaultAsBoolean(spaceAroundTernaryOps));
  82.514 -    }
  82.515 -
  82.516 -    public boolean spaceAroundAssignOps() {
  82.517 -    return preferences.getBoolean(spaceAroundAssignOps, getDefaultAsBoolean(spaceAroundAssignOps));
  82.518 -    }
  82.519 -
  82.520 -    public boolean spaceBeforeClassDeclLeftBrace() {
  82.521 -    return preferences.getBoolean(spaceBeforeClassDeclLeftBrace, getDefaultAsBoolean(spaceBeforeClassDeclLeftBrace));
  82.522 -    }
  82.523 -
  82.524 -    public boolean spaceBeforeMethodDeclLeftBrace() {
  82.525 -    return preferences.getBoolean(spaceBeforeMethodDeclLeftBrace, getDefaultAsBoolean(spaceBeforeMethodDeclLeftBrace));
  82.526 -    }
  82.527 -
  82.528 -    public boolean spaceBeforeIfLeftBrace() {
  82.529 -    return preferences.getBoolean(spaceBeforeIfLeftBrace, getDefaultAsBoolean(spaceBeforeIfLeftBrace));
  82.530 -    }
  82.531 -
  82.532 -    public boolean spaceBeforeElseLeftBrace() {
  82.533 -    return preferences.getBoolean(spaceBeforeElseLeftBrace, getDefaultAsBoolean(spaceBeforeElseLeftBrace));
  82.534 -    }
  82.535 -
  82.536 -    public boolean spaceBeforeWhileLeftBrace() {
  82.537 -    return preferences.getBoolean(spaceBeforeWhileLeftBrace, getDefaultAsBoolean(spaceBeforeWhileLeftBrace));
  82.538 -    }
  82.539 -
  82.540 -    public boolean spaceBeforeForLeftBrace() {
  82.541 -    return preferences.getBoolean(spaceBeforeForLeftBrace, getDefaultAsBoolean(spaceBeforeForLeftBrace));
  82.542 -    }
  82.543 -
  82.544 -    public boolean spaceBeforeDoLeftBrace() {
  82.545 -    return preferences.getBoolean(spaceBeforeDoLeftBrace, getDefaultAsBoolean(spaceBeforeDoLeftBrace));
  82.546 -    }
  82.547 -
  82.548 -    public boolean spaceBeforeSwitchLeftBrace() {
  82.549 -    return preferences.getBoolean(spaceBeforeSwitchLeftBrace, getDefaultAsBoolean(spaceBeforeSwitchLeftBrace));
  82.550 -    }
  82.551 -
  82.552 -    public boolean spaceBeforeTryLeftBrace() {
  82.553 -    return preferences.getBoolean(spaceBeforeTryLeftBrace, getDefaultAsBoolean(spaceBeforeTryLeftBrace));
  82.554 -    }
  82.555 -
  82.556 -    public boolean spaceBeforeCatchLeftBrace() {
  82.557 -    return preferences.getBoolean(spaceBeforeCatchLeftBrace, getDefaultAsBoolean(spaceBeforeCatchLeftBrace));
  82.558 -    }
  82.559 -
  82.560 -    public boolean spaceBeforeFinallyLeftBrace() {
  82.561 -    return preferences.getBoolean(spaceBeforeFinallyLeftBrace, getDefaultAsBoolean(spaceBeforeFinallyLeftBrace));
  82.562 -    }
  82.563 -
  82.564 -    public boolean spaceBeforeSynchronizedLeftBrace() {
  82.565 -    return preferences.getBoolean(spaceBeforeSynchronizedLeftBrace, getDefaultAsBoolean(spaceBeforeSynchronizedLeftBrace));
  82.566 -    }
  82.567 -
  82.568 -    public boolean spaceBeforeStaticInitLeftBrace() {
  82.569 -    return preferences.getBoolean(spaceBeforeStaticInitLeftBrace, getDefaultAsBoolean(spaceBeforeStaticInitLeftBrace));
  82.570 -    }
  82.571 -
  82.572 -    public boolean spaceBeforeArrayInitLeftBrace() {
  82.573 -    return preferences.getBoolean(spaceBeforeArrayInitLeftBrace, getDefaultAsBoolean(spaceBeforeArrayInitLeftBrace));
  82.574 -    }
  82.575 -
  82.576 -    public boolean spaceWithinParens() {
  82.577 -    return preferences.getBoolean(spaceWithinParens, getDefaultAsBoolean(spaceWithinParens));
  82.578 -    }
  82.579 -
  82.580 -    public boolean spaceWithinMethodDeclParens() {
  82.581 -    return preferences.getBoolean(spaceWithinMethodDeclParens, getDefaultAsBoolean(spaceWithinMethodDeclParens));
  82.582 -    }
  82.583 -
  82.584 -    public boolean spaceWithinMethodCallParens() {
  82.585 -    return preferences.getBoolean(spaceWithinMethodCallParens, getDefaultAsBoolean(spaceWithinMethodCallParens));
  82.586 -    }
  82.587 -
  82.588 -    public boolean spaceWithinIfParens() {
  82.589 -    return preferences.getBoolean(spaceWithinIfParens, getDefaultAsBoolean(spaceWithinIfParens));
  82.590 -    }
  82.591 -
  82.592 -    public boolean spaceWithinForParens() {
  82.593 -    return preferences.getBoolean(spaceWithinForParens, getDefaultAsBoolean(spaceWithinForParens));
  82.594 -    }
  82.595 -
  82.596 -    public boolean spaceWithinWhileParens() {
  82.597 -    return preferences.getBoolean(spaceWithinWhileParens, getDefaultAsBoolean(spaceWithinWhileParens));
  82.598 -    }
  82.599 -
  82.600 -    public boolean spaceWithinSwitchParens() {
  82.601 -    return preferences.getBoolean(spaceWithinSwitchParens, getDefaultAsBoolean(spaceWithinSwitchParens));
  82.602 -    }
  82.603 -
  82.604 -    public boolean spaceWithinCatchParens() {
  82.605 -    return preferences.getBoolean(spaceWithinCatchParens, getDefaultAsBoolean(spaceWithinCatchParens));
  82.606 -    }
  82.607 -
  82.608 -    public boolean spaceWithinSynchronizedParens() {
  82.609 -    return preferences.getBoolean(spaceWithinSynchronizedParens, getDefaultAsBoolean(spaceWithinSynchronizedParens));
  82.610 -    }
  82.611 -
  82.612 -    public boolean spaceWithinTypeCastParens() {
  82.613 -    return preferences.getBoolean(spaceWithinTypeCastParens, getDefaultAsBoolean(spaceWithinTypeCastParens));
  82.614 -    }
  82.615 -
  82.616 -    public boolean spaceWithinAnnotationParens() {
  82.617 -    return preferences.getBoolean(spaceWithinAnnotationParens, getDefaultAsBoolean(spaceWithinAnnotationParens));
  82.618 -    }
  82.619 -
  82.620 -    public boolean spaceWithinBraces() {
  82.621 -    return preferences.getBoolean(spaceWithinBraces, getDefaultAsBoolean(spaceWithinBraces));
  82.622 -    }
  82.623 -
  82.624 -    public boolean spaceWithinArrayInitBrackets() {
  82.625 -    return preferences.getBoolean(spaceWithinArrayInitBrackets, getDefaultAsBoolean(spaceWithinArrayInitBrackets));
  82.626 -    }
  82.627 -
  82.628 -    public boolean spaceBeforeComma() {
  82.629 -    return preferences.getBoolean(spaceBeforeComma, getDefaultAsBoolean(spaceBeforeComma));
  82.630 -    }
  82.631 -
  82.632 -    public boolean spaceAfterComma() {
  82.633 -    return preferences.getBoolean(spaceAfterComma, getDefaultAsBoolean(spaceAfterComma));
  82.634 -    }
  82.635 -
  82.636 -    public boolean spaceBeforeSemi() {
  82.637 -    return preferences.getBoolean(spaceBeforeSemi, getDefaultAsBoolean(spaceBeforeSemi));
  82.638 -    }
  82.639 -
  82.640 -    public boolean spaceAfterSemi() {
  82.641 -    return preferences.getBoolean(spaceAfterSemi, getDefaultAsBoolean(spaceAfterSemi));
  82.642 -    }
  82.643 -
  82.644 -    public boolean spaceBeforeColon() {
  82.645 -    return preferences.getBoolean(spaceBeforeColon, getDefaultAsBoolean(spaceBeforeColon));
  82.646 -    }
  82.647 -
  82.648 -    public boolean spaceAfterColon() {
  82.649 -    return preferences.getBoolean(spaceAfterColon, getDefaultAsBoolean(spaceAfterColon));
  82.650 -    }
  82.651 -
  82.652 -    public boolean spaceAfterTypeCast() {
  82.653 -    return preferences.getBoolean(spaceAfterTypeCast, getDefaultAsBoolean(spaceAfterTypeCast));
  82.654 -    }
  82.655 -
  82.656 -     */
  82.657 -    // Spaces -----------------------------------------------------------------
  82.658 -    public boolean addSpaceAroundOperators() {
  82.659 -        return preferences.getBoolean(addSpaceAroundOperators, getDefaultAsBoolean(addSpaceAroundOperators));
  82.660 -    }
  82.661 -
  82.662 -    public boolean removeSpaceInsideParens() {
  82.663 -        return preferences.getBoolean(removeSpaceInParens, getDefaultAsBoolean(removeSpaceInParens));
  82.664 -    }
  82.665 -
  82.666 -    public boolean addSpaceAfterComma() {
  82.667 -        return preferences.getBoolean(addSpaceAfterComma, getDefaultAsBoolean(addSpaceAfterComma));
  82.668 -    }
  82.669 -
  82.670 -    public boolean removeSpaceBeforeSep() {
  82.671 -        return preferences.getBoolean(removeSpaceBeforeSep, getDefaultAsBoolean(removeSpaceBeforeSep));
  82.672 -    }
  82.673 -
  82.674 -    public boolean removeSpaceInParamAssign() {
  82.675 -        return preferences.getBoolean(removeSpaceInParamAssign, getDefaultAsBoolean(removeSpaceInParamAssign));
  82.676 -    }
  82.677 -
  82.678 -    public boolean collapseSpaces() {
  82.679 -        return preferences.getBoolean(collapseSpaces, getDefaultAsBoolean(collapseSpaces));
  82.680 -    }
  82.681 -
  82.682 -    // Imports -----------------------------------------------------------------
  82.683 -    public boolean formatImports() {
  82.684 -        return preferences.getBoolean(formatImports, getDefaultAsBoolean(formatImports));
  82.685 -    }
  82.686 -
  82.687 -    public boolean oneImportPerLine() {
  82.688 -        return preferences.getBoolean(oneImportPerLine, getDefaultAsBoolean(oneImportPerLine));
  82.689 -    }
  82.690 -
  82.691 -    public boolean removeDuplicates() {
  82.692 -        return preferences.getBoolean(removeDuplicates, getDefaultAsBoolean(removeDuplicates));
  82.693 -    }
  82.694 -
  82.695 -    public boolean systemLibsFirst() {
  82.696 -        return preferences.getBoolean(systemLibsFirst, getDefaultAsBoolean(systemLibsFirst));
  82.697 -    }
  82.698 -
  82.699 -    public boolean preferSymbolImports() {
  82.700 -        return preferences.getBoolean(preferSymbolImports, getDefaultAsBoolean(preferSymbolImports));
  82.701 -    }
  82.702 -
  82.703 -    public boolean sortImports() {
  82.704 -        return preferences.getBoolean(sortImports, getDefaultAsBoolean(sortImports));
  82.705 -    }
  82.706 -
  82.707 -    public boolean separateFromImps() {
  82.708 -        return preferences.getBoolean(separateFromImps, getDefaultAsBoolean(separateFromImps));
  82.709 -    }
  82.710 -
  82.711 -    public ImportCleanupStyle cleanupImports() {
  82.712 -        String cleanup = preferences.get(cleanupUnusedImports, getDefaultAsString(cleanupUnusedImports));
  82.713 -        return ImportCleanupStyle.valueOf(cleanup);
  82.714 -    }
  82.715 -
  82.716 -    public String[] getPackagesForStarImport() {
  82.717 -        return null;
  82.718 -    }
  82.719 -
  82.720 -    // Nested classes ----------------------------------------------------------
  82.721 -    public enum WrapStyle {
  82.722 -        WRAP_ALWAYS,
  82.723 -        WRAP_IF_LONG,
  82.724 -        WRAP_NEVER
  82.725 -    }
  82.726 -
  82.727 -    public enum ImportCleanupStyle {
  82.728 -        LEAVE_ALONE,
  82.729 -        COMMENT_OUT,
  82.730 -        DELETE
  82.731 -    }
  82.732 -
  82.733 -    // Communication with non public packages ----------------------------------
  82.734 -    private static class Producer implements FmtOptions.CodeStyleProducer {
  82.735 -        @Override
  82.736 -        public CodeStyle create(Preferences preferences) {
  82.737 -            return new CodeStyle(preferences);
  82.738 -        }
  82.739 -    }
  82.740 -}
    83.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtAlignment.form	Sat Sep 12 23:03:15 2015 -0700
    83.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.3 @@ -1,350 +0,0 @@
    83.4 -<?xml version="1.0" encoding="UTF-8" ?>
    83.5 -
    83.6 -<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    83.7 -  <Properties>
    83.8 -    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    83.9 -      <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_Alignment" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   83.10 -    </Property>
   83.11 -    <Property name="opaque" type="boolean" value="false"/>
   83.12 -  </Properties>
   83.13 -  <AuxValues>
   83.14 -    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   83.15 -    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   83.16 -    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   83.17 -    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
   83.18 -    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   83.19 -    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
   83.20 -    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
   83.21 -    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   83.22 -    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   83.23 -  </AuxValues>
   83.24 -
   83.25 -  <Layout>
   83.26 -    <DimensionLayout dim="0">
   83.27 -      <Group type="103" groupAlignment="0" attributes="0">
   83.28 -          <Group type="102" attributes="0">
   83.29 -              <Group type="103" groupAlignment="0" attributes="0">
   83.30 -                  <Group type="102" alignment="0" attributes="0">
   83.31 -                      <EmptySpace min="-2" max="-2" attributes="0"/>
   83.32 -                      <Component id="amParenthesizedCheckBox1" min="-2" max="-2" attributes="0"/>
   83.33 -                  </Group>
   83.34 -                  <Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
   83.35 -                      <Group type="102" alignment="0" attributes="1">
   83.36 -                          <Component id="newLinesLabel" min="-2" max="-2" attributes="0"/>
   83.37 -                          <EmptySpace max="-2" attributes="0"/>
   83.38 -                          <Component id="jSeparator1" max="32767" attributes="0"/>
   83.39 -                      </Group>
   83.40 -                      <Group type="102" alignment="0" attributes="1">
   83.41 -                          <Component id="multilineAlignmentLabel" min="-2" max="-2" attributes="0"/>
   83.42 -                          <EmptySpace max="-2" attributes="0"/>
   83.43 -                          <Component id="jSeparator2" max="32767" attributes="1"/>
   83.44 -                      </Group>
   83.45 -                      <Group type="102" alignment="0" attributes="0">
   83.46 -                          <EmptySpace max="-2" attributes="0"/>
   83.47 -                          <Group type="103" groupAlignment="0" attributes="0">
   83.48 -                              <Component id="amThrowsCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/>
   83.49 -                              <Component id="amBinaryOpCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/>
   83.50 -                              <Component id="amAssignCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/>
   83.51 -                              <Component id="amAnnotationArgsCheckBox" alignment="0" min="-2" max="-2" attributes="1"/>
   83.52 -                              <Component id="nlElseCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
   83.53 -                              <Component id="nlWhileCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
   83.54 -                              <Component id="nlCatchCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
   83.55 -                              <Component id="amMethodParamsCheckBox" alignment="0" min="-2" max="-2" attributes="1"/>
   83.56 -                          </Group>
   83.57 -                          <EmptySpace min="-2" max="-2" attributes="0"/>
   83.58 -                          <Group type="103" groupAlignment="0" attributes="0">
   83.59 -                              <Component id="amCallArgsCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
   83.60 -                              <Component id="nlModifiersCheckBox" min="-2" max="-2" attributes="0"/>
   83.61 -                              <Component id="nlFinallyCheckBox" min="-2" max="-2" attributes="0"/>
   83.62 -                              <Component id="amImplementsCheckBox1" min="-2" max="-2" attributes="0"/>
   83.63 -                              <Component id="amArrayInitCheckBox1" min="-2" max="-2" attributes="0"/>
   83.64 -                              <Component id="amTernaryOpCheckBox1" min="-2" max="-2" attributes="0"/>
   83.65 -                              <Component id="amForCheckBox1" min="-2" max="-2" attributes="0"/>
   83.66 -                          </Group>
   83.67 -                      </Group>
   83.68 -                  </Group>
   83.69 -              </Group>
   83.70 -              <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
   83.71 -          </Group>
   83.72 -      </Group>
   83.73 -    </DimensionLayout>
   83.74 -    <DimensionLayout dim="1">
   83.75 -      <Group type="103" groupAlignment="0" attributes="0">
   83.76 -          <Group type="102" alignment="0" attributes="0">
   83.77 -              <Group type="103" groupAlignment="0" attributes="0">
   83.78 -                  <Group type="102" attributes="0">
   83.79 -                      <EmptySpace max="-2" attributes="0"/>
   83.80 -                      <Component id="newLinesLabel" min="-2" max="-2" attributes="1"/>
   83.81 -                  </Group>
   83.82 -                  <Group type="102" attributes="0">
   83.83 -                      <EmptySpace min="-2" pref="17" max="-2" attributes="0"/>
   83.84 -                      <Component id="jSeparator1" min="-2" pref="10" max="-2" attributes="0"/>
   83.85 -                  </Group>
   83.86 -              </Group>
   83.87 -              <EmptySpace max="-2" attributes="0"/>
   83.88 -              <Group type="103" groupAlignment="3" attributes="0">
   83.89 -                  <Component id="nlElseCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
   83.90 -                  <Component id="nlFinallyCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
   83.91 -              </Group>
   83.92 -              <EmptySpace max="-2" attributes="0"/>
   83.93 -              <Group type="103" groupAlignment="3" attributes="0">
   83.94 -                  <Component id="nlWhileCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
   83.95 -                  <Component id="nlModifiersCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
   83.96 -              </Group>
   83.97 -              <Group type="103" groupAlignment="0" attributes="0">
   83.98 -                  <Group type="102" attributes="0">
   83.99 -                      <EmptySpace max="-2" attributes="0"/>
  83.100 -                      <Component id="nlCatchCheckBox" min="-2" max="-2" attributes="0"/>
  83.101 -                      <EmptySpace type="separate" max="-2" attributes="0"/>
  83.102 -                      <Component id="multilineAlignmentLabel" min="-2" max="-2" attributes="0"/>
  83.103 -                  </Group>
  83.104 -                  <Group type="102" attributes="0">
  83.105 -                      <EmptySpace min="-2" pref="44" max="-2" attributes="0"/>
  83.106 -                      <Component id="jSeparator2" min="-2" pref="10" max="-2" attributes="0"/>
  83.107 -                  </Group>
  83.108 -              </Group>
  83.109 -              <EmptySpace min="-2" max="-2" attributes="0"/>
  83.110 -              <Group type="103" groupAlignment="3" attributes="0">
  83.111 -                  <Component id="amMethodParamsCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
  83.112 -                  <Component id="amCallArgsCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
  83.113 -              </Group>
  83.114 -              <EmptySpace min="-2" max="-2" attributes="0"/>
  83.115 -              <Group type="103" groupAlignment="3" attributes="0">
  83.116 -                  <Component id="amAnnotationArgsCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
  83.117 -                  <Component id="amImplementsCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
  83.118 -              </Group>
  83.119 -              <EmptySpace max="-2" attributes="0"/>
  83.120 -              <Group type="103" groupAlignment="3" attributes="0">
  83.121 -                  <Component id="amThrowsCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
  83.122 -                  <Component id="amArrayInitCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
  83.123 -              </Group>
  83.124 -              <EmptySpace max="-2" attributes="0"/>
  83.125 -              <Group type="103" groupAlignment="3" attributes="0">
  83.126 -                  <Component id="amBinaryOpCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
  83.127 -                  <Component id="amTernaryOpCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
  83.128 -              </Group>
  83.129 -              <EmptySpace max="-2" attributes="0"/>
  83.130 -              <Group type="103" groupAlignment="3" attributes="0">
  83.131 -                  <Component id="amAssignCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
  83.132 -                  <Component id="amForCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
  83.133 -              </Group>
  83.134 -              <EmptySpace min="-2" max="-2" attributes="0"/>
  83.135 -              <Component id="amParenthesizedCheckBox1" min="-2" max="-2" attributes="0"/>
  83.136 -              <EmptySpace max="32767" attributes="0"/>
  83.137 -          </Group>
  83.138 -      </Group>
  83.139 -    </DimensionLayout>
  83.140 -  </Layout>
  83.141 -  <SubComponents>
  83.142 -    <Component class="javax.swing.JLabel" name="newLinesLabel">
  83.143 -      <Properties>
  83.144 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.145 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_al_newLines" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.146 -        </Property>
  83.147 -      </Properties>
  83.148 -    </Component>
  83.149 -    <Component class="javax.swing.JCheckBox" name="nlElseCheckBox">
  83.150 -      <Properties>
  83.151 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.152 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_nl_Else" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.153 -        </Property>
  83.154 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.155 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.156 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.157 -          </Border>
  83.158 -        </Property>
  83.159 -      </Properties>
  83.160 -    </Component>
  83.161 -    <Component class="javax.swing.JCheckBox" name="nlWhileCheckBox">
  83.162 -      <Properties>
  83.163 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.164 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_nl_While" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.165 -        </Property>
  83.166 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.167 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.168 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.169 -          </Border>
  83.170 -        </Property>
  83.171 -      </Properties>
  83.172 -    </Component>
  83.173 -    <Component class="javax.swing.JCheckBox" name="nlCatchCheckBox">
  83.174 -      <Properties>
  83.175 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.176 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_nl_Catch" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.177 -        </Property>
  83.178 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.179 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.180 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.181 -          </Border>
  83.182 -        </Property>
  83.183 -      </Properties>
  83.184 -    </Component>
  83.185 -    <Component class="javax.swing.JCheckBox" name="nlFinallyCheckBox">
  83.186 -      <Properties>
  83.187 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.188 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_nl_Finally" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.189 -        </Property>
  83.190 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.191 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.192 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.193 -          </Border>
  83.194 -        </Property>
  83.195 -      </Properties>
  83.196 -    </Component>
  83.197 -    <Component class="javax.swing.JCheckBox" name="nlModifiersCheckBox">
  83.198 -      <Properties>
  83.199 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.200 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_nl_Modifiers" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.201 -        </Property>
  83.202 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.203 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.204 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.205 -          </Border>
  83.206 -        </Property>
  83.207 -      </Properties>
  83.208 -    </Component>
  83.209 -    <Component class="javax.swing.JLabel" name="multilineAlignmentLabel">
  83.210 -      <Properties>
  83.211 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.212 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_al_multilineAlignment" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.213 -        </Property>
  83.214 -      </Properties>
  83.215 -    </Component>
  83.216 -    <Component class="javax.swing.JCheckBox" name="amMethodParamsCheckBox">
  83.217 -      <Properties>
  83.218 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.219 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_MethodParams" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.220 -        </Property>
  83.221 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.222 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.223 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.224 -          </Border>
  83.225 -        </Property>
  83.226 -      </Properties>
  83.227 -    </Component>
  83.228 -    <Component class="javax.swing.JCheckBox" name="amCallArgsCheckBox">
  83.229 -      <Properties>
  83.230 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.231 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_CallArgs" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.232 -        </Property>
  83.233 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.234 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.235 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.236 -          </Border>
  83.237 -        </Property>
  83.238 -      </Properties>
  83.239 -    </Component>
  83.240 -    <Component class="javax.swing.JCheckBox" name="amAnnotationArgsCheckBox">
  83.241 -      <Properties>
  83.242 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.243 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_AnnotationArgs" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.244 -        </Property>
  83.245 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.246 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.247 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.248 -          </Border>
  83.249 -        </Property>
  83.250 -      </Properties>
  83.251 -    </Component>
  83.252 -    <Component class="javax.swing.JCheckBox" name="amImplementsCheckBox1">
  83.253 -      <Properties>
  83.254 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.255 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_an_Implements" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.256 -        </Property>
  83.257 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.258 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.259 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.260 -          </Border>
  83.261 -        </Property>
  83.262 -      </Properties>
  83.263 -    </Component>
  83.264 -    <Component class="javax.swing.JCheckBox" name="amThrowsCheckBox1">
  83.265 -      <Properties>
  83.266 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.267 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_Throws" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.268 -        </Property>
  83.269 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.270 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.271 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.272 -          </Border>
  83.273 -        </Property>
  83.274 -      </Properties>
  83.275 -    </Component>
  83.276 -    <Component class="javax.swing.JCheckBox" name="amArrayInitCheckBox1">
  83.277 -      <Properties>
  83.278 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.279 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_ArrayInit" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.280 -        </Property>
  83.281 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.282 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.283 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.284 -          </Border>
  83.285 -        </Property>
  83.286 -      </Properties>
  83.287 -    </Component>
  83.288 -    <Component class="javax.swing.JCheckBox" name="amBinaryOpCheckBox1">
  83.289 -      <Properties>
  83.290 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.291 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_BinaryOp" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.292 -        </Property>
  83.293 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.294 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.295 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.296 -          </Border>
  83.297 -        </Property>
  83.298 -      </Properties>
  83.299 -    </Component>
  83.300 -    <Component class="javax.swing.JCheckBox" name="amTernaryOpCheckBox1">
  83.301 -      <Properties>
  83.302 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.303 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_TernaryOp" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.304 -        </Property>
  83.305 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.306 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.307 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.308 -          </Border>
  83.309 -        </Property>
  83.310 -      </Properties>
  83.311 -    </Component>
  83.312 -    <Component class="javax.swing.JCheckBox" name="amAssignCheckBox1">
  83.313 -      <Properties>
  83.314 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.315 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_Assign" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.316 -        </Property>
  83.317 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.318 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.319 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.320 -          </Border>
  83.321 -        </Property>
  83.322 -      </Properties>
  83.323 -    </Component>
  83.324 -    <Component class="javax.swing.JCheckBox" name="amForCheckBox1">
  83.325 -      <Properties>
  83.326 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.327 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_For" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.328 -        </Property>
  83.329 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.330 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.331 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.332 -          </Border>
  83.333 -        </Property>
  83.334 -      </Properties>
  83.335 -    </Component>
  83.336 -    <Component class="javax.swing.JCheckBox" name="amParenthesizedCheckBox1">
  83.337 -      <Properties>
  83.338 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  83.339 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_Paren" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  83.340 -        </Property>
  83.341 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  83.342 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  83.343 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  83.344 -          </Border>
  83.345 -        </Property>
  83.346 -      </Properties>
  83.347 -    </Component>
  83.348 -    <Component class="javax.swing.JSeparator" name="jSeparator1">
  83.349 -    </Component>
  83.350 -    <Component class="javax.swing.JSeparator" name="jSeparator2">
  83.351 -    </Component>
  83.352 -  </SubComponents>
  83.353 -</Form>
    84.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtAlignment.java	Sat Sep 12 23:03:15 2015 -0700
    84.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.3 @@ -1,309 +0,0 @@
    84.4 -/*
    84.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    84.6 - *
    84.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    84.8 - *
    84.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   84.10 - * Other names may be trademarks of their respective owners.
   84.11 - *
   84.12 - * The contents of this file are subject to the terms of either the GNU
   84.13 - * General Public License Version 2 only ("GPL") or the Common
   84.14 - * Development and Distribution License("CDDL") (collectively, the
   84.15 - * "License"). You may not use this file except in compliance with the
   84.16 - * License. You can obtain a copy of the License at
   84.17 - * http://www.netbeans.org/cddl-gplv2.html
   84.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   84.19 - * specific language governing permissions and limitations under the
   84.20 - * License.  When distributing the software, include this License Header
   84.21 - * Notice in each file and include the License file at
   84.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   84.23 - * particular file as subject to the "Classpath" exception as provided
   84.24 - * by Oracle in the GPL Version 2 section of the License file that
   84.25 - * accompanied this code. If applicable, add the following below the
   84.26 - * License Header, with the fields enclosed by brackets [] replaced by
   84.27 - * your own identifying information:
   84.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   84.29 - *
   84.30 - * Contributor(s):
   84.31 - *
   84.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   84.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   84.34 - * Microsystems, Inc. All Rights Reserved.
   84.35 - *
   84.36 - * If you wish your version of this file to be governed by only the CDDL
   84.37 - * or only the GPL Version 2, indicate your decision by adding
   84.38 - * "[Contributor] elects to include this software in this distribution
   84.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   84.40 - * single choice of license, a recipient has the option to distribute
   84.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   84.42 - * to extend the choice of license to its licensees as provided above.
   84.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   84.44 - * Version 2 license, then the option applies only if the new code is
   84.45 - * made subject to such option by the copyright holder.
   84.46 - */
   84.47 -
   84.48 -package org.netbeans.modules.python.editor.options;
   84.49 -
   84.50 -import org.netbeans.modules.python.editor.options.CodeStyle.WrapStyle;
   84.51 -import static org.netbeans.modules.python.editor.options.FmtOptions.*;
   84.52 -import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
   84.53 -import org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport;
   84.54 -import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
   84.55 -
   84.56 -
   84.57 -/**
   84.58 - *
   84.59 - * @author  phrebejk
   84.60 - */
   84.61 -public class FmtAlignment extends javax.swing.JPanel {
   84.62 -    
   84.63 -    /** Creates new form FmtAlignment */
   84.64 -    public FmtAlignment() {
   84.65 -        initComponents();
   84.66 -/*
   84.67 -        nlElseCheckBox.putClientProperty(OPTION_ID, placeElseOnNewLine);
   84.68 -        nlWhileCheckBox.putClientProperty(OPTION_ID, placeWhileOnNewLine);
   84.69 -        nlCatchCheckBox.putClientProperty(OPTION_ID, placeCatchOnNewLine);
   84.70 -        nlFinallyCheckBox.putClientProperty(OPTION_ID, placeFinallyOnNewLine);
   84.71 -        nlModifiersCheckBox.putClientProperty(OPTION_ID, placeNewLineAfterModifiers);
   84.72 -        amMethodParamsCheckBox.putClientProperty(OPTION_ID, alignMultilineMethodParams);
   84.73 -        amCallArgsCheckBox.putClientProperty(OPTION_ID, alignMultilineCallArgs);
   84.74 -        amAnnotationArgsCheckBox.putClientProperty(OPTION_ID, alignMultilineAnnotationArgs);
   84.75 -        amArrayInitCheckBox1.putClientProperty(OPTION_ID, alignMultilineArrayInit);
   84.76 -        amAssignCheckBox1.putClientProperty(OPTION_ID, alignMultilineAssignment);
   84.77 -        amBinaryOpCheckBox1.putClientProperty(OPTION_ID, alignMultilineBinaryOp);
   84.78 -        amForCheckBox1.putClientProperty(OPTION_ID, alignMultilineFor);
   84.79 -        amImplementsCheckBox1.putClientProperty(OPTION_ID, alignMultilineImplements);
   84.80 -        amParenthesizedCheckBox1.putClientProperty(OPTION_ID, alignMultilineParenthesized);
   84.81 -        amTernaryOpCheckBox1.putClientProperty(OPTION_ID, alignMultilineTernaryOp);
   84.82 -        amThrowsCheckBox1.putClientProperty(OPTION_ID, alignMultilineThrows);
   84.83 -    }
   84.84 -    
   84.85 -    public static PreferencesCustomizer.Factory getController() {
   84.86 -        return new CategorySupport.Factory("alignment", FmtAlignment.class, //NOI18N
   84.87 -                org.openide.util.NbBundle.getMessage(FmtAlignment.class, "SAMPLE_AlignBraces"), // NOI18N
   84.88 -                new String[] { FmtOptions.wrapAnnotations, WrapStyle.WRAP_ALWAYS.name() },
   84.89 -                new String[] { FmtOptions.wrapArrayInit, WrapStyle.WRAP_ALWAYS.name() },
   84.90 -                new String[] { FmtOptions.wrapAssert, WrapStyle.WRAP_ALWAYS.name() },
   84.91 -                new String[] { FmtOptions.wrapAssignOps, WrapStyle.WRAP_ALWAYS.name() },
   84.92 -                new String[] { FmtOptions.wrapBinaryOps, WrapStyle.WRAP_ALWAYS.name() },
   84.93 -                new String[] { FmtOptions.wrapChainedMethodCalls, WrapStyle.WRAP_ALWAYS.name() },
   84.94 -                new String[] { FmtOptions.wrapDoWhileStatement, WrapStyle.WRAP_ALWAYS.name() },
   84.95 -                new String[] { FmtOptions.wrapEnumConstants, WrapStyle.WRAP_ALWAYS.name() },
   84.96 -                new String[] { FmtOptions.wrapExtendsImplementsKeyword, WrapStyle.WRAP_ALWAYS.name() },
   84.97 -                new String[] { FmtOptions.wrapExtendsImplementsList, WrapStyle.WRAP_ALWAYS.name() },
   84.98 -                new String[] { FmtOptions.wrapFor, WrapStyle.WRAP_ALWAYS.name() },
   84.99 -                new String[] { FmtOptions.wrapForStatement, WrapStyle.WRAP_ALWAYS.name() },
  84.100 -                new String[] { FmtOptions.wrapIfStatement, WrapStyle.WRAP_ALWAYS.name() },
  84.101 -                new String[] { FmtOptions.wrapMethodCallArgs, WrapStyle.WRAP_ALWAYS.name() },
  84.102 -                new String[] { FmtOptions.wrapAnnotationArgs, WrapStyle.WRAP_ALWAYS.name() },
  84.103 -                new String[] { FmtOptions.wrapMethodParams, WrapStyle.WRAP_ALWAYS.name() },
  84.104 -                new String[] { FmtOptions.wrapTernaryOps, WrapStyle.WRAP_ALWAYS.name() },
  84.105 -                new String[] { FmtOptions.wrapThrowsKeyword, WrapStyle.WRAP_ALWAYS.name() },
  84.106 -                new String[] { FmtOptions.wrapThrowsList, WrapStyle.WRAP_ALWAYS.name() },
  84.107 -                new String[] { FmtOptions.wrapWhileStatement, WrapStyle.WRAP_ALWAYS.name() }  );
  84.108 - */
  84.109 -    }
  84.110 -    
  84.111 -    /** This method is called from within the constructor to
  84.112 -     * initialize the form.
  84.113 -     * WARNING: Do NOT modify this code. The content of this method is
  84.114 -     * always regenerated by the Form Editor.
  84.115 -     */
  84.116 -    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  84.117 -    private void initComponents() {
  84.118 -
  84.119 -        newLinesLabel = new javax.swing.JLabel();
  84.120 -        nlElseCheckBox = new javax.swing.JCheckBox();
  84.121 -        nlWhileCheckBox = new javax.swing.JCheckBox();
  84.122 -        nlCatchCheckBox = new javax.swing.JCheckBox();
  84.123 -        nlFinallyCheckBox = new javax.swing.JCheckBox();
  84.124 -        nlModifiersCheckBox = new javax.swing.JCheckBox();
  84.125 -        multilineAlignmentLabel = new javax.swing.JLabel();
  84.126 -        amMethodParamsCheckBox = new javax.swing.JCheckBox();
  84.127 -        amCallArgsCheckBox = new javax.swing.JCheckBox();
  84.128 -        amAnnotationArgsCheckBox = new javax.swing.JCheckBox();
  84.129 -        amImplementsCheckBox1 = new javax.swing.JCheckBox();
  84.130 -        amThrowsCheckBox1 = new javax.swing.JCheckBox();
  84.131 -        amArrayInitCheckBox1 = new javax.swing.JCheckBox();
  84.132 -        amBinaryOpCheckBox1 = new javax.swing.JCheckBox();
  84.133 -        amTernaryOpCheckBox1 = new javax.swing.JCheckBox();
  84.134 -        amAssignCheckBox1 = new javax.swing.JCheckBox();
  84.135 -        amForCheckBox1 = new javax.swing.JCheckBox();
  84.136 -        amParenthesizedCheckBox1 = new javax.swing.JCheckBox();
  84.137 -        jSeparator1 = new javax.swing.JSeparator();
  84.138 -        jSeparator2 = new javax.swing.JSeparator();
  84.139 -
  84.140 -        setName(org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_Alignment")); // NOI18N
  84.141 -        setOpaque(false);
  84.142 -
  84.143 -        org.openide.awt.Mnemonics.setLocalizedText(newLinesLabel, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_al_newLines")); // NOI18N
  84.144 -
  84.145 -        org.openide.awt.Mnemonics.setLocalizedText(nlElseCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Else")); // NOI18N
  84.146 -        nlElseCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.147 -
  84.148 -        org.openide.awt.Mnemonics.setLocalizedText(nlWhileCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_While")); // NOI18N
  84.149 -        nlWhileCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.150 -
  84.151 -        org.openide.awt.Mnemonics.setLocalizedText(nlCatchCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Catch")); // NOI18N
  84.152 -        nlCatchCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.153 -
  84.154 -        org.openide.awt.Mnemonics.setLocalizedText(nlFinallyCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Finally")); // NOI18N
  84.155 -        nlFinallyCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.156 -
  84.157 -        org.openide.awt.Mnemonics.setLocalizedText(nlModifiersCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Modifiers")); // NOI18N
  84.158 -        nlModifiersCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.159 -
  84.160 -        org.openide.awt.Mnemonics.setLocalizedText(multilineAlignmentLabel, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_al_multilineAlignment")); // NOI18N
  84.161 -
  84.162 -        org.openide.awt.Mnemonics.setLocalizedText(amMethodParamsCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_MethodParams")); // NOI18N
  84.163 -        amMethodParamsCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.164 -
  84.165 -        org.openide.awt.Mnemonics.setLocalizedText(amCallArgsCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_CallArgs")); // NOI18N
  84.166 -        amCallArgsCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.167 -
  84.168 -        org.openide.awt.Mnemonics.setLocalizedText(amAnnotationArgsCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_AnnotationArgs")); // NOI18N
  84.169 -        amAnnotationArgsCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.170 -
  84.171 -        org.openide.awt.Mnemonics.setLocalizedText(amImplementsCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_an_Implements")); // NOI18N
  84.172 -        amImplementsCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.173 -
  84.174 -        org.openide.awt.Mnemonics.setLocalizedText(amThrowsCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_Throws")); // NOI18N
  84.175 -        amThrowsCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.176 -
  84.177 -        org.openide.awt.Mnemonics.setLocalizedText(amArrayInitCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_ArrayInit")); // NOI18N
  84.178 -        amArrayInitCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.179 -
  84.180 -        org.openide.awt.Mnemonics.setLocalizedText(amBinaryOpCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_BinaryOp")); // NOI18N
  84.181 -        amBinaryOpCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.182 -
  84.183 -        org.openide.awt.Mnemonics.setLocalizedText(amTernaryOpCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_TernaryOp")); // NOI18N
  84.184 -        amTernaryOpCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.185 -
  84.186 -        org.openide.awt.Mnemonics.setLocalizedText(amAssignCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_Assign")); // NOI18N
  84.187 -        amAssignCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.188 -
  84.189 -        org.openide.awt.Mnemonics.setLocalizedText(amForCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_For")); // NOI18N
  84.190 -        amForCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.191 -
  84.192 -        org.openide.awt.Mnemonics.setLocalizedText(amParenthesizedCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_Paren")); // NOI18N
  84.193 -        amParenthesizedCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  84.194 -
  84.195 -        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
  84.196 -        this.setLayout(layout);
  84.197 -        layout.setHorizontalGroup(
  84.198 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  84.199 -            .addGroup(layout.createSequentialGroup()
  84.200 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  84.201 -                    .addGroup(layout.createSequentialGroup()
  84.202 -                        .addContainerGap()
  84.203 -                        .addComponent(amParenthesizedCheckBox1))
  84.204 -                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
  84.205 -                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
  84.206 -                            .addComponent(newLinesLabel)
  84.207 -                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  84.208 -                            .addComponent(jSeparator1))
  84.209 -                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
  84.210 -                            .addComponent(multilineAlignmentLabel)
  84.211 -                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  84.212 -                            .addComponent(jSeparator2))
  84.213 -                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
  84.214 -                            .addContainerGap()
  84.215 -                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  84.216 -                                .addComponent(amThrowsCheckBox1)
  84.217 -                                .addComponent(amBinaryOpCheckBox1)
  84.218 -                                .addComponent(amAssignCheckBox1)
  84.219 -                                .addComponent(amAnnotationArgsCheckBox)
  84.220 -                                .addComponent(nlElseCheckBox)
  84.221 -                                .addComponent(nlWhileCheckBox)
  84.222 -                                .addComponent(nlCatchCheckBox)
  84.223 -                                .addComponent(amMethodParamsCheckBox))
  84.224 -                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  84.225 -                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  84.226 -                                .addComponent(amCallArgsCheckBox)
  84.227 -                                .addComponent(nlModifiersCheckBox)
  84.228 -                                .addComponent(nlFinallyCheckBox)
  84.229 -                                .addComponent(amImplementsCheckBox1)
  84.230 -                                .addComponent(amArrayInitCheckBox1)
  84.231 -                                .addComponent(amTernaryOpCheckBox1)
  84.232 -                                .addComponent(amForCheckBox1)))))
  84.233 -                .addGap(0, 0, 0))
  84.234 -        );
  84.235 -        layout.setVerticalGroup(
  84.236 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  84.237 -            .addGroup(layout.createSequentialGroup()
  84.238 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  84.239 -                    .addGroup(layout.createSequentialGroup()
  84.240 -                        .addContainerGap()
  84.241 -                        .addComponent(newLinesLabel))
  84.242 -                    .addGroup(layout.createSequentialGroup()
  84.243 -                        .addGap(17, 17, 17)
  84.244 -                        .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)))
  84.245 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  84.246 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  84.247 -                    .addComponent(nlElseCheckBox)
  84.248 -                    .addComponent(nlFinallyCheckBox))
  84.249 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  84.250 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  84.251 -                    .addComponent(nlWhileCheckBox)
  84.252 -                    .addComponent(nlModifiersCheckBox))
  84.253 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  84.254 -                    .addGroup(layout.createSequentialGroup()
  84.255 -                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  84.256 -                        .addComponent(nlCatchCheckBox)
  84.257 -                        .addGap(18, 18, 18)
  84.258 -                        .addComponent(multilineAlignmentLabel))
  84.259 -                    .addGroup(layout.createSequentialGroup()
  84.260 -                        .addGap(44, 44, 44)
  84.261 -                        .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)))
  84.262 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  84.263 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  84.264 -                    .addComponent(amMethodParamsCheckBox)
  84.265 -                    .addComponent(amCallArgsCheckBox))
  84.266 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  84.267 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  84.268 -                    .addComponent(amAnnotationArgsCheckBox)
  84.269 -                    .addComponent(amImplementsCheckBox1))
  84.270 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  84.271 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  84.272 -                    .addComponent(amThrowsCheckBox1)
  84.273 -                    .addComponent(amArrayInitCheckBox1))
  84.274 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  84.275 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  84.276 -                    .addComponent(amBinaryOpCheckBox1)
  84.277 -                    .addComponent(amTernaryOpCheckBox1))
  84.278 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  84.279 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  84.280 -                    .addComponent(amAssignCheckBox1)
  84.281 -                    .addComponent(amForCheckBox1))
  84.282 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  84.283 -                .addComponent(amParenthesizedCheckBox1)
  84.284 -                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  84.285 -        );
  84.286 -    }// </editor-fold>//GEN-END:initComponents
  84.287 -    
  84.288 -    
  84.289 -    // Variables declaration - do not modify//GEN-BEGIN:variables
  84.290 -    private javax.swing.JCheckBox amAnnotationArgsCheckBox;
  84.291 -    private javax.swing.JCheckBox amArrayInitCheckBox1;
  84.292 -    private javax.swing.JCheckBox amAssignCheckBox1;
  84.293 -    private javax.swing.JCheckBox amBinaryOpCheckBox1;
  84.294 -    private javax.swing.JCheckBox amCallArgsCheckBox;
  84.295 -    private javax.swing.JCheckBox amForCheckBox1;
  84.296 -    private javax.swing.JCheckBox amImplementsCheckBox1;
  84.297 -    private javax.swing.JCheckBox amMethodParamsCheckBox;
  84.298 -    private javax.swing.JCheckBox amParenthesizedCheckBox1;
  84.299 -    private javax.swing.JCheckBox amTernaryOpCheckBox1;
  84.300 -    private javax.swing.JCheckBox amThrowsCheckBox1;
  84.301 -    private javax.swing.JSeparator jSeparator1;
  84.302 -    private javax.swing.JSeparator jSeparator2;
  84.303 -    private javax.swing.JLabel multilineAlignmentLabel;
  84.304 -    private javax.swing.JLabel newLinesLabel;
  84.305 -    private javax.swing.JCheckBox nlCatchCheckBox;
  84.306 -    private javax.swing.JCheckBox nlElseCheckBox;
  84.307 -    private javax.swing.JCheckBox nlFinallyCheckBox;
  84.308 -    private javax.swing.JCheckBox nlModifiersCheckBox;
  84.309 -    private javax.swing.JCheckBox nlWhileCheckBox;
  84.310 -    // End of variables declaration//GEN-END:variables
  84.311 -    
  84.312 -}
    85.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtBlankLines.form	Sat Sep 12 23:03:15 2015 -0700
    85.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.3 @@ -1,284 +0,0 @@
    85.4 -<?xml version="1.0" encoding="UTF-8" ?>
    85.5 -
    85.6 -<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    85.7 -  <Properties>
    85.8 -    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    85.9 -      <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_BlankLines" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   85.10 -    </Property>
   85.11 -    <Property name="opaque" type="boolean" value="false"/>
   85.12 -  </Properties>
   85.13 -  <AuxValues>
   85.14 -    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   85.15 -    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   85.16 -    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   85.17 -    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
   85.18 -    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   85.19 -    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
   85.20 -    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
   85.21 -    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   85.22 -    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   85.23 -  </AuxValues>
   85.24 -
   85.25 -  <Layout>
   85.26 -    <DimensionLayout dim="0">
   85.27 -      <Group type="103" groupAlignment="0" attributes="0">
   85.28 -          <Group type="102" attributes="0">
   85.29 -              <Group type="103" groupAlignment="0" attributes="0">
   85.30 -                  <Component id="bPackageLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   85.31 -                  <Component id="aPackageLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   85.32 -                  <Component id="bImportsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   85.33 -                  <Component id="aImports" alignment="0" min="-2" max="-2" attributes="0"/>
   85.34 -                  <Component id="bClassLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   85.35 -                  <Component id="aClassLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   85.36 -                  <Component id="aClassHeaderLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   85.37 -                  <Component id="bFieldsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   85.38 -                  <Component id="aFieldsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   85.39 -                  <Component id="bMethodsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   85.40 -                  <Component id="aMethodsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   85.41 -              </Group>
   85.42 -              <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
   85.43 -              <Group type="103" groupAlignment="0" attributes="0">
   85.44 -                  <Component id="aMethodsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   85.45 -                  <Component id="bMethodsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   85.46 -                  <Component id="aFieldsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   85.47 -                  <Component id="bFieldsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   85.48 -                  <Component id="aClassHeaderField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   85.49 -                  <Component id="aClassField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   85.50 -                  <Component id="bClassField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   85.51 -                  <Component id="aImportsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   85.52 -                  <Component id="bImportsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   85.53 -                  <Component id="aPackageField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   85.54 -                  <Component id="bPackageField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   85.55 -              </Group>
   85.56 -          </Group>
   85.57 -      </Group>
   85.58 -    </DimensionLayout>
   85.59 -    <DimensionLayout dim="1">
   85.60 -      <Group type="103" groupAlignment="0" attributes="0">
   85.61 -          <Group type="102" attributes="0">
   85.62 -              <Group type="103" groupAlignment="3" attributes="0">
   85.63 -                  <Component id="bPackageField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   85.64 -                  <Component id="bPackageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   85.65 -              </Group>
   85.66 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
   85.67 -              <Group type="103" groupAlignment="3" attributes="0">
   85.68 -                  <Component id="aPackageField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   85.69 -                  <Component id="aPackageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   85.70 -              </Group>
   85.71 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
   85.72 -              <Group type="103" groupAlignment="3" attributes="0">
   85.73 -                  <Component id="bImportsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   85.74 -                  <Component id="bImportsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   85.75 -              </Group>
   85.76 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
   85.77 -              <Group type="103" groupAlignment="3" attributes="0">
   85.78 -                  <Component id="aImportsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   85.79 -                  <Component id="aImports" alignment="3" min="-2" max="-2" attributes="0"/>
   85.80 -              </Group>
   85.81 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
   85.82 -              <Group type="103" groupAlignment="3" attributes="0">
   85.83 -                  <Component id="bClassField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   85.84 -                  <Component id="bClassLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   85.85 -              </Group>
   85.86 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
   85.87 -              <Group type="103" groupAlignment="3" attributes="0">
   85.88 -                  <Component id="aClassField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   85.89 -                  <Component id="aClassLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   85.90 -              </Group>
   85.91 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
   85.92 -              <Group type="103" groupAlignment="3" attributes="0">
   85.93 -                  <Component id="aClassHeaderField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   85.94 -                  <Component id="aClassHeaderLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   85.95 -              </Group>
   85.96 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
   85.97 -              <Group type="103" groupAlignment="3" attributes="0">
   85.98 -                  <Component id="bFieldsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   85.99 -                  <Component id="bFieldsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  85.100 -              </Group>
  85.101 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  85.102 -              <Group type="103" groupAlignment="3" attributes="0">
  85.103 -                  <Component id="aFieldsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  85.104 -                  <Component id="aFieldsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  85.105 -              </Group>
  85.106 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  85.107 -              <Group type="103" groupAlignment="3" attributes="0">
  85.108 -                  <Component id="bMethodsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  85.109 -                  <Component id="bMethodsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  85.110 -              </Group>
  85.111 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  85.112 -              <Group type="103" groupAlignment="3" attributes="0">
  85.113 -                  <Component id="aMethodsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  85.114 -                  <Component id="aMethodsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  85.115 -              </Group>
  85.116 -          </Group>
  85.117 -      </Group>
  85.118 -    </DimensionLayout>
  85.119 -  </Layout>
  85.120 -  <SubComponents>
  85.121 -    <Component class="javax.swing.JLabel" name="bPackageLabel">
  85.122 -      <Properties>
  85.123 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  85.124 -          <ComponentRef name="bPackageField"/>
  85.125 -        </Property>
  85.126 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  85.127 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blBeforePackage" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  85.128 -        </Property>
  85.129 -      </Properties>
  85.130 -    </Component>
  85.131 -    <Component class="javax.swing.JTextField" name="bPackageField">
  85.132 -      <Properties>
  85.133 -        <Property name="columns" type="int" value="5"/>
  85.134 -      </Properties>
  85.135 -    </Component>
  85.136 -    <Component class="javax.swing.JLabel" name="aPackageLabel">
  85.137 -      <Properties>
  85.138 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  85.139 -          <ComponentRef name="aPackageField"/>
  85.140 -        </Property>
  85.141 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  85.142 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blAfterPackage" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  85.143 -        </Property>
  85.144 -      </Properties>
  85.145 -    </Component>
  85.146 -    <Component class="javax.swing.JTextField" name="aPackageField">
  85.147 -      <Properties>
  85.148 -        <Property name="columns" type="int" value="5"/>
  85.149 -      </Properties>
  85.150 -    </Component>
  85.151 -    <Component class="javax.swing.JLabel" name="bImportsLabel">
  85.152 -      <Properties>
  85.153 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  85.154 -          <ComponentRef name="bImportsField"/>
  85.155 -        </Property>
  85.156 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  85.157 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blBeforeImports" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  85.158 -        </Property>
  85.159 -      </Properties>
  85.160 -    </Component>
  85.161 -    <Component class="javax.swing.JTextField" name="bImportsField">
  85.162 -      <Properties>
  85.163 -        <Property name="columns" type="int" value="5"/>
  85.164 -      </Properties>
  85.165 -    </Component>
  85.166 -    <Component class="javax.swing.JLabel" name="aImports">
  85.167 -      <Properties>
  85.168 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  85.169 -          <ComponentRef name="aImportsField"/>
  85.170 -        </Property>
  85.171 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  85.172 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blAfterImports" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  85.173 -        </Property>
  85.174 -      </Properties>
  85.175 -    </Component>
  85.176 -    <Component class="javax.swing.JTextField" name="aImportsField">
  85.177 -      <Properties>
  85.178 -        <Property name="columns" type="int" value="5"/>
  85.179 -      </Properties>
  85.180 -    </Component>
  85.181 -    <Component class="javax.swing.JLabel" name="bClassLabel">
  85.182 -      <Properties>
  85.183 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  85.184 -          <ComponentRef name="bClassField"/>
  85.185 -        </Property>
  85.186 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  85.187 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blBeforeClass" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  85.188 -        </Property>
  85.189 -      </Properties>
  85.190 -    </Component>
  85.191 -    <Component class="javax.swing.JTextField" name="bClassField">
  85.192 -      <Properties>
  85.193 -        <Property name="columns" type="int" value="5"/>
  85.194 -      </Properties>
  85.195 -    </Component>
  85.196 -    <Component class="javax.swing.JLabel" name="aClassLabel">
  85.197 -      <Properties>
  85.198 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  85.199 -          <ComponentRef name="aClassField"/>
  85.200 -        </Property>
  85.201 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  85.202 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blAfterClass" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  85.203 -        </Property>
  85.204 -      </Properties>
  85.205 -    </Component>
  85.206 -    <Component class="javax.swing.JTextField" name="aClassField">
  85.207 -      <Properties>
  85.208 -        <Property name="columns" type="int" value="5"/>
  85.209 -      </Properties>
  85.210 -    </Component>
  85.211 -    <Component class="javax.swing.JLabel" name="aClassHeaderLabel">
  85.212 -      <Properties>
  85.213 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  85.214 -          <ComponentRef name="aClassHeaderField"/>
  85.215 -        </Property>
  85.216 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  85.217 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blAfterClassHeader" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  85.218 -        </Property>
  85.219 -      </Properties>
  85.220 -    </Component>
  85.221 -    <Component class="javax.swing.JTextField" name="aClassHeaderField">
  85.222 -      <Properties>
  85.223 -        <Property name="columns" type="int" value="5"/>
  85.224 -      </Properties>
  85.225 -    </Component>
  85.226 -    <Component class="javax.swing.JLabel" name="bFieldsLabel">
  85.227 -      <Properties>
  85.228 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  85.229 -          <ComponentRef name="bFieldsField"/>
  85.230 -        </Property>
  85.231 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  85.232 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blBeforeFields" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  85.233 -        </Property>
  85.234 -      </Properties>
  85.235 -    </Component>
  85.236 -    <Component class="javax.swing.JTextField" name="bFieldsField">
  85.237 -      <Properties>
  85.238 -        <Property name="columns" type="int" value="5"/>
  85.239 -      </Properties>
  85.240 -    </Component>
  85.241 -    <Component class="javax.swing.JLabel" name="aFieldsLabel">
  85.242 -      <Properties>
  85.243 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  85.244 -          <ComponentRef name="aFieldsField"/>
  85.245 -        </Property>
  85.246 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  85.247 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blAfterFields" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  85.248 -        </Property>
  85.249 -      </Properties>
  85.250 -    </Component>
  85.251 -    <Component class="javax.swing.JTextField" name="aFieldsField">
  85.252 -      <Properties>
  85.253 -        <Property name="columns" type="int" value="5"/>
  85.254 -      </Properties>
  85.255 -    </Component>
  85.256 -    <Component class="javax.swing.JLabel" name="bMethodsLabel">
  85.257 -      <Properties>
  85.258 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  85.259 -          <ComponentRef name="bMethodsField"/>
  85.260 -        </Property>
  85.261 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  85.262 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blBeforeMethods" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  85.263 -        </Property>
  85.264 -      </Properties>
  85.265 -    </Component>
  85.266 -    <Component class="javax.swing.JTextField" name="bMethodsField">
  85.267 -      <Properties>
  85.268 -        <Property name="columns" type="int" value="5"/>
  85.269 -      </Properties>
  85.270 -    </Component>
  85.271 -    <Component class="javax.swing.JLabel" name="aMethodsLabel">
  85.272 -      <Properties>
  85.273 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  85.274 -          <ComponentRef name="aMethodsField"/>
  85.275 -        </Property>
  85.276 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  85.277 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blAfterMethods" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  85.278 -        </Property>
  85.279 -      </Properties>
  85.280 -    </Component>
  85.281 -    <Component class="javax.swing.JTextField" name="aMethodsField">
  85.282 -      <Properties>
  85.283 -        <Property name="columns" type="int" value="5"/>
  85.284 -      </Properties>
  85.285 -    </Component>
  85.286 -  </SubComponents>
  85.287 -</Form>
    86.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtBlankLines.java	Sat Sep 12 23:03:15 2015 -0700
    86.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.3 @@ -1,295 +0,0 @@
    86.4 -/*
    86.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    86.6 - *
    86.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    86.8 - *
    86.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   86.10 - * Other names may be trademarks of their respective owners.
   86.11 - *
   86.12 - * The contents of this file are subject to the terms of either the GNU
   86.13 - * General Public License Version 2 only ("GPL") or the Common
   86.14 - * Development and Distribution License("CDDL") (collectively, the
   86.15 - * "License"). You may not use this file except in compliance with the
   86.16 - * License. You can obtain a copy of the License at
   86.17 - * http://www.netbeans.org/cddl-gplv2.html
   86.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   86.19 - * specific language governing permissions and limitations under the
   86.20 - * License.  When distributing the software, include this License Header
   86.21 - * Notice in each file and include the License file at
   86.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   86.23 - * particular file as subject to the "Classpath" exception as provided
   86.24 - * by Oracle in the GPL Version 2 section of the License file that
   86.25 - * accompanied this code. If applicable, add the following below the
   86.26 - * License Header, with the fields enclosed by brackets [] replaced by
   86.27 - * your own identifying information:
   86.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   86.29 - *
   86.30 - * Contributor(s):
   86.31 - *
   86.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   86.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   86.34 - * Microsystems, Inc. All Rights Reserved.
   86.35 - *
   86.36 - * If you wish your version of this file to be governed by only the CDDL
   86.37 - * or only the GPL Version 2, indicate your decision by adding
   86.38 - * "[Contributor] elects to include this software in this distribution
   86.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   86.40 - * single choice of license, a recipient has the option to distribute
   86.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   86.42 - * to extend the choice of license to its licensees as provided above.
   86.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   86.44 - * Version 2 license, then the option applies only if the new code is
   86.45 - * made subject to such option by the copyright holder.
   86.46 - */
   86.47 -
   86.48 -package org.netbeans.modules.python.editor.options;
   86.49 -
   86.50 -import static org.netbeans.modules.python.editor.options.FmtOptions.*;
   86.51 -import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
   86.52 -import org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport;
   86.53 -import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
   86.54 -
   86.55 -/**
   86.56 - *
   86.57 - * @author  phrebejk
   86.58 - */
   86.59 -public class FmtBlankLines extends javax.swing.JPanel {
   86.60 -    
   86.61 -    /** Creates new form FmtBlankLines */
   86.62 -    public FmtBlankLines() {
   86.63 -        initComponents();
   86.64 -/*
   86.65 -        bPackageField.putClientProperty(OPTION_ID, blankLinesBeforePackage );
   86.66 -        aPackageField.putClientProperty(OPTION_ID, blankLinesAfterPackage);
   86.67 -        bImportsField.putClientProperty(OPTION_ID, blankLinesBeforeImports);
   86.68 -        aImportsField.putClientProperty(OPTION_ID, blankLinesAfterImports);
   86.69 -        bClassField.putClientProperty(OPTION_ID, blankLinesBeforeClass);
   86.70 -        aClassField.putClientProperty(OPTION_ID, blankLinesAfterClass);
   86.71 -        aClassHeaderField.putClientProperty(OPTION_ID, blankLinesAfterClassHeader);
   86.72 -        bFieldsField.putClientProperty(OPTION_ID, blankLinesBeforeFields);
   86.73 -        aFieldsField.putClientProperty(OPTION_ID, blankLinesAfterFields);
   86.74 -        bMethodsField.putClientProperty(OPTION_ID, blankLinesBeforeMethods );
   86.75 -        aMethodsField.putClientProperty(OPTION_ID, blankLinesAfterMethods);
   86.76 -        
   86.77 -        bPackageField.addKeyListener(new NumericKeyListener());
   86.78 -        aPackageField.addKeyListener(new NumericKeyListener());
   86.79 -        bImportsField.addKeyListener(new NumericKeyListener());
   86.80 -        aImportsField.addKeyListener(new NumericKeyListener());
   86.81 -        bClassField.addKeyListener(new NumericKeyListener());
   86.82 -        aClassField.addKeyListener(new NumericKeyListener());
   86.83 -        aClassHeaderField.addKeyListener(new NumericKeyListener());
   86.84 -        bFieldsField.addKeyListener(new NumericKeyListener());
   86.85 -        aFieldsField.addKeyListener(new NumericKeyListener());
   86.86 -        bMethodsField.addKeyListener(new NumericKeyListener());
   86.87 -        aMethodsField.addKeyListener(new NumericKeyListener());
   86.88 -        
   86.89 -    }
   86.90 -    
   86.91 -    public static PreferencesCustomizer.Factory getController() {
   86.92 -        return new CategorySupport.Factory("blank-lines", FmtBlankLines.class, //NOI18N
   86.93 -                 org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "SAMPLE_BlankLines")); // NOI18N
   86.94 - */
   86.95 -    }
   86.96 -    
   86.97 -    /** This method is called from within the constructor to
   86.98 -     * initialize the form.
   86.99 -     * WARNING: Do NOT modify this code. The content of this method is
  86.100 -     * always regenerated by the Form Editor.
  86.101 -     */
  86.102 -    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  86.103 -    private void initComponents() {
  86.104 -
  86.105 -        bPackageLabel = new javax.swing.JLabel();
  86.106 -        bPackageField = new javax.swing.JTextField();
  86.107 -        aPackageLabel = new javax.swing.JLabel();
  86.108 -        aPackageField = new javax.swing.JTextField();
  86.109 -        bImportsLabel = new javax.swing.JLabel();
  86.110 -        bImportsField = new javax.swing.JTextField();
  86.111 -        aImports = new javax.swing.JLabel();
  86.112 -        aImportsField = new javax.swing.JTextField();
  86.113 -        bClassLabel = new javax.swing.JLabel();
  86.114 -        bClassField = new javax.swing.JTextField();
  86.115 -        aClassLabel = new javax.swing.JLabel();
  86.116 -        aClassField = new javax.swing.JTextField();
  86.117 -        aClassHeaderLabel = new javax.swing.JLabel();
  86.118 -        aClassHeaderField = new javax.swing.JTextField();
  86.119 -        bFieldsLabel = new javax.swing.JLabel();
  86.120 -        bFieldsField = new javax.swing.JTextField();
  86.121 -        aFieldsLabel = new javax.swing.JLabel();
  86.122 -        aFieldsField = new javax.swing.JTextField();
  86.123 -        bMethodsLabel = new javax.swing.JLabel();
  86.124 -        bMethodsField = new javax.swing.JTextField();
  86.125 -        aMethodsLabel = new javax.swing.JLabel();
  86.126 -        aMethodsField = new javax.swing.JTextField();
  86.127 -
  86.128 -        setName(org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_BlankLines")); // NOI18N
  86.129 -        setOpaque(false);
  86.130 -
  86.131 -        bPackageLabel.setLabelFor(bPackageField);
  86.132 -        org.openide.awt.Mnemonics.setLocalizedText(bPackageLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforePackage")); // NOI18N
  86.133 -
  86.134 -        bPackageField.setColumns(5);
  86.135 -
  86.136 -        aPackageLabel.setLabelFor(aPackageField);
  86.137 -        org.openide.awt.Mnemonics.setLocalizedText(aPackageLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterPackage")); // NOI18N
  86.138 -
  86.139 -        aPackageField.setColumns(5);
  86.140 -
  86.141 -        bImportsLabel.setLabelFor(bImportsField);
  86.142 -        org.openide.awt.Mnemonics.setLocalizedText(bImportsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeImports")); // NOI18N
  86.143 -
  86.144 -        bImportsField.setColumns(5);
  86.145 -
  86.146 -        aImports.setLabelFor(aImportsField);
  86.147 -        org.openide.awt.Mnemonics.setLocalizedText(aImports, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterImports")); // NOI18N
  86.148 -
  86.149 -        aImportsField.setColumns(5);
  86.150 -
  86.151 -        bClassLabel.setLabelFor(bClassField);
  86.152 -        org.openide.awt.Mnemonics.setLocalizedText(bClassLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeClass")); // NOI18N
  86.153 -
  86.154 -        bClassField.setColumns(5);
  86.155 -
  86.156 -        aClassLabel.setLabelFor(aClassField);
  86.157 -        org.openide.awt.Mnemonics.setLocalizedText(aClassLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterClass")); // NOI18N
  86.158 -
  86.159 -        aClassField.setColumns(5);
  86.160 -
  86.161 -        aClassHeaderLabel.setLabelFor(aClassHeaderField);
  86.162 -        org.openide.awt.Mnemonics.setLocalizedText(aClassHeaderLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterClassHeader")); // NOI18N
  86.163 -
  86.164 -        aClassHeaderField.setColumns(5);
  86.165 -
  86.166 -        bFieldsLabel.setLabelFor(bFieldsField);
  86.167 -        org.openide.awt.Mnemonics.setLocalizedText(bFieldsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeFields")); // NOI18N
  86.168 -
  86.169 -        bFieldsField.setColumns(5);
  86.170 -
  86.171 -        aFieldsLabel.setLabelFor(aFieldsField);
  86.172 -        org.openide.awt.Mnemonics.setLocalizedText(aFieldsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterFields")); // NOI18N
  86.173 -
  86.174 -        aFieldsField.setColumns(5);
  86.175 -
  86.176 -        bMethodsLabel.setLabelFor(bMethodsField);
  86.177 -        org.openide.awt.Mnemonics.setLocalizedText(bMethodsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeMethods")); // NOI18N
  86.178 -
  86.179 -        bMethodsField.setColumns(5);
  86.180 -
  86.181 -        aMethodsLabel.setLabelFor(aMethodsField);
  86.182 -        org.openide.awt.Mnemonics.setLocalizedText(aMethodsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterMethods")); // NOI18N
  86.183 -
  86.184 -        aMethodsField.setColumns(5);
  86.185 -
  86.186 -        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
  86.187 -        this.setLayout(layout);
  86.188 -        layout.setHorizontalGroup(
  86.189 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  86.190 -            .addGroup(layout.createSequentialGroup()
  86.191 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  86.192 -                    .addComponent(bPackageLabel)
  86.193 -                    .addComponent(aPackageLabel)
  86.194 -                    .addComponent(bImportsLabel)
  86.195 -                    .addComponent(aImports)
  86.196 -                    .addComponent(bClassLabel)
  86.197 -                    .addComponent(aClassLabel)
  86.198 -                    .addComponent(aClassHeaderLabel)
  86.199 -                    .addComponent(bFieldsLabel)
  86.200 -                    .addComponent(aFieldsLabel)
  86.201 -                    .addComponent(bMethodsLabel)
  86.202 -                    .addComponent(aMethodsLabel))
  86.203 -                .addGap(6, 6, 6)
  86.204 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  86.205 -                    .addComponent(aMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.206 -                    .addComponent(bMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.207 -                    .addComponent(aFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.208 -                    .addComponent(bFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.209 -                    .addComponent(aClassHeaderField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.210 -                    .addComponent(aClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.211 -                    .addComponent(bClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.212 -                    .addComponent(aImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.213 -                    .addComponent(bImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.214 -                    .addComponent(aPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.215 -                    .addComponent(bPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
  86.216 -        );
  86.217 -
  86.218 -        layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {aClassField, aClassHeaderField, aFieldsField, aImportsField, aMethodsField, aPackageField, bClassField, bFieldsField, bImportsField, bMethodsField, bPackageField});
  86.219 -
  86.220 -        layout.setVerticalGroup(
  86.221 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  86.222 -            .addGroup(layout.createSequentialGroup()
  86.223 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  86.224 -                    .addComponent(bPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.225 -                    .addComponent(bPackageLabel))
  86.226 -                .addGap(4, 4, 4)
  86.227 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  86.228 -                    .addComponent(aPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.229 -                    .addComponent(aPackageLabel))
  86.230 -                .addGap(4, 4, 4)
  86.231 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  86.232 -                    .addComponent(bImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.233 -                    .addComponent(bImportsLabel))
  86.234 -                .addGap(4, 4, 4)
  86.235 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  86.236 -                    .addComponent(aImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.237 -                    .addComponent(aImports))
  86.238 -                .addGap(4, 4, 4)
  86.239 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  86.240 -                    .addComponent(bClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.241 -                    .addComponent(bClassLabel))
  86.242 -                .addGap(4, 4, 4)
  86.243 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  86.244 -                    .addComponent(aClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.245 -                    .addComponent(aClassLabel))
  86.246 -                .addGap(4, 4, 4)
  86.247 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  86.248 -                    .addComponent(aClassHeaderField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.249 -                    .addComponent(aClassHeaderLabel))
  86.250 -                .addGap(4, 4, 4)
  86.251 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  86.252 -                    .addComponent(bFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.253 -                    .addComponent(bFieldsLabel))
  86.254 -                .addGap(4, 4, 4)
  86.255 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  86.256 -                    .addComponent(aFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.257 -                    .addComponent(aFieldsLabel))
  86.258 -                .addGap(4, 4, 4)
  86.259 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  86.260 -                    .addComponent(bMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.261 -                    .addComponent(bMethodsLabel))
  86.262 -                .addGap(4, 4, 4)
  86.263 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  86.264 -                    .addComponent(aMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  86.265 -                    .addComponent(aMethodsLabel)))
  86.266 -        );
  86.267 -
  86.268 -        layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {aClassField, aClassHeaderField, aFieldsField, aImportsField, aMethodsField, aPackageField, bClassField, bFieldsField, bImportsField, bMethodsField, bPackageField});
  86.269 -
  86.270 -    }// </editor-fold>//GEN-END:initComponents
  86.271 -    
  86.272 -    
  86.273 -    // Variables declaration - do not modify//GEN-BEGIN:variables
  86.274 -    private javax.swing.JTextField aClassField;
  86.275 -    private javax.swing.JTextField aClassHeaderField;
  86.276 -    private javax.swing.JLabel aClassHeaderLabel;
  86.277 -    private javax.swing.JLabel aClassLabel;
  86.278 -    private javax.swing.JTextField aFieldsField;
  86.279 -    private javax.swing.JLabel aFieldsLabel;
  86.280 -    private javax.swing.JLabel aImports;
  86.281 -    private javax.swing.JTextField aImportsField;
  86.282 -    private javax.swing.JTextField aMethodsField;
  86.283 -    private javax.swing.JLabel aMethodsLabel;
  86.284 -    private javax.swing.JTextField aPackageField;
  86.285 -    private javax.swing.JLabel aPackageLabel;
  86.286 -    private javax.swing.JTextField bClassField;
  86.287 -    private javax.swing.JLabel bClassLabel;
  86.288 -    private javax.swing.JTextField bFieldsField;
  86.289 -    private javax.swing.JLabel bFieldsLabel;
  86.290 -    private javax.swing.JTextField bImportsField;
  86.291 -    private javax.swing.JLabel bImportsLabel;
  86.292 -    private javax.swing.JTextField bMethodsField;
  86.293 -    private javax.swing.JLabel bMethodsLabel;
  86.294 -    private javax.swing.JTextField bPackageField;
  86.295 -    private javax.swing.JLabel bPackageLabel;
  86.296 -    // End of variables declaration//GEN-END:variables
  86.297 -    
  86.298 -}
    87.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtImports.form	Sat Sep 12 23:03:15 2015 -0700
    87.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.3 @@ -1,129 +0,0 @@
    87.4 -<?xml version="1.0" encoding="UTF-8" ?>
    87.5 -
    87.6 -<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    87.7 -  <Properties>
    87.8 -    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    87.9 -      <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_Imports" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   87.10 -    </Property>
   87.11 -  </Properties>
   87.12 -  <AuxValues>
   87.13 -    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   87.14 -    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   87.15 -    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   87.16 -    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
   87.17 -    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   87.18 -    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
   87.19 -    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
   87.20 -    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   87.21 -    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   87.22 -  </AuxValues>
   87.23 -
   87.24 -  <Layout>
   87.25 -    <DimensionLayout dim="0">
   87.26 -      <Group type="103" groupAlignment="0" attributes="0">
   87.27 -          <Group type="102" attributes="0">
   87.28 -              <Group type="103" groupAlignment="0" attributes="0">
   87.29 -                  <Component id="formatImportsCb" alignment="0" min="-2" max="-2" attributes="0"/>
   87.30 -                  <Component id="onePerLineCb" alignment="0" min="-2" max="-2" attributes="0"/>
   87.31 -                  <Component id="systemLibsCb" alignment="0" min="-2" max="-2" attributes="0"/>
   87.32 -                  <Component id="sortImportsCb" alignment="0" min="-2" max="-2" attributes="0"/>
   87.33 -                  <Component id="sepFromImpCb" alignment="0" min="-2" max="-2" attributes="0"/>
   87.34 -                  <Component id="removeDuplicateCb" alignment="0" min="-2" max="-2" attributes="0"/>
   87.35 -                  <Component id="preferSymbols" alignment="0" min="-2" max="-2" attributes="0"/>
   87.36 -                  <Group type="102" alignment="0" attributes="0">
   87.37 -                      <Component id="cleanupLabel" min="-2" max="-2" attributes="0"/>
   87.38 -                      <EmptySpace max="-2" attributes="0"/>
   87.39 -                      <Component id="cleanupCombo" min="-2" max="-2" attributes="0"/>
   87.40 -                  </Group>
   87.41 -              </Group>
   87.42 -              <EmptySpace max="32767" attributes="0"/>
   87.43 -          </Group>
   87.44 -      </Group>
   87.45 -    </DimensionLayout>
   87.46 -    <DimensionLayout dim="1">
   87.47 -      <Group type="103" groupAlignment="0" attributes="0">
   87.48 -          <Group type="102" alignment="0" attributes="0">
   87.49 -              <Component id="formatImportsCb" min="-2" max="-2" attributes="0"/>
   87.50 -              <EmptySpace type="separate" max="-2" attributes="0"/>
   87.51 -              <Component id="onePerLineCb" min="-2" max="-2" attributes="0"/>
   87.52 -              <EmptySpace max="-2" attributes="0"/>
   87.53 -              <Component id="systemLibsCb" min="-2" max="-2" attributes="0"/>
   87.54 -              <EmptySpace max="-2" attributes="0"/>
   87.55 -              <Component id="sortImportsCb" min="-2" max="-2" attributes="0"/>
   87.56 -              <EmptySpace max="-2" attributes="0"/>
   87.57 -              <Component id="sepFromImpCb" min="-2" max="-2" attributes="0"/>
   87.58 -              <EmptySpace max="-2" attributes="0"/>
   87.59 -              <Component id="removeDuplicateCb" min="-2" max="-2" attributes="0"/>
   87.60 -              <EmptySpace max="-2" attributes="0"/>
   87.61 -              <Component id="preferSymbols" min="-2" max="-2" attributes="0"/>
   87.62 -              <EmptySpace type="separate" max="-2" attributes="0"/>
   87.63 -              <Group type="103" groupAlignment="3" attributes="0">
   87.64 -                  <Component id="cleanupLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   87.65 -                  <Component id="cleanupCombo" alignment="3" min="-2" max="-2" attributes="0"/>
   87.66 -              </Group>
   87.67 -              <EmptySpace max="32767" attributes="0"/>
   87.68 -          </Group>
   87.69 -      </Group>
   87.70 -    </DimensionLayout>
   87.71 -  </Layout>
   87.72 -  <SubComponents>
   87.73 -    <Component class="javax.swing.JCheckBox" name="formatImportsCb">
   87.74 -      <Properties>
   87.75 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   87.76 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.formatImportsCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   87.77 -        </Property>
   87.78 -      </Properties>
   87.79 -    </Component>
   87.80 -    <Component class="javax.swing.JCheckBox" name="onePerLineCb">
   87.81 -      <Properties>
   87.82 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   87.83 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.onePerLineCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   87.84 -        </Property>
   87.85 -      </Properties>
   87.86 -    </Component>
   87.87 -    <Component class="javax.swing.JCheckBox" name="systemLibsCb">
   87.88 -      <Properties>
   87.89 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   87.90 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.systemLibsCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   87.91 -        </Property>
   87.92 -      </Properties>
   87.93 -    </Component>
   87.94 -    <Component class="javax.swing.JCheckBox" name="removeDuplicateCb">
   87.95 -      <Properties>
   87.96 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   87.97 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.removeDuplicateCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   87.98 -        </Property>
   87.99 -      </Properties>
  87.100 -    </Component>
  87.101 -    <Component class="javax.swing.JLabel" name="cleanupLabel">
  87.102 -      <Properties>
  87.103 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  87.104 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.cleanupLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  87.105 -        </Property>
  87.106 -      </Properties>
  87.107 -    </Component>
  87.108 -    <Component class="javax.swing.JComboBox" name="cleanupCombo">
  87.109 -    </Component>
  87.110 -    <Component class="javax.swing.JCheckBox" name="preferSymbols">
  87.111 -      <Properties>
  87.112 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  87.113 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.preferSymbols.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  87.114 -        </Property>
  87.115 -      </Properties>
  87.116 -    </Component>
  87.117 -    <Component class="javax.swing.JCheckBox" name="sortImportsCb">
  87.118 -      <Properties>
  87.119 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  87.120 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.sortImportsCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  87.121 -        </Property>
  87.122 -      </Properties>
  87.123 -    </Component>
  87.124 -    <Component class="javax.swing.JCheckBox" name="sepFromImpCb">
  87.125 -      <Properties>
  87.126 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  87.127 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.sepFromImpCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  87.128 -        </Property>
  87.129 -      </Properties>
  87.130 -    </Component>
  87.131 -  </SubComponents>
  87.132 -</Form>
    88.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtImports.java	Sat Sep 12 23:03:15 2015 -0700
    88.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.3 @@ -1,169 +0,0 @@
    88.4 -/*
    88.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    88.6 - *
    88.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    88.8 - *
    88.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   88.10 - * Other names may be trademarks of their respective owners.
   88.11 - *
   88.12 - * The contents of this file are subject to the terms of either the GNU
   88.13 - * General Public License Version 2 only ("GPL") or the Common
   88.14 - * Development and Distribution License("CDDL") (collectively, the
   88.15 - * "License"). You may not use this file except in compliance with the
   88.16 - * License. You can obtain a copy of the License at
   88.17 - * http://www.netbeans.org/cddl-gplv2.html
   88.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   88.19 - * specific language governing permissions and limitations under the
   88.20 - * License.  When distributing the software, include this License Header
   88.21 - * Notice in each file and include the License file at
   88.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   88.23 - * particular file as subject to the "Classpath" exception as provided
   88.24 - * by Oracle in the GPL Version 2 section of the License file that
   88.25 - * accompanied this code. If applicable, add the following below the
   88.26 - * License Header, with the fields enclosed by brackets [] replaced by
   88.27 - * your own identifying information:
   88.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   88.29 - *
   88.30 - * Contributor(s):
   88.31 - *
   88.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   88.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   88.34 - * Microsystems, Inc. All Rights Reserved.
   88.35 - *
   88.36 - * If you wish your version of this file to be governed by only the CDDL
   88.37 - * or only the GPL Version 2, indicate your decision by adding
   88.38 - * "[Contributor] elects to include this software in this distribution
   88.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   88.40 - * single choice of license, a recipient has the option to distribute
   88.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   88.42 - * to extend the choice of license to its licensees as provided above.
   88.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   88.44 - * Version 2 license, then the option applies only if the new code is
   88.45 - * made subject to such option by the copyright holder.
   88.46 - */
   88.47 -
   88.48 -package org.netbeans.modules.python.editor.options;
   88.49 -
   88.50 -import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
   88.51 -import static org.netbeans.modules.python.editor.options.FmtOptions.*;
   88.52 -import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
   88.53 -
   88.54 -/**
   88.55 - * Options related to imports
   88.56 - * 
   88.57 - * @author  Tor Norbye
   88.58 - */
   88.59 -public class FmtImports extends javax.swing.JPanel {
   88.60 -    
   88.61 -    /** Creates new form FmtImports */
   88.62 -    public FmtImports() {
   88.63 -        initComponents();
   88.64 -
   88.65 -        formatImportsCb.putClientProperty(OPTION_ID, formatImports);
   88.66 -        onePerLineCb.putClientProperty(OPTION_ID, oneImportPerLine);
   88.67 -        removeDuplicateCb.putClientProperty(OPTION_ID, removeDuplicates);
   88.68 -        systemLibsCb.putClientProperty(OPTION_ID, systemLibsFirst);
   88.69 -        cleanupCombo.putClientProperty(OPTION_ID, cleanupUnusedImports);
   88.70 -        preferSymbols.putClientProperty(OPTION_ID, preferSymbolImports);
   88.71 -        sortImportsCb.putClientProperty(OPTION_ID, sortImports);
   88.72 -        sepFromImpCb.putClientProperty(OPTION_ID, separateFromImps);
   88.73 -    }
   88.74 -    
   88.75 -    public static PreferencesCustomizer.Factory getController() {
   88.76 -        return new CategorySupport.Factory("imports", FmtImports.class,
   88.77 -                org.openide.util.NbBundle.getMessage(FmtImports.class, "SAMPLE_Imports"));
   88.78 -    }
   88.79 -    
   88.80 -    /** This method is called from within the constructor to
   88.81 -     * initialize the form.
   88.82 -     * WARNING: Do NOT modify this code. The content of this method is
   88.83 -     * always regenerated by the Form Editor.
   88.84 -     */
   88.85 -    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
   88.86 -    private void initComponents() {
   88.87 -
   88.88 -        formatImportsCb = new javax.swing.JCheckBox();
   88.89 -        onePerLineCb = new javax.swing.JCheckBox();
   88.90 -        systemLibsCb = new javax.swing.JCheckBox();
   88.91 -        removeDuplicateCb = new javax.swing.JCheckBox();
   88.92 -        cleanupLabel = new javax.swing.JLabel();
   88.93 -        cleanupCombo = new javax.swing.JComboBox();
   88.94 -        preferSymbols = new javax.swing.JCheckBox();
   88.95 -        sortImportsCb = new javax.swing.JCheckBox();
   88.96 -        sepFromImpCb = new javax.swing.JCheckBox();
   88.97 -
   88.98 -        setName(org.openide.util.NbBundle.getMessage(FmtImports.class, "LBL_Imports")); // NOI18N
   88.99 -
  88.100 -        org.openide.awt.Mnemonics.setLocalizedText(formatImportsCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.formatImportsCb.text")); // NOI18N
  88.101 -
  88.102 -        org.openide.awt.Mnemonics.setLocalizedText(onePerLineCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.onePerLineCb.text")); // NOI18N
  88.103 -
  88.104 -        org.openide.awt.Mnemonics.setLocalizedText(systemLibsCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.systemLibsCb.text")); // NOI18N
  88.105 -
  88.106 -        org.openide.awt.Mnemonics.setLocalizedText(removeDuplicateCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.removeDuplicateCb.text")); // NOI18N
  88.107 -
  88.108 -        org.openide.awt.Mnemonics.setLocalizedText(cleanupLabel, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.cleanupLabel.text")); // NOI18N
  88.109 -
  88.110 -        org.openide.awt.Mnemonics.setLocalizedText(preferSymbols, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.preferSymbols.text")); // NOI18N
  88.111 -
  88.112 -        org.openide.awt.Mnemonics.setLocalizedText(sortImportsCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.sortImportsCb.text")); // NOI18N
  88.113 -
  88.114 -        org.openide.awt.Mnemonics.setLocalizedText(sepFromImpCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.sepFromImpCb.text")); // NOI18N
  88.115 -
  88.116 -        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
  88.117 -        this.setLayout(layout);
  88.118 -        layout.setHorizontalGroup(
  88.119 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  88.120 -            .addGroup(layout.createSequentialGroup()
  88.121 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  88.122 -                    .addComponent(formatImportsCb)
  88.123 -                    .addComponent(onePerLineCb)
  88.124 -                    .addComponent(systemLibsCb)
  88.125 -                    .addComponent(sortImportsCb)
  88.126 -                    .addComponent(sepFromImpCb)
  88.127 -                    .addComponent(removeDuplicateCb)
  88.128 -                    .addComponent(preferSymbols)
  88.129 -                    .addGroup(layout.createSequentialGroup()
  88.130 -                        .addComponent(cleanupLabel)
  88.131 -                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  88.132 -                        .addComponent(cleanupCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
  88.133 -                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  88.134 -        );
  88.135 -        layout.setVerticalGroup(
  88.136 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  88.137 -            .addGroup(layout.createSequentialGroup()
  88.138 -                .addComponent(formatImportsCb)
  88.139 -                .addGap(18, 18, 18)
  88.140 -                .addComponent(onePerLineCb)
  88.141 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  88.142 -                .addComponent(systemLibsCb)
  88.143 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  88.144 -                .addComponent(sortImportsCb)
  88.145 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  88.146 -                .addComponent(sepFromImpCb)
  88.147 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  88.148 -                .addComponent(removeDuplicateCb)
  88.149 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  88.150 -                .addComponent(preferSymbols)
  88.151 -                .addGap(18, 18, 18)
  88.152 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  88.153 -                    .addComponent(cleanupLabel)
  88.154 -                    .addComponent(cleanupCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
  88.155 -                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  88.156 -        );
  88.157 -    }// </editor-fold>//GEN-END:initComponents
  88.158 -    
  88.159 -    
  88.160 -    // Variables declaration - do not modify//GEN-BEGIN:variables
  88.161 -    private javax.swing.JComboBox cleanupCombo;
  88.162 -    private javax.swing.JLabel cleanupLabel;
  88.163 -    private javax.swing.JCheckBox formatImportsCb;
  88.164 -    private javax.swing.JCheckBox onePerLineCb;
  88.165 -    private javax.swing.JCheckBox preferSymbols;
  88.166 -    private javax.swing.JCheckBox removeDuplicateCb;
  88.167 -    private javax.swing.JCheckBox sepFromImpCb;
  88.168 -    private javax.swing.JCheckBox sortImportsCb;
  88.169 -    private javax.swing.JCheckBox systemLibsCb;
  88.170 -    // End of variables declaration//GEN-END:variables
  88.171 -    
  88.172 -}
    89.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtOptions.java	Sat Sep 12 23:03:15 2015 -0700
    89.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.3 @@ -1,1035 +0,0 @@
    89.4 -/*
    89.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    89.6 - *
    89.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    89.8 - *
    89.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   89.10 - * Other names may be trademarks of their respective owners.
   89.11 - *
   89.12 - * The contents of this file are subject to the terms of either the GNU
   89.13 - * General Public License Version 2 only ("GPL") or the Common
   89.14 - * Development and Distribution License("CDDL") (collectively, the
   89.15 - * "License"). You may not use this file except in compliance with the
   89.16 - * License. You can obtain a copy of the License at
   89.17 - * http://www.netbeans.org/cddl-gplv2.html
   89.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   89.19 - * specific language governing permissions and limitations under the
   89.20 - * License.  When distributing the software, include this License Header
   89.21 - * Notice in each file and include the License file at
   89.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   89.23 - * particular file as subject to the "Classpath" exception as provided
   89.24 - * by Oracle in the GPL Version 2 section of the License file that
   89.25 - * accompanied this code. If applicable, add the following below the
   89.26 - * License Header, with the fields enclosed by brackets [] replaced by
   89.27 - * your own identifying information:
   89.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   89.29 - *
   89.30 - * Contributor(s):
   89.31 - *
   89.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   89.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
   89.34 - * Microsystems, Inc. All Rights Reserved.
   89.35 - *
   89.36 - * If you wish your version of this file to be governed by only the CDDL
   89.37 - * or only the GPL Version 2, indicate your decision by adding
   89.38 - * "[Contributor] elects to include this software in this distribution
   89.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   89.40 - * single choice of license, a recipient has the option to distribute
   89.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   89.42 - * to extend the choice of license to its licensees as provided above.
   89.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   89.44 - * Version 2 license, then the option applies only if the new code is
   89.45 - * made subject to such option by the copyright holder.
   89.46 - */
   89.47 -package org.netbeans.modules.python.editor.options;
   89.48 -
   89.49 -import java.awt.Component;
   89.50 -import java.awt.Container;
   89.51 -import java.awt.Rectangle;
   89.52 -import java.awt.event.ActionEvent;
   89.53 -import java.awt.event.ActionListener;
   89.54 -import java.io.BufferedWriter;
   89.55 -import java.io.File;
   89.56 -import java.io.FileWriter;
   89.57 -import java.io.IOException;
   89.58 -import java.util.Arrays;
   89.59 -import java.util.HashMap;
   89.60 -import java.util.HashSet;
   89.61 -import java.util.LinkedList;
   89.62 -import java.util.List;
   89.63 -import java.util.Map;
   89.64 -import java.util.Set;
   89.65 -import java.util.prefs.AbstractPreferences;
   89.66 -import java.util.prefs.BackingStoreException;
   89.67 -import java.util.prefs.Preferences;
   89.68 -import javax.swing.ComboBoxModel;
   89.69 -import javax.swing.DefaultComboBoxModel;
   89.70 -import javax.swing.JCheckBox;
   89.71 -import javax.swing.JComboBox;
   89.72 -import javax.swing.JComponent;
   89.73 -import javax.swing.JEditorPane;
   89.74 -import javax.swing.JPanel;
   89.75 -import javax.swing.JTextField;
   89.76 -import javax.swing.event.DocumentEvent;
   89.77 -import javax.swing.event.DocumentListener;
   89.78 -import javax.swing.text.BadLocationException;
   89.79 -import javax.swing.text.Document;
   89.80 -import org.netbeans.api.editor.settings.SimpleValueNames;
   89.81 -import static org.netbeans.modules.python.editor.options.CodeStyle.*;
   89.82 -import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
   89.83 -import org.netbeans.modules.options.editor.spi.PreviewProvider;
   89.84 -import org.netbeans.modules.python.api.PythonMIMEResolver;
   89.85 -import org.netbeans.modules.python.editor.PythonFormatter;
   89.86 -import org.netbeans.modules.python.editor.PythonParserResult;
   89.87 -import org.openide.cookies.SaveCookie;
   89.88 -import org.openide.filesystems.FileObject;
   89.89 -import org.openide.filesystems.FileUtil;
   89.90 -import org.openide.loaders.DataObject;
   89.91 -import org.openide.loaders.DataObjectNotFoundException;
   89.92 -import org.openide.text.CloneableEditorSupport;
   89.93 -import org.openide.util.Exceptions;
   89.94 -import org.openide.util.HelpCtx;
   89.95 -import org.openide.util.NbBundle;
   89.96 -
   89.97 -/**
   89.98 - *
   89.99 - * @author phrebejk
  89.100 - */
  89.101 -public class FmtOptions {
  89.102 -    public static final String expandTabToSpaces = SimpleValueNames.EXPAND_TABS;
  89.103 -    public static final String tabSize = SimpleValueNames.TAB_SIZE;
  89.104 -    public static final String spacesPerTab = SimpleValueNames.SPACES_PER_TAB;
  89.105 -    public static final String indentSize = SimpleValueNames.INDENT_SHIFT_WIDTH;
  89.106 -    public static final String continuationIndentSize = "continuationIndentSize"; //NOI18N
  89.107 -    public static final String labelIndent = "labelIndent"; //NOI18N
  89.108 -    public static final String absoluteLabelIndent = "absoluteLabelIndent"; //NOI18N
  89.109 -    public static final String indentTopLevelClassMembers = "indentTopLevelClassMembers"; //NOI18N
  89.110 -    public static final String indentCasesFromSwitch = "indentCasesFromSwitch"; //NOI18N
  89.111 -    public static final String rightMargin = SimpleValueNames.TEXT_LIMIT_WIDTH;
  89.112 -
  89.113 -    /*
  89.114 -    public static final String addLeadingStarInComment = "addLeadingStarInComment"; //NOI18N
  89.115 -
  89.116 -    public static final String preferLongerNames = "preferLongerNames"; //NOI18N
  89.117 -    public static final String fieldNamePrefix = "fieldNamePrefix"; //NOI18N
  89.118 -    public static final String fieldNameSuffix = "fieldNameSuffix"; //NOI18N
  89.119 -    public static final String staticFieldNamePrefix = "staticFieldNamePrefix"; //NOI18N
  89.120 -    public static final String staticFieldNameSuffix = "staticFieldNameSuffix"; //NOI18N
  89.121 -    public static final String parameterNamePrefix = "parameterNamePrefix"; //NOI18N
  89.122 -    public static final String parameterNameSuffix = "parameterNameSuffix"; //NOI18N
  89.123 -    public static final String localVarNamePrefix = "localVarNamePrefix"; //NOI18N
  89.124 -    public static final String localVarNameSuffix = "localVarNameSuffix"; //NOI18N
  89.125 -    public static final String qualifyFieldAccess = "qualifyFieldAccess"; //NOI18N
  89.126 -    public static final String useIsForBooleanGetters = "useIsForBooleanGetters"; //NOI18N
  89.127 -    public static final String addOverrideAnnotation = "addOverrideAnnotation"; //NOI18N
  89.128 -    public static final String makeLocalVarsFinal = "makeLocalVarsFinal"; //NOI18N
  89.129 -    public static final String makeParametersFinal = "makeParametersFinal"; //NOI18N
  89.130 -    public static final String classMembersOrder = "classMembersOrder"; //NOI18N
  89.131 -    
  89.132 -    public static final String alignMultilineMethodParams = "alignMultilineMethodParams"; //NOI18N
  89.133 -    public static final String alignMultilineCallArgs = "alignMultilineCallArgs"; //NOI18N
  89.134 -    public static final String alignMultilineAnnotationArgs = "alignMultilineAnnotationArgs"; //NOI18N
  89.135 -    public static final String alignMultilineImplements = "alignMultilineImplements"; //NOI18N
  89.136 -    public static final String alignMultilineThrows = "alignMultilineThrows"; //NOI18N
  89.137 -    public static final String alignMultilineParenthesized = "alignMultilineParenthesized"; //NOI18N
  89.138 -    public static final String alignMultilineBinaryOp = "alignMultilineBinaryOp"; //NOI18N
  89.139 -    public static final String alignMultilineTernaryOp = "alignMultilineTernaryOp"; //NOI18N
  89.140 -    public static final String alignMultilineAssignment = "alignMultilineAssignment"; //NOI18N
  89.141 -    public static final String alignMultilineFor = "alignMultilineFor"; //NOI18N
  89.142 -    public static final String alignMultilineArrayInit = "alignMultilineArrayInit"; //NOI18N
  89.143 -    public static final String placeElseOnNewLine = "placeElseOnNewLine"; //NOI18N
  89.144 -    public static final String placeWhileOnNewLine = "placeWhileOnNewLine"; //NOI18N
  89.145 -    public static final String placeCatchOnNewLine = "placeCatchOnNewLine"; //NOI18N
  89.146 -    public static final String placeFinallyOnNewLine = "placeFinallyOnNewLine"; //NOI18N
  89.147 -    public static final String placeNewLineAfterModifiers = "placeNewLineAfterModifiers"; //NOI18N
  89.148 -    
  89.149 -    public static final String wrapExtendsImplementsKeyword = "wrapExtendsImplementsKeyword"; //NOI18N
  89.150 -    public static final String wrapExtendsImplementsList = "wrapExtendsImplementsList"; //NOI18N
  89.151 -    public static final String wrapMethodParams = "wrapMethodParams"; //NOI18N
  89.152 -    public static final String wrapThrowsKeyword = "wrapThrowsKeyword"; //NOI18N
  89.153 -    public static final String wrapThrowsList = "wrapThrowsList"; //NOI18N
  89.154 -    public static final String wrapMethodCallArgs = "wrapMethodCallArgs"; //NOI18N
  89.155 -    public static final String wrapAnnotationArgs = "wrapAnnotationArgs"; //NOI18N
  89.156 -    public static final String wrapChainedMethodCalls = "wrapChainedMethodCalls"; //NOI18N
  89.157 -    public static final String wrapArrayInit = "wrapArrayInit"; //NOI18N
  89.158 -    public static final String wrapFor = "wrapFor"; //NOI18N
  89.159 -    public static final String wrapForStatement = "wrapForStatement"; //NOI18N
  89.160 -    public static final String wrapIfStatement = "wrapIfStatement"; //NOI18N
  89.161 -    public static final String wrapWhileStatement = "wrapWhileStatement"; //NOI18N
  89.162 -    public static final String wrapDoWhileStatement = "wrapDoWhileStatement"; //NOI18N
  89.163 -    public static final String wrapAssert = "wrapAssert"; //NOI18N
  89.164 -    public static final String wrapEnumConstants = "wrapEnumConstants"; //NOI18N
  89.165 -    public static final String wrapAnnotations = "wrapAnnotations"; //NOI18N
  89.166 -    public static final String wrapBinaryOps = "wrapBinaryOps"; //NOI18N
  89.167 -    public static final String wrapTernaryOps = "wrapTernaryOps"; //NOI18N
  89.168 -    public static final String wrapAssignOps = "wrapAssignOps"; //NOI18N
  89.169 -    
  89.170 -    public static final String blankLinesBeforePackage = "blankLinesBeforePackage"; //NOI18N
  89.171 -    public static final String blankLinesAfterPackage = "blankLinesAfterPackage"; //NOI18N
  89.172 -    public static final String blankLinesBeforeImports = "blankLinesBeforeImports"; //NOI18N
  89.173 -    public static final String blankLinesAfterImports = "blankLinesAfterImports"; //NOI18N
  89.174 -    public static final String blankLinesBeforeClass = "blankLinesBeforeClass"; //NOI18N
  89.175 -    public static final String blankLinesAfterClass = "blankLinesAfterClass"; //NOI18N
  89.176 -    public static final String blankLinesAfterClassHeader = "blankLinesAfterClassHeader"; //NOI18N
  89.177 -    public static final String blankLinesBeforeFields = "blankLinesBeforeFields"; //NOI18N
  89.178 -    public static final String blankLinesAfterFields = "blankLinesAfterFields"; //NOI18N
  89.179 -    public static final String blankLinesBeforeMethods = "blankLinesBeforeMethods"; //NOI18N
  89.180 -    public static final String blankLinesAfterMethods = "blankLinesAfterMethods"; //NOI18N
  89.181 -    
  89.182 -    public static final String spaceBeforeWhile = "spaceBeforeWhile"; //NOI18N
  89.183 -    public static final String spaceBeforeElse = "spaceBeforeElse"; //NOI18N
  89.184 -    public static final String spaceBeforeCatch = "spaceBeforeCatch"; //NOI18N
  89.185 -    public static final String spaceBeforeFinally = "spaceBeforeFinally"; //NOI18N
  89.186 -    public static final String spaceBeforeMethodDeclParen = "spaceBeforeMethodDeclParen"; //NOI18N
  89.187 -    public static final String spaceBeforeMethodCallParen = "spaceBeforeMethodCallParen"; //NOI18N
  89.188 -    public static final String spaceBeforeIfParen = "spaceBeforeIfParen"; //NOI18N
  89.189 -    public static final String spaceBeforeForParen = "spaceBeforeForParen"; //NOI18N
  89.190 -    public static final String spaceBeforeWhileParen = "spaceBeforeWhileParen"; //NOI18N
  89.191 -    public static final String spaceBeforeCatchParen = "spaceBeforeCatchParen"; //NOI18N
  89.192 -    public static final String spaceBeforeSwitchParen = "spaceBeforeSwitchParen"; //NOI18N
  89.193 -    public static final String spaceBeforeSynchronizedParen = "spaceBeforeSynchronizedParen"; //NOI18N
  89.194 -    public static final String spaceBeforeAnnotationParen = "spaceBeforeAnnotationParen"; //NOI18N    
  89.195 -    public static final String spaceAroundUnaryOps = "spaceAroundUnaryOps"; //NOI18N
  89.196 -    public static final String spaceAroundBinaryOps = "spaceAroundBinaryOps"; //NOI18N
  89.197 -    public static final String spaceAroundTernaryOps = "spaceAroundTernaryOps"; //NOI18N
  89.198 -    public static final String spaceAroundAssignOps = "spaceAroundAssignOps"; //NOI18N
  89.199 -    public static final String spaceBeforeClassDeclLeftBrace = "spaceBeforeClassDeclLeftBrace"; //NOI18N
  89.200 -    public static final String spaceBeforeMethodDeclLeftBrace = "spaceBeforeMethodDeclLeftBrace"; //NOI18N
  89.201 -    public static final String spaceBeforeIfLeftBrace = "spaceBeforeIfLeftBrace"; //NOI18N
  89.202 -    public static final String spaceBeforeElseLeftBrace = "spaceBeforeElseLeftBrace"; //NOI18N
  89.203 -    public static final String spaceBeforeWhileLeftBrace = "spaceBeforeWhileLeftBrace"; //NOI18N
  89.204 -    public static final String spaceBeforeForLeftBrace = "spaceBeforeForLeftBrace"; //NOI18N
  89.205 -    public static final String spaceBeforeDoLeftBrace = "spaceBeforeDoLeftBrace"; //NOI18N
  89.206 -    public static final String spaceBeforeSwitchLeftBrace = "spaceBeforeSwitchLeftBrace"; //NOI18N
  89.207 -    public static final String spaceBeforeTryLeftBrace = "spaceBeforeTryLeftBrace"; //NOI18N
  89.208 -    public static final String spaceBeforeCatchLeftBrace = "spaceBeforeCatchLeftBrace"; //NOI18N
  89.209 -    public static final String spaceBeforeFinallyLeftBrace = "spaceBeforeFinallyLeftBrace"; //NOI18N
  89.210 -    public static final String spaceBeforeSynchronizedLeftBrace = "spaceBeforeSynchronizedLeftBrace"; //NOI18N
  89.211 -    public static final String spaceBeforeStaticInitLeftBrace = "spaceBeforeStaticInitLeftBrace"; //NOI18N
  89.212 -    public static final String spaceBeforeArrayInitLeftBrace = "spaceBeforeArrayInitLeftBrace"; //NOI18N
  89.213 -    public static final String spaceWithinParens = "spaceWithinParens"; //NOI18N
  89.214 -    public static final String spaceWithinMethodDeclParens = "spaceWithinMethodDeclParens"; //NOI18N
  89.215 -    public static final String spaceWithinMethodCallParens = "spaceWithinMethodCallParens"; //NOI18N
  89.216 -    public static final String spaceWithinIfParens = "spaceWithinIfParens"; //NOI18N
  89.217 -    public static final String spaceWithinForParens = "spaceWithinForParens"; //NOI18N
  89.218 -    public static final String spaceWithinWhileParens = "spaceWithinWhileParens"; //NOI18N
  89.219 -    public static final String spaceWithinSwitchParens = "spaceWithinSwitchParens"; //NOI18N
  89.220 -    public static final String spaceWithinCatchParens = "spaceWithinCatchParens"; //NOI18N
  89.221 -    public static final String spaceWithinSynchronizedParens = "spaceWithinSynchronizedParens"; //NOI18N
  89.222 -    public static final String spaceWithinTypeCastParens = "spaceWithinTypeCastParens"; //NOI18N
  89.223 -    public static final String spaceWithinAnnotationParens = "spaceWithinAnnotationParens"; //NOI18N
  89.224 -    public static final String spaceWithinBraces = "spaceWithinBraces"; //NOI18N
  89.225 -    public static final String spaceWithinArrayInitBrackets = "spaceWithinArrayInitBrackets"; //NOI18N
  89.226 -    public static final String spaceBeforeComma = "spaceBeforeComma"; //NOI18N
  89.227 -    public static final String spaceAfterComma = "spaceAfterComma"; //NOI18N
  89.228 -    public static final String spaceBeforeSemi = "spaceBeforeSemi"; //NOI18N
  89.229 -    public static final String spaceAfterSemi = "spaceAfterSemi"; //NOI18N
  89.230 -    public static final String spaceBeforeColon = "spaceBeforeColon"; //NOI18N
  89.231 -    public static final String spaceAfterColon = "spaceAfterColon"; //NOI18N
  89.232 -    public static final String spaceAfterTypeCast = "spaceAfterTypeCast"; //NOI18N
  89.233 -     */
  89.234 -
  89.235 -    // Spaces
  89.236 -    public static final String addSpaceAroundOperators = "spaceAroundOperators"; //NOI18N
  89.237 -    public static final String removeSpaceInParens = "spaceInsideParens"; //NOI18N
  89.238 -    public static final String addSpaceAfterComma = "spaceAfterComma"; //NOI18N
  89.239 -    public static final String removeSpaceBeforeSep = "spaceBeforeSeparator"; //NOI18N
  89.240 -    public static final String removeSpaceInParamAssign = "spaceInKeywordAssign"; //NOI18N
  89.241 -    public static final String collapseSpaces = "collapseSpaces"; //NOI18N
  89.242 -    // Imports
  89.243 -    public static final String formatImports = "formatImports"; //NOI18N
  89.244 -    public static final String oneImportPerLine = "oneImportPerLine"; //NOI18N
  89.245 -    public static final String removeDuplicates = "removeDuplicates"; //NOI18N
  89.246 -    public static final String systemLibsFirst = "systemLibsFirst"; //NOI18N
  89.247 -    public static final String cleanupUnusedImports = "cleanupUnusedImports"; //NOI18N
  89.248 -    public static final String preferSymbolImports = "preferSymbolImports"; //NOI18N
  89.249 -    public static final String sortImports = "sortImports"; //NOI18N
  89.250 -    public static final String separateFromImps = "separateFromImps"; //NOI18N
  89.251 -    public static CodeStyleProducer codeStyleProducer;
  89.252 -    static final String CODE_STYLE_PROFILE = "CodeStyle"; // NOI18N
  89.253 -    static final String DEFAULT_PROFILE = "default"; // NOI18N
  89.254 -    static final String PROJECT_PROFILE = "project"; // NOI18N
  89.255 -    static final String usedProfile = "usedProfile"; // NOI18N
  89.256 -
  89.257 -    private FmtOptions() {
  89.258 -    }
  89.259 -
  89.260 -    public static int getDefaultAsInt(String key) {
  89.261 -        return Integer.parseInt(defaults.get(key));
  89.262 -    }
  89.263 -
  89.264 -    public static boolean getDefaultAsBoolean(String key) {
  89.265 -        return Boolean.parseBoolean(defaults.get(key));
  89.266 -    }
  89.267 -
  89.268 -    public static String getDefaultAsString(String key) {
  89.269 -        return defaults.get(key);
  89.270 -    }
  89.271 -
  89.272 -    public static boolean isInteger(String optionID) {
  89.273 -        String value = defaults.get(optionID);
  89.274 -
  89.275 -        try {
  89.276 -            Integer.parseInt(value);
  89.277 -            return true;
  89.278 -        } catch (NumberFormatException numberFormatException) {
  89.279 -            return false;
  89.280 -        }
  89.281 -    }
  89.282 -    // Private section ---------------------------------------------------------
  89.283 -    private static final String TRUE = "true";      // NOI18N
  89.284 -    private static final String FALSE = "false";    // NOI18N
  89.285 -    private static final String WRAP_ALWAYS = WrapStyle.WRAP_ALWAYS.name();
  89.286 -    //private static final String WRAP_IF_LONG  = WrapStyle.WRAP_IF_LONG.name();
  89.287 -    private static final String WRAP_NEVER = WrapStyle.WRAP_NEVER.name();
  89.288 -
  89.289 -    //private static final String CLEANUP_COMMENT  = ImportCleanupStyle.COMMENT_OUT.name();
  89.290 -    private static final String IMP_LEAVE_ALONE = ImportCleanupStyle.LEAVE_ALONE.name();
  89.291 -    private static Map<String, String> defaults;
  89.292 -
  89.293 -
  89.294 -    static {
  89.295 -        createDefaults();
  89.296 -    }
  89.297 -
  89.298 -    private static void createDefaults() {
  89.299 -        String defaultValues[][] = {
  89.300 -            {expandTabToSpaces, TRUE}, //NOI18N
  89.301 -            {tabSize, "4"}, //NOI18N
  89.302 -            {spacesPerTab, "4"}, //NOI18N
  89.303 -            {indentSize, "4"}, //NOI18N
  89.304 -            {continuationIndentSize, "8"}, //NOI18N
  89.305 -            {labelIndent, "0"}, //NOI18N
  89.306 -            {absoluteLabelIndent, FALSE}, //NOI18N
  89.307 -            {indentTopLevelClassMembers, TRUE}, //NOI18N
  89.308 -            {indentCasesFromSwitch, TRUE}, //NOI18N
  89.309 -            {rightMargin, "80"}, //NOI18N
  89.310 -
  89.311 -            /*
  89.312 -            { addLeadingStarInComment, TRUE}, //NOI18N
  89.313 -
  89.314 -            { preferLongerNames, TRUE}, //NOI18N
  89.315 -            { fieldNamePrefix, ""}, //NOI18N // XXX null
  89.316 -            { fieldNameSuffix, ""}, //NOI18N // XXX null
  89.317 -            { staticFieldNamePrefix, ""}, //NOI18N // XXX null
  89.318 -            { staticFieldNameSuffix, ""}, //NOI18N // XXX null
  89.319 -            { parameterNamePrefix, ""}, //NOI18N // XXX null
  89.320 -            { parameterNameSuffix, ""}, //NOI18N // XXX null
  89.321 -            { localVarNamePrefix, ""}, //NOI18N // XXX null
  89.322 -            { localVarNameSuffix, ""}, //NOI18N // XXX null
  89.323 -            { qualifyFieldAccess, FALSE}, //NOI18N // XXX
  89.324 -            { useIsForBooleanGetters, TRUE}, //NOI18N
  89.325 -            { addOverrideAnnotation, TRUE}, //NOI18N
  89.326 -            { makeLocalVarsFinal, FALSE}, //NOI18N
  89.327 -            { makeParametersFinal, FALSE}, //NOI18N
  89.328 -            { classMembersOrder, ""}, //NOI18N // XXX
  89.329 -
  89.330 -            { alignMultilineMethodParams, FALSE}, //NOI18N
  89.331 -            { alignMultilineCallArgs, FALSE}, //NOI18N
  89.332 -            { alignMultilineAnnotationArgs, FALSE}, //NOI18N
  89.333 -            { alignMultilineImplements, FALSE}, //NOI18N
  89.334 -            { alignMultilineThrows, FALSE}, //NOI18N
  89.335 -            { alignMultilineParenthesized, FALSE}, //NOI18N
  89.336 -            { alignMultilineBinaryOp, FALSE}, //NOI18N
  89.337 -            { alignMultilineTernaryOp, FALSE}, //NOI18N
  89.338 -            { alignMultilineAssignment, FALSE}, //NOI18N
  89.339 -            { alignMultilineFor, FALSE}, //NOI18N
  89.340 -            { alignMultilineArrayInit, FALSE}, //NOI18N
  89.341 -            { placeElseOnNewLine, FALSE}, //NOI18N 
  89.342 -            { placeWhileOnNewLine, FALSE}, //NOI18N
  89.343 -            { placeCatchOnNewLine, FALSE}, //NOI18N 
  89.344 -            { placeFinallyOnNewLine, FALSE}, //NOI18N 
  89.345 -            { placeNewLineAfterModifiers, FALSE}, //NOI18N
  89.346 -
  89.347 -            { wrapExtendsImplementsKeyword, WRAP_NEVER}, //NOI18N
  89.348 -            { wrapExtendsImplementsList, WRAP_NEVER}, //NOI18N
  89.349 -            { wrapMethodParams, WRAP_NEVER}, //NOI18N
  89.350 -            { wrapThrowsKeyword, WRAP_NEVER}, //NOI18N
  89.351 -            { wrapThrowsList, WRAP_NEVER}, //NOI18N
  89.352 -            { wrapMethodCallArgs, WRAP_NEVER}, //NOI18N
  89.353 -            { wrapAnnotationArgs, WRAP_NEVER}, //NOI18N
  89.354 -            { wrapChainedMethodCalls, WRAP_NEVER}, //NOI18N
  89.355 -            { wrapArrayInit, WRAP_NEVER}, //NOI18N
  89.356 -            { wrapFor, WRAP_NEVER}, //NOI18N
  89.357 -            { wrapForStatement, WRAP_ALWAYS}, //NOI18N
  89.358 -            { wrapIfStatement, WRAP_ALWAYS}, //NOI18N
  89.359 -            { wrapWhileStatement, WRAP_ALWAYS}, //NOI18N
  89.360 -            { wrapDoWhileStatement, WRAP_ALWAYS}, //NOI18N
  89.361 -            { wrapAssert, WRAP_NEVER}, //NOI18N
  89.362 -            { wrapEnumConstants, WRAP_NEVER}, //NOI18N
  89.363 -            { wrapAnnotations, WRAP_ALWAYS}, //NOI18N
  89.364 -            { wrapBinaryOps, WRAP_NEVER}, //NOI18N
  89.365 -            { wrapTernaryOps, WRAP_NEVER}, //NOI18N
  89.366 -            { wrapAssignOps, WRAP_NEVER}, //NOI18N
  89.367 -
  89.368 -            { blankLinesBeforePackage, "0"}, //NOI18N
  89.369 -            { blankLinesAfterPackage, "1"}, //NOI18N
  89.370 -            { blankLinesBeforeImports, "1"}, //NOI18N 
  89.371 -            { blankLinesAfterImports, "1"}, //NOI18N
  89.372 -            { blankLinesBeforeClass, "1"}, //NOI18N 
  89.373 -            { blankLinesAfterClass, "0"}, //NOI18N
  89.374 -            { blankLinesAfterClassHeader, "1"}, //NOI18N 
  89.375 -            { blankLinesBeforeFields, "0"}, //NOI18N 
  89.376 -            { blankLinesAfterFields, "0"}, //NOI18N
  89.377 -            { blankLinesBeforeMethods, "1"}, //NOI18N
  89.378 -            { blankLinesAfterMethods, "0"}, //NOI18N
  89.379 -
  89.380 -            { spaceBeforeWhile, TRUE}, //NOI18N // XXX
  89.381 -            { spaceBeforeElse, TRUE}, //NOI18N // XXX
  89.382 -            { spaceBeforeCatch, TRUE}, //NOI18N // XXX
  89.383 -            { spaceBeforeFinally, TRUE}, //NOI18N // XXX
  89.384 -            { spaceBeforeMethodDeclParen, FALSE}, //NOI18N
  89.385 -            { spaceBeforeMethodCallParen, FALSE}, //NOI18N
  89.386 -            { spaceBeforeIfParen, TRUE}, //NOI18N
  89.387 -            { spaceBeforeForParen, TRUE}, //NOI18N
  89.388 -            { spaceBeforeWhileParen, TRUE}, //NOI18N
  89.389 -            { spaceBeforeCatchParen, TRUE}, //NOI18N
  89.390 -            { spaceBeforeSwitchParen, TRUE}, //NOI18N
  89.391 -            { spaceBeforeSynchronizedParen, TRUE}, //NOI18N
  89.392 -            { spaceBeforeAnnotationParen, FALSE}, //NOI18N    
  89.393 -            { spaceAroundUnaryOps, FALSE}, //NOI18N
  89.394 -            { spaceAroundBinaryOps, TRUE}, //NOI18N
  89.395 -            { spaceAroundTernaryOps, TRUE}, //NOI18N
  89.396 -            { spaceAroundAssignOps, TRUE}, //NOI18N
  89.397 -            { spaceBeforeClassDeclLeftBrace, TRUE}, //NOI18N
  89.398 -            { spaceBeforeMethodDeclLeftBrace, TRUE}, //NOI18N
  89.399 -            { spaceBeforeIfLeftBrace, TRUE}, //NOI18N
  89.400 -            { spaceBeforeElseLeftBrace, TRUE}, //NOI18N
  89.401 -            { spaceBeforeWhileLeftBrace, TRUE}, //NOI18N
  89.402 -            { spaceBeforeForLeftBrace, TRUE}, //NOI18N
  89.403 -            { spaceBeforeDoLeftBrace, TRUE}, //NOI18N
  89.404 -            { spaceBeforeSwitchLeftBrace, TRUE}, //NOI18N
  89.405 -            { spaceBeforeTryLeftBrace, TRUE}, //NOI18N
  89.406 -            { spaceBeforeCatchLeftBrace, TRUE}, //NOI18N
  89.407 -            { spaceBeforeFinallyLeftBrace, TRUE}, //NOI18N
  89.408 -            { spaceBeforeSynchronizedLeftBrace, TRUE}, //NOI18N
  89.409 -            { spaceBeforeStaticInitLeftBrace, TRUE}, //NOI18N
  89.410 -            { spaceBeforeArrayInitLeftBrace, FALSE}, //NOI18N
  89.411 -            { spaceWithinParens, FALSE}, //NOI18N
  89.412 -            { spaceWithinMethodDeclParens, FALSE}, //NOI18N
  89.413 -            { spaceWithinMethodCallParens, FALSE}, //NOI18N
  89.414 -            { spaceWithinIfParens, FALSE}, //NOI18N
  89.415 -            { spaceWithinForParens, FALSE}, //NOI18N
  89.416 -            { spaceWithinWhileParens, FALSE}, //NOI18N
  89.417 -            { spaceWithinSwitchParens, FALSE}, //NOI18N
  89.418 -            { spaceWithinCatchParens, FALSE}, //NOI18N
  89.419 -            { spaceWithinSynchronizedParens, FALSE}, //NOI18N
  89.420 -            { spaceWithinTypeCastParens, FALSE}, //NOI18N
  89.421 -            { spaceWithinAnnotationParens, FALSE}, //NOI18N
  89.422 -            { spaceWithinBraces, FALSE}, //NOI18N
  89.423 -            { spaceWithinArrayInitBrackets, FALSE}, //NOI18N
  89.424 -            { spaceBeforeComma, FALSE}, //NOI18N
  89.425 -            { spaceAfterComma, TRUE}, //NOI18N
  89.426 -            { spaceBeforeSemi, FALSE}, //NOI18N
  89.427 -            { spaceAfterSemi, TRUE}, //NOI18N
  89.428 -            { spaceBeforeColon, TRUE}, //NOI18N
  89.429 -            { spaceAfterColon, TRUE}, //NOI18N
  89.430 -            { spaceAfterTypeCast, TRUE}, //NOI18N
  89.431 -             */
  89.432 -            // Spaces
  89.433 -            {addSpaceAroundOperators, TRUE},
  89.434 -            {removeSpaceInParens, TRUE},
  89.435 -            {addSpaceAfterComma, TRUE},
  89.436 -            {removeSpaceBeforeSep, TRUE},
  89.437 -            {removeSpaceInParamAssign, TRUE},
  89.438 -            {collapseSpaces, TRUE},
  89.439 -            // Imports
  89.440 -            {formatImports, TRUE},
  89.441 -            {oneImportPerLine, TRUE},
  89.442 -            {removeDuplicates, TRUE},
  89.443 -            {systemLibsFirst, TRUE},
  89.444 -            {preferSymbolImports, TRUE},
  89.445 -            {sortImports, TRUE},
  89.446 -            {cleanupUnusedImports, IMP_LEAVE_ALONE},
  89.447 -            {separateFromImps, FALSE},};
  89.448 -
  89.449 -        defaults = new HashMap<>();
  89.450 -
  89.451 -        for (java.lang.String[] strings : defaultValues) {
  89.452 -            defaults.put(strings[0], strings[1]);
  89.453 -        }
  89.454 -
  89.455 -    }
  89.456 -
  89.457 -    // Support section ---------------------------------------------------------
  89.458 -    public static class CategorySupport implements ActionListener, DocumentListener, PreviewProvider, PreferencesCustomizer {
  89.459 -        public static final String OPTION_ID = "org.netbeans.modules.python.editor.options.FormatingOptions.ID";
  89.460 -        private static final int LOAD = 0;
  89.461 -        private static final int STORE = 1;
  89.462 -        private static final int ADD_LISTENERS = 2;
  89.463 -        private static final ComboItem wrap[] = new ComboItem[]{
  89.464 -            new ComboItem(WrapStyle.WRAP_ALWAYS.name(), "LBL_wrp_WRAP_ALWAYS"), // NOI18N
  89.465 -            new ComboItem(WrapStyle.WRAP_IF_LONG.name(), "LBL_wrp_WRAP_IF_LONG"), // NOI18N
  89.466 -            new ComboItem(WrapStyle.WRAP_NEVER.name(), "LBL_wrp_WRAP_NEVER") // NOI18N
  89.467 -        };
  89.468 -        private static final ComboItem cleanupImports[] = new ComboItem[]{
  89.469 -            new ComboItem(ImportCleanupStyle.LEAVE_ALONE.name(), "LBL_imp_LEAVE_ALONE"), // NOI18N
  89.470 -            new ComboItem(ImportCleanupStyle.COMMENT_OUT.name(), "LBL_imp_COMMENT_OUT"), // NOI18N
  89.471 -            new ComboItem(ImportCleanupStyle.DELETE.name(), "LBL_imp_DELETE") // NOI18N
  89.472 -        };
  89.473 -        private final String previewText;
  89.474 -        private final String id;
  89.475 -        protected final JPanel panel;
  89.476 -        private final List<JComponent> components = new LinkedList<>();
  89.477 -        private JEditorPane previewPane;
  89.478 -        private final Preferences preferences;
  89.479 -        private final Preferences previewPrefs;
  89.480 -
  89.481 -        protected CategorySupport(Preferences preferences, String id, JPanel panel, String previewText, String[]... forcedOptions) {
  89.482 -            this.preferences = preferences;
  89.483 -            this.id = id;
  89.484 -            this.panel = panel;
  89.485 -            this.previewText = previewText != null ? previewText : NbBundle.getMessage(FmtOptions.class, "SAMPLE_Default"); //NOI18N
  89.486 -
  89.487 -            // Scan the panel for its components
  89.488 -            scan(panel, components);
  89.489 -
  89.490 -            // Initialize the preview preferences
  89.491 -            Preferences forcedPrefs = new PreviewPreferences();
  89.492 -            for (String[] option : forcedOptions) {
  89.493 -                forcedPrefs.put(option[0], option[1]);
  89.494 -            }
  89.495 -            this.previewPrefs = new ProxyPreferences(preferences, forcedPrefs);
  89.496 -
  89.497 -            // Load and hook up all the components
  89.498 -            loadFrom(preferences);
  89.499 -            addListeners();
  89.500 -        }
  89.501 -
  89.502 -        protected void addListeners() {
  89.503 -            scan(ADD_LISTENERS, null);
  89.504 -        }
  89.505 -
  89.506 -        protected void loadFrom(Preferences preferences) {
  89.507 -//            loaded = true;
  89.508 -            scan(LOAD, preferences);
  89.509 -//            loaded = false;
  89.510 -        }
  89.511 -//
  89.512 -//        public void applyChanges() {
  89.513 -//            storeTo(preferences);
  89.514 -//        }
  89.515 -//
  89.516 -
  89.517 -        protected void storeTo(Preferences p) {
  89.518 -            scan(STORE, p);
  89.519 -        }
  89.520 -
  89.521 -        protected void notifyChanged() {
  89.522 -//            if (loaded)
  89.523 -//                return;
  89.524 -            storeTo(preferences);
  89.525 -            refreshPreview();
  89.526 -        }
  89.527 -
  89.528 -        // ActionListener implementation ---------------------------------------
  89.529 -        @Override
  89.530 -        public void actionPerformed(ActionEvent e) {
  89.531 -            notifyChanged();
  89.532 -        }
  89.533 -
  89.534 -        // DocumentListener implementation -------------------------------------
  89.535 -        @Override
  89.536 -        public void insertUpdate(DocumentEvent e) {
  89.537 -            notifyChanged();
  89.538 -        }
  89.539 -
  89.540 -        @Override
  89.541 -        public void removeUpdate(DocumentEvent e) {
  89.542 -            notifyChanged();
  89.543 -        }
  89.544 -
  89.545 -        @Override
  89.546 -        public void changedUpdate(DocumentEvent e) {
  89.547 -            notifyChanged();
  89.548 -        }
  89.549 -
  89.550 -        // PreviewProvider methods -----------------------------------------------------
  89.551 -        @Override
  89.552 -        public JComponent getPreviewComponent() {
  89.553 -            if (previewPane == null) {
  89.554 -                previewPane = new JEditorPane();
  89.555 -                previewPane.getAccessibleContext().setAccessibleName(NbBundle.getMessage(FmtOptions.class, "AN_Preview")); //NOI18N
  89.556 -                previewPane.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(FmtOptions.class, "AD_Preview")); //NOI18N
  89.557 -                previewPane.putClientProperty("HighlightsLayerIncludes", "^org\\.netbeans\\.modules\\.editor\\.lib2\\.highlighting\\.SyntaxHighlighting$"); //NOI18N
  89.558 -                previewPane.setEditorKit(CloneableEditorSupport.getEditorKit(PythonMIMEResolver.PYTHON_MIME_TYPE));
  89.559 -                previewPane.setEditable(false);
  89.560 -            }
  89.561 -            return previewPane;
  89.562 -        }
  89.563 -
  89.564 -        @Override
  89.565 -        public void refreshPreview() {
  89.566 -            JEditorPane jep = (JEditorPane)getPreviewComponent();
  89.567 -            try {
  89.568 -                int rm = previewPrefs.getInt(rightMargin, getDefaultAsInt(rightMargin));
  89.569 -                jep.putClientProperty("TextLimitLine", rm); //NOI18N
  89.570 -            } catch (NumberFormatException e) {
  89.571 -                // Ignore it
  89.572 -            }
  89.573 -            try {
  89.574 -                Class.forName(CodeStyle.class.getName(), true, CodeStyle.class.getClassLoader());
  89.575 -            } catch (ClassNotFoundException cnfe) {
  89.576 -                // ignore
  89.577 -            }
  89.578 -
  89.579 -            CodeStyle codeStyle = codeStyleProducer.create(previewPrefs);
  89.580 -            jep.setIgnoreRepaint(true);
  89.581 -
  89.582 -//            if (jep.getDocument() instanceof BaseDocument) {
  89.583 -//                BaseDocument document = (BaseDocument) jep.getDocument();
  89.584 -//                final org.netbeans.editor.Formatter f = document.getFormatter();
  89.585 -//                try {
  89.586 -//                    f.reformatLock();
  89.587 -//                    try {
  89.588 -//                        int reformattedLen = f.reformat(document, 0, document.getLength());
  89.589 -//                    } catch (BadLocationException ex) {
  89.590 -//                        Exceptions.printStackTrace(ex);
  89.591 -//                    }
  89.592 -//                } finally {
  89.593 -//                    f.reformatUnlock();
  89.594 -//                }
  89.595 -//            }
  89.596 -
  89.597 -            // Hacky code to do preview: We want to preview blank text without
  89.598 -            // a data object... this doesn't work very well so requires some hacks
  89.599 -            // to create a temp file, format it, then save it and delete it
  89.600 -            // (to avoid save confirmation dialogs on the modified file etc)
  89.601 -            PythonFormatter formatter = new PythonFormatter(codeStyle);
  89.602 -            PythonParserResult info = null;
  89.603 -            File tmp = null;
  89.604 -            FileObject tmpFo = null;
  89.605 -            if (formatter.needsParserResult()) {
  89.606 -                try {
  89.607 -                    tmp = File.createTempFile("preview", ".py"); // NOI18N
  89.608 -                    BufferedWriter writer = new BufferedWriter(new FileWriter(tmp));
  89.609 -                    writer.write(previewText);
  89.610 -                    writer.close();
  89.611 -                    final FileObject fo = FileUtil.toFileObject(FileUtil.normalizeFile(tmp));
  89.612 -                    tmpFo = fo;
  89.613 -                    // TODO - I need to get the classpath involved here such that it can
  89.614 -                    // find used/unused libraries
  89.615 -//                    if (!SourceUtils.isScanInProgress()) {
  89.616 -//                        // I'm using custom GSF code here because I want to set up an explicit
  89.617 -//                        // source path for the fake file object which includes the Python
  89.618 -//                        // libraries (since we need them for the isSystemModule lookup
  89.619 -//                        //SourceModel model = SourceModelFactory.getInstance().getModel(fo);
  89.620 -//                        //if (model != null && !model.isScanInProgress()) {
  89.621 -//                        List<FileObject> roots = new ArrayList<FileObject>(new PythonLanguage().getCoreLibraries());
  89.622 -//
  89.623 -//                        final PythonPlatformManager manager = PythonPlatformManager.getInstance();
  89.624 -//                        final String platformName = manager.getDefaultPlatform();
  89.625 -//                        PythonPlatform activePlatform = manager.getPlatform(platformName);
  89.626 -//                        if (activePlatform != null) {
  89.627 -//                            roots.addAll(activePlatform.getUniqueLibraryRoots());
  89.628 -//                            ClassPath boot = ClassPathSupport.createClassPath(roots.toArray(new FileObject[roots.size()]));
  89.629 -//                            ClassPath source = ClassPathSupport.createClassPath(new FileObject[]{fo.getParent()});
  89.630 -//                            ClassPath compile = source;
  89.631 -//
  89.632 -//                            ClasspathInfo cpInfo = ClasspathInfo.create(boot, compile, source);
  89.633 -//                            Source model = Source.create(cpInfo, fo);
  89.634 -//                            if (model != null) {
  89.635 -//                                final CompilationInfo[] infoHolder = new CompilationInfo[1];
  89.636 -//                                //model.runUserActionTask(new CancellableTask<CompilationInfo>() {
  89.637 -//                                model.runUserActionTask(new CancellableTask<CompilationController>() {
  89.638 -//                                    public void cancel() {
  89.639 -//                                    }
  89.640 -//
  89.641 -//                                    //public void run(CompilationInfo info) throws Exception {
  89.642 -//                                    public void run(CompilationController info) throws Exception {
  89.643 -//                                        info.toPhase(Phase.RESOLVED);
  89.644 -//                                        infoHolder[0] = info;
  89.645 -//                                        // Force open so info.getFileObject will succeed
  89.646 -//                                        GsfUtilities.getDocument(fo, true);
  89.647 -//                                    }
  89.648 -//                                }, false);
  89.649 -//                                info = infoHolder[0];
  89.650 -//                            }
  89.651 -//                        }
  89.652 -//                    }
  89.653 -                } catch (IOException ex) {
  89.654 -                    Exceptions.printStackTrace(ex);
  89.655 -                }
  89.656 -            }
  89.657 -            try {
  89.658 -                if (info != null && info.getSnapshot().getSource().getDocument(false) != null) {
  89.659 -                    Document doc = info.getSnapshot().getSource().getDocument(false);
  89.660 -                    formatter.reformat(null, doc, 0, doc.getLength(), info);
  89.661 -                    jep.setText(doc.getText(0, doc.getLength()));
  89.662 -                    // Save file to avoid warning on exit
  89.663 -                    DataObject dobj = DataObject.find(info.getSnapshot().getSource().getFileObject());
  89.664 -                    SaveCookie cookie = dobj.getCookie(SaveCookie.class);
  89.665 -                    if (cookie != null) {
  89.666 -                        cookie.save();
  89.667 -                    }
  89.668 -                } else {
  89.669 -                    Document doc = jep.getDocument();
  89.670 -                    if (doc.getLength() > 0) {
  89.671 -                        doc.remove(0, doc.getLength());
  89.672 -                    }
  89.673 -                    doc.insertString(0, previewText, null);
  89.674 -                    formatter.reformat(null, doc, 0, doc.getLength(), null);
  89.675 -                    jep.setText(doc.getText(0, doc.getLength()));
  89.676 -                }
  89.677 -            } catch (DataObjectNotFoundException dof) {
  89.678 -                Exceptions.printStackTrace(dof);
  89.679 -            } catch (IOException | BadLocationException ioe) {
  89.680 -                Exceptions.printStackTrace(ioe);
  89.681 -            }
  89.682 -
  89.683 -            if (tmpFo != null) {
  89.684 -                try {
  89.685 -                    tmpFo.delete();
  89.686 -                } catch (IOException ex) {
  89.687 -                    Exceptions.printStackTrace(ex);
  89.688 -                }
  89.689 -            } else if (tmp != null) {
  89.690 -                tmp.delete();
  89.691 -            }
  89.692 -
  89.693 -
  89.694 -            jep.setIgnoreRepaint(false);
  89.695 -            jep.scrollRectToVisible(new Rectangle(0, 0, 10, 10));
  89.696 -            jep.repaint(100);
  89.697 -        }
  89.698 -
  89.699 -        // PreferencesCustomizer implementation --------------------------------
  89.700 -        @Override
  89.701 -        public JComponent getComponent() {
  89.702 -            return panel;
  89.703 -        }
  89.704 -
  89.705 -        @Override
  89.706 -        public String getDisplayName() {
  89.707 -            return panel.getName();
  89.708 -        }
  89.709 -
  89.710 -        @Override
  89.711 -        public String getId() {
  89.712 -            return id;
  89.713 -        }
  89.714 -
  89.715 -        @Override
  89.716 -        public HelpCtx getHelpCtx() {
  89.717 -            return null;
  89.718 -        }
  89.719 -
  89.720 -        // PreferencesCustomizer.Factory implementation ------------------------
  89.721 -        public static final class Factory implements PreferencesCustomizer.Factory {
  89.722 -            private final String id;
  89.723 -            private final Class<? extends JPanel> panelClass;
  89.724 -            private final String previewText;
  89.725 -            private final String[][] forcedOptions;
  89.726 -
  89.727 -            public Factory(String id, Class<? extends JPanel> panelClass, String previewText, String[]... forcedOptions) {
  89.728 -                this.id = id;
  89.729 -                this.panelClass = panelClass;
  89.730 -                this.previewText = previewText;
  89.731 -                this.forcedOptions = forcedOptions;
  89.732 -            }
  89.733 -
  89.734 -            @Override
  89.735 -            public PreferencesCustomizer create(Preferences preferences) {
  89.736 -                try {
  89.737 -                    return new CategorySupport(preferences, id, panelClass.newInstance(), previewText, forcedOptions);
  89.738 -                } catch (IllegalAccessException | InstantiationException e) {
  89.739 -                    return null;
  89.740 -                }
  89.741 -            }
  89.742 -        } // End of CategorySupport.Factory class
  89.743 -
  89.744 -        // Private methods -----------------------------------------------------
  89.745 -        private void performOperation(int operation, JComponent jc, String optionID, Preferences p) {
  89.746 -            switch (operation) {
  89.747 -            case LOAD:
  89.748 -                loadData(jc, optionID, p);
  89.749 -                break;
  89.750 -            case STORE:
  89.751 -                storeData(jc, optionID, p);
  89.752 -                break;
  89.753 -            case ADD_LISTENERS:
  89.754 -                addListener(jc);
  89.755 -                break;
  89.756 -            }
  89.757 -        }
  89.758 -
  89.759 -        private void scan(int what, Preferences p) {
  89.760 -            for (JComponent jc : components) {
  89.761 -                Object o = jc.getClientProperty(OPTION_ID);
  89.762 -                if (o instanceof String) {
  89.763 -                    performOperation(what, jc, (String)o, p);
  89.764 -                } else if (o instanceof String[]) {
  89.765 -                    for (String oid : (String[])o) {
  89.766 -                        performOperation(what, jc, oid, p);
  89.767 -                    }
  89.768 -                }
  89.769 -            }
  89.770 -        }
  89.771 -
  89.772 -        private void scan(Container container, List<JComponent> components) {
  89.773 -            for (Component c : container.getComponents()) {
  89.774 -                if (c instanceof JComponent) {
  89.775 -                    JComponent jc = (JComponent)c;
  89.776 -                    Object o = jc.getClientProperty(OPTION_ID);
  89.777 -                    if (o instanceof String || o instanceof String[]) {
  89.778 -                        components.add(jc);
  89.779 -                    }
  89.780 -                }
  89.781 -                if (c instanceof Container) {
  89.782 -                    scan((Container)c, components);
  89.783 -                }
  89.784 -            }
  89.785 -        }
  89.786 -
  89.787 -        /** Very smart method which tries to set the values in the components correctly
  89.788 -         */
  89.789 -        private void loadData(JComponent jc, String optionID, Preferences node) {
  89.790 -
  89.791 -            if (jc instanceof JTextField) {
  89.792 -                JTextField field = (JTextField)jc;
  89.793 -                field.setText(node.get(optionID, getDefaultAsString(optionID)));
  89.794 -            } else if (jc instanceof JCheckBox) {
  89.795 -                JCheckBox checkBox = (JCheckBox)jc;
  89.796 -                boolean df = getDefaultAsBoolean(optionID);
  89.797 -                checkBox.setSelected(node.getBoolean(optionID, df));
  89.798 -            } else if (jc instanceof JComboBox) {
  89.799 -                JComboBox cb = (JComboBox)jc;
  89.800 -                String value = node.get(optionID, getDefaultAsString(optionID));
  89.801 -                ComboBoxModel model = createModel(value);
  89.802 -                cb.setModel(model);
  89.803 -                ComboItem item = whichItem(value, model);
  89.804 -                cb.setSelectedItem(item);
  89.805 -            }
  89.806 -
  89.807 -        }
  89.808 -
  89.809 -        private void storeData(JComponent jc, String optionID, Preferences node) {
  89.810 -
  89.811 -            if (jc instanceof JTextField) {
  89.812 -                JTextField field = (JTextField)jc;
  89.813 -
  89.814 -                String text = field.getText();
  89.815 -
  89.816 -                // XXX test for numbers
  89.817 -                if (isInteger(optionID)) {
  89.818 -                    try {
  89.819 -                        int i = Integer.parseInt(text);
  89.820 -                    } catch (NumberFormatException e) {
  89.821 -                        return;
  89.822 -                    }
  89.823 -                }
  89.824 -
  89.825 -                // XXX: watch out, tabSize, spacesPerTab, indentSize and expandTabToSpaces
  89.826 -                // fall back on getGlopalXXX() values and not getDefaultAsXXX value,
  89.827 -                // which is why we must not remove them. Proper solution would be to
  89.828 -                // store formatting preferences to MimeLookup and not use NbPreferences.
  89.829 -                // The problem currently is that MimeLookup based Preferences do not support subnodes.
  89.830 -                if (!optionID.equals(tabSize) &&
  89.831 -                        !optionID.equals(spacesPerTab) && !optionID.equals(indentSize) &&
  89.832 -                        getDefaultAsString(optionID).equals(text)) {
  89.833 -                    node.remove(optionID);
  89.834 -                } else {
  89.835 -                    node.put(optionID, text);
  89.836 -                }
  89.837 -            } else if (jc instanceof JCheckBox) {
  89.838 -                JCheckBox checkBox = (JCheckBox)jc;
  89.839 -                if (!optionID.equals(expandTabToSpaces) && getDefaultAsBoolean(optionID) == checkBox.isSelected()) {
  89.840 -                    node.remove(optionID);
  89.841 -                } else {
  89.842 -                    node.putBoolean(optionID, checkBox.isSelected());
  89.843 -                }
  89.844 -            } else if (jc instanceof JComboBox) {
  89.845 -                JComboBox cb = (JComboBox)jc;
  89.846 -                // Logger.global.info( cb.getSelectedItem() + " " + optionID);
  89.847 -                String value = ((ComboItem)cb.getSelectedItem()).value;
  89.848 -                if (getDefaultAsString(optionID).equals(value)) {
  89.849 -                    node.remove(optionID);
  89.850 -                } else {
  89.851 -                    node.put(optionID, value);
  89.852 -                }
  89.853 -            }
  89.854 -        }
  89.855 -
  89.856 -        private void addListener(JComponent jc) {
  89.857 -            if (jc instanceof JTextField) {
  89.858 -                JTextField field = (JTextField)jc;
  89.859 -                field.addActionListener(this);
  89.860 -                field.getDocument().addDocumentListener(this);
  89.861 -            } else if (jc instanceof JCheckBox) {
  89.862 -                JCheckBox checkBox = (JCheckBox)jc;
  89.863 -                checkBox.addActionListener(this);
  89.864 -            } else if (jc instanceof JComboBox) {
  89.865 -                JComboBox cb = (JComboBox)jc;
  89.866 -                cb.addActionListener(this);
  89.867 -            }
  89.868 -        }
  89.869 -
  89.870 -        private ComboBoxModel createModel(String value) {
  89.871 -
  89.872 -            // is it imports?
  89.873 -            for (ComboItem comboItem : cleanupImports) {
  89.874 -                if (value.equals(comboItem.value)) {
  89.875 -                    return new DefaultComboBoxModel(cleanupImports);
  89.876 -                }
  89.877 -            }
  89.878 -
  89.879 -            // is it wrap
  89.880 -            for (ComboItem comboItem : wrap) {
  89.881 -                if (value.equals(comboItem.value)) {
  89.882 -                    return new DefaultComboBoxModel(wrap);
  89.883 -                }
  89.884 -            }
  89.885 -
  89.886 -            return null;
  89.887 -        }
  89.888 -
  89.889 -        private static ComboItem whichItem(String value, ComboBoxModel model) {
  89.890 -
  89.891 -            for (int i = 0; i < model.getSize(); i++) {
  89.892 -                ComboItem item = (ComboItem)model.getElementAt(i);
  89.893 -                if (value.equals(item.value)) {
  89.894 -                    return item;
  89.895 -                }
  89.896 -            }
  89.897 -            return null;
  89.898 -        }
  89.899 -
  89.900 -        private static class ComboItem {
  89.901 -            String value;
  89.902 -            String displayName;
  89.903 -
  89.904 -            public ComboItem(String value, String key) {
  89.905 -                this.value = value;
  89.906 -                this.displayName = NbBundle.getMessage(FmtOptions.class, key);
  89.907 -            }
  89.908 -
  89.909 -            @Override
  89.910 -            public String toString() {
  89.911 -                return displayName;
  89.912 -            }
  89.913 -        }
  89.914 -    }
  89.915 -
  89.916 -    public static class PreviewPreferences extends AbstractPreferences {
  89.917 -        private Map<String, Object> map = new HashMap<>();
  89.918 -
  89.919 -        public PreviewPreferences() {
  89.920 -            super(null, ""); // NOI18N
  89.921 -        }
  89.922 -
  89.923 -        @Override
  89.924 -        protected void putSpi(String key, String value) {
  89.925 -            map.put(key, value);
  89.926 -        }
  89.927 -
  89.928 -        @Override
  89.929 -        protected String getSpi(String key) {
  89.930 -            return (String)map.get(key);
  89.931 -        }
  89.932 -
  89.933 -        @Override
  89.934 -        protected void removeSpi(String key) {
  89.935 -            map.remove(key);
  89.936 -        }
  89.937 -
  89.938 -        @Override
  89.939 -        protected void removeNodeSpi() throws BackingStoreException {
  89.940 -            throw new UnsupportedOperationException("Not supported yet.");
  89.941 -        }
  89.942 -
  89.943 -        @Override
  89.944 -        protected String[] keysSpi() throws BackingStoreException {
  89.945 -            String array[] = new String[map.keySet().size()];
  89.946 -            return map.keySet().toArray(array);
  89.947 -        }
  89.948 -
  89.949 -        @Override
  89.950 -        protected String[] childrenNamesSpi() throws BackingStoreException {
  89.951 -            throw new UnsupportedOperationException("Not supported yet.");
  89.952 -        }
  89.953 -
  89.954 -        @Override
  89.955 -        protected AbstractPreferences childSpi(String name) {
  89.956 -            throw new UnsupportedOperationException("Not supported yet.");
  89.957 -        }
  89.958 -
  89.959 -        @Override
  89.960 -        protected void syncSpi() throws BackingStoreException {
  89.961 -            throw new UnsupportedOperationException("Not supported yet.");
  89.962 -        }
  89.963 -
  89.964 -        @Override
  89.965 -        protected void flushSpi() throws BackingStoreException {
  89.966 -            throw new UnsupportedOperationException("Not supported yet.");
  89.967 -        }
  89.968 -    }
  89.969 -
  89.970 -    // read-only, no subnodes
  89.971 -    public static final class ProxyPreferences extends AbstractPreferences {
  89.972 -        private final Preferences[] delegates;
  89.973 -
  89.974 -        public ProxyPreferences(Preferences... delegates) {
  89.975 -            super(null, ""); // NOI18N
  89.976 -            this.delegates = delegates;
  89.977 -        }
  89.978 -
  89.979 -        @Override
  89.980 -        protected void putSpi(String key, String value) {
  89.981 -            throw new UnsupportedOperationException("Not supported yet.");
  89.982 -        }
  89.983 -
  89.984 -        @Override
  89.985 -        protected String getSpi(String key) {
  89.986 -            for (Preferences p : delegates) {
  89.987 -                String value = p.get(key, null);
  89.988 -                if (value != null) {
  89.989 -                    return value;
  89.990 -                }
  89.991 -            }
  89.992 -            return null;
  89.993 -        }
  89.994 -
  89.995 -        @Override
  89.996 -        protected void removeSpi(String key) {
  89.997 -            throw new UnsupportedOperationException("Not supported yet.");
  89.998 -        }
  89.999 -
 89.1000 -        @Override
 89.1001 -        protected void removeNodeSpi() throws BackingStoreException {
 89.1002 -            throw new UnsupportedOperationException("Not supported yet.");
 89.1003 -        }
 89.1004 -
 89.1005 -        @Override
 89.1006 -        protected String[] keysSpi() throws BackingStoreException {
 89.1007 -            Set<String> keys = new HashSet<>();
 89.1008 -            for (Preferences p : delegates) {
 89.1009 -                keys.addAll(Arrays.asList(p.keys()));
 89.1010 -            }
 89.1011 -            return keys.toArray(new String[keys.size()]);
 89.1012 -        }
 89.1013 -
 89.1014 -        @Override
 89.1015 -        protected String[] childrenNamesSpi() throws BackingStoreException {
 89.1016 -            throw new UnsupportedOperationException("Not supported yet.");
 89.1017 -        }
 89.1018 -
 89.1019 -        @Override
 89.1020 -        protected AbstractPreferences childSpi(String name) {
 89.1021 -            throw new UnsupportedOperationException("Not supported yet.");
 89.1022 -        }
 89.1023 -
 89.1024 -        @Override
 89.1025 -        protected void syncSpi() throws BackingStoreException {
 89.1026 -            throw new UnsupportedOperationException("Not supported yet.");
 89.1027 -        }
 89.1028 -
 89.1029 -        @Override
 89.1030 -        protected void flushSpi() throws BackingStoreException {
 89.1031 -            throw new UnsupportedOperationException("Not supported yet.");
 89.1032 -        }
 89.1033 -    } // End of ProxyPreferences class
 89.1034 -
 89.1035 -    public static interface CodeStyleProducer {
 89.1036 -        public CodeStyle create(Preferences preferences);
 89.1037 -    }
 89.1038 -}
    90.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtSpaces.form	Sat Sep 12 23:03:15 2015 -0700
    90.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.3 @@ -1,104 +0,0 @@
    90.4 -<?xml version="1.0" encoding="UTF-8" ?>
    90.5 -
    90.6 -<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    90.7 -  <Properties>
    90.8 -    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    90.9 -      <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_Spaces" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   90.10 -    </Property>
   90.11 -    <Property name="opaque" type="boolean" value="false"/>
   90.12 -  </Properties>
   90.13 -  <AuxValues>
   90.14 -    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   90.15 -    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   90.16 -    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   90.17 -    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
   90.18 -    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   90.19 -    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
   90.20 -    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
   90.21 -    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   90.22 -    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   90.23 -  </AuxValues>
   90.24 -
   90.25 -  <Layout>
   90.26 -    <DimensionLayout dim="0">
   90.27 -      <Group type="103" groupAlignment="0" attributes="0">
   90.28 -          <Group type="102" attributes="0">
   90.29 -              <Group type="103" groupAlignment="0" attributes="0">
   90.30 -                  <Component id="addAroundOp" alignment="0" min="-2" max="-2" attributes="0"/>
   90.31 -                  <Group type="102" alignment="0" attributes="0">
   90.32 -                      <EmptySpace min="27" pref="27" max="27" attributes="0"/>
   90.33 -                      <Component id="removeInParam" min="-2" max="-2" attributes="0"/>
   90.34 -                  </Group>
   90.35 -                  <Component id="removeInParen" alignment="0" min="-2" max="-2" attributes="0"/>
   90.36 -                  <Component id="addAfterComma" alignment="0" min="-2" max="-2" attributes="0"/>
   90.37 -                  <Component id="removeBeforeSep" alignment="0" min="-2" max="-2" attributes="0"/>
   90.38 -                  <Component id="collapseSpacesCb" alignment="0" min="-2" max="-2" attributes="0"/>
   90.39 -              </Group>
   90.40 -              <EmptySpace max="32767" attributes="0"/>
   90.41 -          </Group>
   90.42 -      </Group>
   90.43 -    </DimensionLayout>
   90.44 -    <DimensionLayout dim="1">
   90.45 -      <Group type="103" groupAlignment="0" attributes="0">
   90.46 -          <Group type="102" alignment="0" attributes="0">
   90.47 -              <Component id="addAroundOp" min="-2" max="-2" attributes="0"/>
   90.48 -              <EmptySpace max="-2" attributes="0"/>
   90.49 -              <Component id="removeInParam" min="-2" max="-2" attributes="0"/>
   90.50 -              <EmptySpace max="-2" attributes="0"/>
   90.51 -              <Component id="removeInParen" min="-2" max="-2" attributes="0"/>
   90.52 -              <EmptySpace max="-2" attributes="0"/>
   90.53 -              <Component id="addAfterComma" min="-2" max="-2" attributes="0"/>
   90.54 -              <EmptySpace max="-2" attributes="0"/>
   90.55 -              <Component id="removeBeforeSep" min="-2" max="-2" attributes="0"/>
   90.56 -              <EmptySpace max="-2" attributes="0"/>
   90.57 -              <Component id="collapseSpacesCb" min="-2" max="-2" attributes="0"/>
   90.58 -              <EmptySpace max="32767" attributes="0"/>
   90.59 -          </Group>
   90.60 -      </Group>
   90.61 -    </DimensionLayout>
   90.62 -  </Layout>
   90.63 -  <SubComponents>
   90.64 -    <Component class="javax.swing.JCheckBox" name="addAroundOp">
   90.65 -      <Properties>
   90.66 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   90.67 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtSpaces.addAroundOp.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   90.68 -        </Property>
   90.69 -      </Properties>
   90.70 -    </Component>
   90.71 -    <Component class="javax.swing.JCheckBox" name="removeInParam">
   90.72 -      <Properties>
   90.73 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   90.74 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtSpaces.removeInParam.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   90.75 -        </Property>
   90.76 -      </Properties>
   90.77 -    </Component>
   90.78 -    <Component class="javax.swing.JCheckBox" name="removeInParen">
   90.79 -      <Properties>
   90.80 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   90.81 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtSpaces.removeInParen.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   90.82 -        </Property>
   90.83 -      </Properties>
   90.84 -    </Component>
   90.85 -    <Component class="javax.swing.JCheckBox" name="addAfterComma">
   90.86 -      <Properties>
   90.87 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   90.88 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtSpaces.addAfterComma.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   90.89 -        </Property>
   90.90 -      </Properties>
   90.91 -    </Component>
   90.92 -    <Component class="javax.swing.JCheckBox" name="removeBeforeSep">
   90.93 -      <Properties>
   90.94 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   90.95 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtSpaces.removeBeforeSep.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   90.96 -        </Property>
   90.97 -      </Properties>
   90.98 -    </Component>
   90.99 -    <Component class="javax.swing.JCheckBox" name="collapseSpacesCb">
  90.100 -      <Properties>
  90.101 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  90.102 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtSpaces.collapseSpacesCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  90.103 -        </Property>
  90.104 -      </Properties>
  90.105 -    </Component>
  90.106 -  </SubComponents>
  90.107 -</Form>
    91.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtSpaces.java	Sat Sep 12 23:03:15 2015 -0700
    91.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.3 @@ -1,143 +0,0 @@
    91.4 -/*
    91.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    91.6 - *
    91.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    91.8 - *
    91.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   91.10 - * Other names may be trademarks of their respective owners.
   91.11 - *
   91.12 - * The contents of this file are subject to the terms of either the GNU
   91.13 - * General Public License Version 2 only ("GPL") or the Common
   91.14 - * Development and Distribution License("CDDL") (collectively, the
   91.15 - * "License"). You may not use this file except in compliance with the
   91.16 - * License. You can obtain a copy of the License at
   91.17 - * http://www.netbeans.org/cddl-gplv2.html
   91.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   91.19 - * specific language governing permissions and limitations under the
   91.20 - * License.  When distributing the software, include this License Header
   91.21 - * Notice in each file and include the License file at
   91.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   91.23 - * particular file as subject to the "Classpath" exception as provided
   91.24 - * by Oracle in the GPL Version 2 section of the License file that
   91.25 - * accompanied this code. If applicable, add the following below the
   91.26 - * License Header, with the fields enclosed by brackets [] replaced by
   91.27 - * your own identifying information:
   91.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   91.29 - *
   91.30 - * Contributor(s):
   91.31 - *
   91.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   91.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   91.34 - * Microsystems, Inc. All Rights Reserved.
   91.35 - *
   91.36 - * If you wish your version of this file to be governed by only the CDDL
   91.37 - * or only the GPL Version 2, indicate your decision by adding
   91.38 - * "[Contributor] elects to include this software in this distribution
   91.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   91.40 - * single choice of license, a recipient has the option to distribute
   91.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   91.42 - * to extend the choice of license to its licensees as provided above.
   91.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   91.44 - * Version 2 license, then the option applies only if the new code is
   91.45 - * made subject to such option by the copyright holder.
   91.46 - */
   91.47 -
   91.48 -package org.netbeans.modules.python.editor.options;
   91.49 -
   91.50 -import javax.swing.JPanel;
   91.51 -import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
   91.52 -import static org.netbeans.modules.python.editor.options.FmtOptions.*;
   91.53 -import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
   91.54 -
   91.55 -/**
   91.56 - * Preferences for formatting related to spaces
   91.57 - * 
   91.58 - * @author  Tor Norbye
   91.59 - */
   91.60 -public class FmtSpaces extends JPanel {
   91.61 -    public FmtSpaces() {
   91.62 -        initComponents();
   91.63 -
   91.64 -        addAroundOp.putClientProperty(OPTION_ID, addSpaceAroundOperators);
   91.65 -        addAfterComma.putClientProperty(OPTION_ID, addSpaceAfterComma);
   91.66 -        removeBeforeSep.putClientProperty(OPTION_ID, removeSpaceBeforeSep);
   91.67 -        removeInParam.putClientProperty(OPTION_ID, removeSpaceInParamAssign);
   91.68 -        removeInParen.putClientProperty(OPTION_ID, removeSpaceInParens);
   91.69 -        collapseSpacesCb.putClientProperty(OPTION_ID, collapseSpaces);
   91.70 -    }
   91.71 -
   91.72 -    public static PreferencesCustomizer.Factory getController() {
   91.73 -        return new CategorySupport.Factory("spaces", FmtSpaces.class, // NOI18N
   91.74 -                org.openide.util.NbBundle.getMessage(FmtSpaces.class, "SAMPLE_Spaces"));
   91.75 -    }
   91.76 -    
   91.77 -    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
   91.78 -    private void initComponents() {
   91.79 -
   91.80 -        addAroundOp = new javax.swing.JCheckBox();
   91.81 -        removeInParam = new javax.swing.JCheckBox();
   91.82 -        removeInParen = new javax.swing.JCheckBox();
   91.83 -        addAfterComma = new javax.swing.JCheckBox();
   91.84 -        removeBeforeSep = new javax.swing.JCheckBox();
   91.85 -        collapseSpacesCb = new javax.swing.JCheckBox();
   91.86 -
   91.87 -        setName(org.openide.util.NbBundle.getMessage(FmtSpaces.class, "LBL_Spaces")); // NOI18N
   91.88 -        setOpaque(false);
   91.89 -
   91.90 -        org.openide.awt.Mnemonics.setLocalizedText(addAroundOp, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.addAroundOp.text")); // NOI18N
   91.91 -
   91.92 -        org.openide.awt.Mnemonics.setLocalizedText(removeInParam, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.removeInParam.text")); // NOI18N
   91.93 -
   91.94 -        org.openide.awt.Mnemonics.setLocalizedText(removeInParen, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.removeInParen.text")); // NOI18N
   91.95 -
   91.96 -        org.openide.awt.Mnemonics.setLocalizedText(addAfterComma, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.addAfterComma.text")); // NOI18N
   91.97 -
   91.98 -        org.openide.awt.Mnemonics.setLocalizedText(removeBeforeSep, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.removeBeforeSep.text")); // NOI18N
   91.99 -
  91.100 -        org.openide.awt.Mnemonics.setLocalizedText(collapseSpacesCb, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.collapseSpacesCb.text")); // NOI18N
  91.101 -
  91.102 -        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
  91.103 -        this.setLayout(layout);
  91.104 -        layout.setHorizontalGroup(
  91.105 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  91.106 -            .addGroup(layout.createSequentialGroup()
  91.107 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  91.108 -                    .addComponent(addAroundOp)
  91.109 -                    .addGroup(layout.createSequentialGroup()
  91.110 -                        .addGap(27, 27, 27)
  91.111 -                        .addComponent(removeInParam))
  91.112 -                    .addComponent(removeInParen)
  91.113 -                    .addComponent(addAfterComma)
  91.114 -                    .addComponent(removeBeforeSep)
  91.115 -                    .addComponent(collapseSpacesCb))
  91.116 -                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  91.117 -        );
  91.118 -        layout.setVerticalGroup(
  91.119 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  91.120 -            .addGroup(layout.createSequentialGroup()
  91.121 -                .addComponent(addAroundOp)
  91.122 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  91.123 -                .addComponent(removeInParam)
  91.124 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  91.125 -                .addComponent(removeInParen)
  91.126 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  91.127 -                .addComponent(addAfterComma)
  91.128 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  91.129 -                .addComponent(removeBeforeSep)
  91.130 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  91.131 -                .addComponent(collapseSpacesCb)
  91.132 -                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  91.133 -        );
  91.134 -    }// </editor-fold>//GEN-END:initComponents
  91.135 -    
  91.136 -    
  91.137 -    // Variables declaration - do not modify//GEN-BEGIN:variables
  91.138 -    private javax.swing.JCheckBox addAfterComma;
  91.139 -    private javax.swing.JCheckBox addAroundOp;
  91.140 -    private javax.swing.JCheckBox collapseSpacesCb;
  91.141 -    private javax.swing.JCheckBox removeBeforeSep;
  91.142 -    private javax.swing.JCheckBox removeInParam;
  91.143 -    private javax.swing.JCheckBox removeInParen;
  91.144 -    // End of variables declaration//GEN-END:variables
  91.145 -    
  91.146 -}
    92.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtTabsIndents.form	Sat Sep 12 23:03:15 2015 -0700
    92.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.3 @@ -1,127 +0,0 @@
    92.4 -<?xml version="1.0" encoding="UTF-8" ?>
    92.5 -
    92.6 -<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    92.7 -  <Properties>
    92.8 -    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    92.9 -      <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_TabsAndIndents" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   92.10 -    </Property>
   92.11 -    <Property name="opaque" type="boolean" value="false"/>
   92.12 -  </Properties>
   92.13 -  <AuxValues>
   92.14 -    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   92.15 -    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   92.16 -    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   92.17 -    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
   92.18 -    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   92.19 -    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
   92.20 -    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
   92.21 -    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   92.22 -    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   92.23 -  </AuxValues>
   92.24 -
   92.25 -  <Layout>
   92.26 -    <DimensionLayout dim="0">
   92.27 -      <Group type="103" groupAlignment="0" attributes="0">
   92.28 -          <Group type="102" alignment="0" attributes="0">
   92.29 -              <Group type="103" groupAlignment="0" attributes="0">
   92.30 -                  <Component id="continuationIndentSizeLabel" max="32767" attributes="0"/>
   92.31 -                  <Component id="labelIndentLabel" min="-2" max="-2" attributes="0"/>
   92.32 -              </Group>
   92.33 -              <EmptySpace max="-2" attributes="0"/>
   92.34 -              <Group type="103" groupAlignment="1" attributes="0">
   92.35 -                  <Component id="continuationIndentSizeField" linkSize="2" min="-2" pref="36" max="-2" attributes="1"/>
   92.36 -                  <Component id="labelIndentField" linkSize="2" min="-2" pref="36" max="-2" attributes="1"/>
   92.37 -              </Group>
   92.38 -          </Group>
   92.39 -          <Component id="indentCasesFromSwitchCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
   92.40 -          <Component id="indentTopLevelClassMembersCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
   92.41 -          <Component id="absoluteLabelIndentCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
   92.42 -      </Group>
   92.43 -    </DimensionLayout>
   92.44 -    <DimensionLayout dim="1">
   92.45 -      <Group type="103" groupAlignment="0" attributes="0">
   92.46 -          <Group type="102" attributes="0">
   92.47 -              <EmptySpace max="-2" attributes="0"/>
   92.48 -              <Group type="103" groupAlignment="3" attributes="0">
   92.49 -                  <Component id="continuationIndentSizeLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   92.50 -                  <Component id="continuationIndentSizeField" alignment="3" min="-2" max="-2" attributes="0"/>
   92.51 -              </Group>
   92.52 -              <EmptySpace min="-2" max="-2" attributes="0"/>
   92.53 -              <Group type="103" groupAlignment="3" attributes="0">
   92.54 -                  <Component id="labelIndentLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   92.55 -                  <Component id="labelIndentField" alignment="3" min="-2" max="-2" attributes="0"/>
   92.56 -              </Group>
   92.57 -              <EmptySpace type="unrelated" max="-2" attributes="0"/>
   92.58 -              <Component id="absoluteLabelIndentCheckBox" min="-2" max="-2" attributes="0"/>
   92.59 -              <EmptySpace max="-2" attributes="0"/>
   92.60 -              <Component id="indentTopLevelClassMembersCheckBox" min="-2" max="-2" attributes="0"/>
   92.61 -              <EmptySpace max="-2" attributes="0"/>
   92.62 -              <Component id="indentCasesFromSwitchCheckBox" min="-2" max="-2" attributes="0"/>
   92.63 -              <EmptySpace max="32767" attributes="0"/>
   92.64 -          </Group>
   92.65 -      </Group>
   92.66 -    </DimensionLayout>
   92.67 -  </Layout>
   92.68 -  <SubComponents>
   92.69 -    <Component class="javax.swing.JLabel" name="continuationIndentSizeLabel">
   92.70 -      <Properties>
   92.71 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
   92.72 -          <ComponentRef name="continuationIndentSizeField"/>
   92.73 -        </Property>
   92.74 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   92.75 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_ContinuationIndentSize" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   92.76 -        </Property>
   92.77 -      </Properties>
   92.78 -    </Component>
   92.79 -    <Component class="javax.swing.JTextField" name="continuationIndentSizeField">
   92.80 -    </Component>
   92.81 -    <Component class="javax.swing.JLabel" name="labelIndentLabel">
   92.82 -      <Properties>
   92.83 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
   92.84 -          <ComponentRef name="labelIndentField"/>
   92.85 -        </Property>
   92.86 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   92.87 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_LabelIndent" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   92.88 -        </Property>
   92.89 -      </Properties>
   92.90 -    </Component>
   92.91 -    <Component class="javax.swing.JTextField" name="labelIndentField">
   92.92 -    </Component>
   92.93 -    <Component class="javax.swing.JCheckBox" name="absoluteLabelIndentCheckBox">
   92.94 -      <Properties>
   92.95 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   92.96 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_AbsoluteLabelIndent" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   92.97 -        </Property>
   92.98 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
   92.99 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  92.100 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  92.101 -          </Border>
  92.102 -        </Property>
  92.103 -      </Properties>
  92.104 -    </Component>
  92.105 -    <Component class="javax.swing.JCheckBox" name="indentTopLevelClassMembersCheckBox">
  92.106 -      <Properties>
  92.107 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  92.108 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_IndentTopLevelClassMemberts" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  92.109 -        </Property>
  92.110 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  92.111 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  92.112 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  92.113 -          </Border>
  92.114 -        </Property>
  92.115 -      </Properties>
  92.116 -    </Component>
  92.117 -    <Component class="javax.swing.JCheckBox" name="indentCasesFromSwitchCheckBox">
  92.118 -      <Properties>
  92.119 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  92.120 -          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_IndentCasesFromSwitch" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  92.121 -        </Property>
  92.122 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  92.123 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  92.124 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  92.125 -          </Border>
  92.126 -        </Property>
  92.127 -      </Properties>
  92.128 -    </Component>
  92.129 -  </SubComponents>
  92.130 -</Form>
    93.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtTabsIndents.java	Sat Sep 12 23:03:15 2015 -0700
    93.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    93.3 @@ -1,196 +0,0 @@
    93.4 -/*
    93.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    93.6 - *
    93.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    93.8 - *
    93.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   93.10 - * Other names may be trademarks of their respective owners.
   93.11 - *
   93.12 - * The contents of this file are subject to the terms of either the GNU
   93.13 - * General Public License Version 2 only ("GPL") or the Common
   93.14 - * Development and Distribution License("CDDL") (collectively, the
   93.15 - * "License"). You may not use this file except in compliance with the
   93.16 - * License. You can obtain a copy of the License at
   93.17 - * http://www.netbeans.org/cddl-gplv2.html
   93.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   93.19 - * specific language governing permissions and limitations under the
   93.20 - * License.  When distributing the software, include this License Header
   93.21 - * Notice in each file and include the License file at
   93.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   93.23 - * particular file as subject to the "Classpath" exception as provided
   93.24 - * by Oracle in the GPL Version 2 section of the License file that
   93.25 - * accompanied this code. If applicable, add the following below the
   93.26 - * License Header, with the fields enclosed by brackets [] replaced by
   93.27 - * your own identifying information:
   93.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   93.29 - *
   93.30 - * Contributor(s):
   93.31 - *
   93.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   93.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   93.34 - * Microsystems, Inc. All Rights Reserved.
   93.35 - *
   93.36 - * If you wish your version of this file to be governed by only the CDDL
   93.37 - * or only the GPL Version 2, indicate your decision by adding
   93.38 - * "[Contributor] elects to include this software in this distribution
   93.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   93.40 - * single choice of license, a recipient has the option to distribute
   93.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   93.42 - * to extend the choice of license to its licensees as provided above.
   93.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   93.44 - * Version 2 license, then the option applies only if the new code is
   93.45 - * made subject to such option by the copyright holder.
   93.46 - */
   93.47 -
   93.48 -package org.netbeans.modules.python.editor.options;
   93.49 -
   93.50 -import org.netbeans.modules.python.editor.options.CodeStyle.WrapStyle;
   93.51 -import static org.netbeans.modules.python.editor.options.FmtOptions.*;
   93.52 -import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
   93.53 -import org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport;
   93.54 -import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
   93.55 -
   93.56 -/**
   93.57 - *
   93.58 - * @author  phrebejk
   93.59 - */
   93.60 -public class FmtTabsIndents extends javax.swing.JPanel {
   93.61 -   
   93.62 -    /** Creates new form FmtTabsIndents */
   93.63 -    public FmtTabsIndents() {
   93.64 -        initComponents();
   93.65 -/*
   93.66 -//        expandTabCheckBox.putClientProperty(OPTION_ID, expandTabToSpaces);
   93.67 -//        tabSizeField.putClientProperty(OPTION_ID, tabSize);
   93.68 -//        indentSizeField.putClientProperty(OPTION_ID, new String [] { indentSize, spacesPerTab });
   93.69 -        continuationIndentSizeField.putClientProperty(OPTION_ID, continuationIndentSize);
   93.70 -        labelIndentField.putClientProperty(OPTION_ID, labelIndent);
   93.71 -        absoluteLabelIndentCheckBox.putClientProperty(OPTION_ID, absoluteLabelIndent);
   93.72 -        indentTopLevelClassMembersCheckBox.putClientProperty(OPTION_ID, indentTopLevelClassMembers);
   93.73 -        indentCasesFromSwitchCheckBox.putClientProperty(OPTION_ID, indentCasesFromSwitch);
   93.74 -//        rightMarginField.putClientProperty(OPTION_ID, rightMargin);
   93.75 -    }
   93.76 -    
   93.77 -    public static PreferencesCustomizer.Factory getController() {
   93.78 -        return new CategorySupport.Factory(PreferencesCustomizer.TABS_AND_INDENTS_ID, FmtTabsIndents.class, //NOI18N
   93.79 -                org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "SAMPLE_TabsIndents"), // NOI18N
   93.80 -                new String[] { FmtOptions.rightMargin, "30" }, //NOI18N
   93.81 -                new String[] { FmtOptions.wrapAnnotations, WrapStyle.WRAP_ALWAYS.name() },
   93.82 -                new String[] { FmtOptions.wrapArrayInit, WrapStyle.WRAP_ALWAYS.name() },
   93.83 -                new String[] { FmtOptions.wrapAssert, WrapStyle.WRAP_ALWAYS.name() },
   93.84 -                new String[] { FmtOptions.wrapAssignOps, WrapStyle.WRAP_ALWAYS.name() },
   93.85 -                new String[] { FmtOptions.wrapBinaryOps, WrapStyle.WRAP_ALWAYS.name() },
   93.86 -                new String[] { FmtOptions.wrapChainedMethodCalls, WrapStyle.WRAP_ALWAYS.name() },
   93.87 -                new String[] { FmtOptions.wrapDoWhileStatement, WrapStyle.WRAP_ALWAYS.name() },
   93.88 -                new String[] { FmtOptions.wrapEnumConstants, WrapStyle.WRAP_ALWAYS.name() },
   93.89 -                new String[] { FmtOptions.wrapExtendsImplementsKeyword, WrapStyle.WRAP_ALWAYS.name() },
   93.90 -                new String[] { FmtOptions.wrapExtendsImplementsList, WrapStyle.WRAP_ALWAYS.name() },
   93.91 -                new String[] { FmtOptions.wrapFor, WrapStyle.WRAP_ALWAYS.name() },
   93.92 -                new String[] { FmtOptions.wrapForStatement, WrapStyle.WRAP_ALWAYS.name() },
   93.93 -                new String[] { FmtOptions.wrapIfStatement, WrapStyle.WRAP_ALWAYS.name() },
   93.94 -                new String[] { FmtOptions.wrapMethodCallArgs, WrapStyle.WRAP_ALWAYS.name() },
   93.95 -                new String[] { FmtOptions.wrapMethodParams, WrapStyle.WRAP_ALWAYS.name() },
   93.96 -                new String[] { FmtOptions.wrapTernaryOps, WrapStyle.WRAP_ALWAYS.name() },
   93.97 -                new String[] { FmtOptions.wrapThrowsKeyword, WrapStyle.WRAP_ALWAYS.name() },
   93.98 -                new String[] { FmtOptions.wrapThrowsList, WrapStyle.WRAP_ALWAYS.name() },
   93.99 -                new String[] { FmtOptions.wrapWhileStatement, WrapStyle.WRAP_ALWAYS.name() },
  93.100 -                new String[] { FmtOptions.alignMultilineArrayInit, Boolean.FALSE.toString() },
  93.101 -                new String[] { FmtOptions.alignMultilineAssignment, Boolean.FALSE.toString() },
  93.102 -                new String[] { FmtOptions.alignMultilineBinaryOp, Boolean.FALSE.toString() },
  93.103 -                new String[] { FmtOptions.alignMultilineCallArgs, Boolean.FALSE.toString() },
  93.104 -                new String[] { FmtOptions.alignMultilineFor, Boolean.FALSE.toString() },
  93.105 -                new String[] { FmtOptions.alignMultilineImplements, Boolean.FALSE.toString() },
  93.106 -                new String[] { FmtOptions.alignMultilineMethodParams, Boolean.FALSE.toString() },
  93.107 -                new String[] { FmtOptions.alignMultilineParenthesized, Boolean.FALSE.toString() },
  93.108 -                new String[] { FmtOptions.alignMultilineTernaryOp, Boolean.FALSE.toString() },
  93.109 -                new String[] { FmtOptions.alignMultilineThrows, Boolean.FALSE.toString() }
  93.110 -                );
  93.111 - */
  93.112 -    }
  93.113 -    
  93.114 -    /** This method is called from within the constructor to
  93.115 -     * initialize the form.
  93.116 -     * WARNING: Do NOT modify this code. The content of this method is
  93.117 -     * always regenerated by the Form Editor.
  93.118 -     */
  93.119 -    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  93.120 -    private void initComponents() {
  93.121 -
  93.122 -        continuationIndentSizeLabel = new javax.swing.JLabel();
  93.123 -        continuationIndentSizeField = new javax.swing.JTextField();
  93.124 -        labelIndentLabel = new javax.swing.JLabel();
  93.125 -        labelIndentField = new javax.swing.JTextField();
  93.126 -        absoluteLabelIndentCheckBox = new javax.swing.JCheckBox();
  93.127 -        indentTopLevelClassMembersCheckBox = new javax.swing.JCheckBox();
  93.128 -        indentCasesFromSwitchCheckBox = new javax.swing.JCheckBox();
  93.129 -
  93.130 -        setName(org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_TabsAndIndents")); // NOI18N
  93.131 -        setOpaque(false);
  93.132 -
  93.133 -        continuationIndentSizeLabel.setLabelFor(continuationIndentSizeField);
  93.134 -        org.openide.awt.Mnemonics.setLocalizedText(continuationIndentSizeLabel, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_ContinuationIndentSize")); // NOI18N
  93.135 -
  93.136 -        labelIndentLabel.setLabelFor(labelIndentField);
  93.137 -        org.openide.awt.Mnemonics.setLocalizedText(labelIndentLabel, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_LabelIndent")); // NOI18N
  93.138 -
  93.139 -        org.openide.awt.Mnemonics.setLocalizedText(absoluteLabelIndentCheckBox, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_AbsoluteLabelIndent")); // NOI18N
  93.140 -        absoluteLabelIndentCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  93.141 -
  93.142 -        org.openide.awt.Mnemonics.setLocalizedText(indentTopLevelClassMembersCheckBox, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_IndentTopLevelClassMemberts")); // NOI18N
  93.143 -        indentTopLevelClassMembersCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  93.144 -
  93.145 -        org.openide.awt.Mnemonics.setLocalizedText(indentCasesFromSwitchCheckBox, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_IndentCasesFromSwitch")); // NOI18N
  93.146 -        indentCasesFromSwitchCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  93.147 -
  93.148 -        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
  93.149 -        this.setLayout(layout);
  93.150 -        layout.setHorizontalGroup(
  93.151 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  93.152 -            .addGroup(layout.createSequentialGroup()
  93.153 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  93.154 -                    .addComponent(continuationIndentSizeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
  93.155 -                    .addComponent(labelIndentLabel))
  93.156 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  93.157 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
  93.158 -                    .addComponent(continuationIndentSizeField, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE)
  93.159 -                    .addComponent(labelIndentField, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE)))
  93.160 -            .addComponent(indentCasesFromSwitchCheckBox)
  93.161 -            .addComponent(indentTopLevelClassMembersCheckBox)
  93.162 -            .addComponent(absoluteLabelIndentCheckBox)
  93.163 -        );
  93.164 -
  93.165 -        layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {continuationIndentSizeField, labelIndentField});
  93.166 -
  93.167 -        layout.setVerticalGroup(
  93.168 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  93.169 -            .addGroup(layout.createSequentialGroup()
  93.170 -                .addContainerGap()
  93.171 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  93.172 -                    .addComponent(continuationIndentSizeLabel)
  93.173 -                    .addComponent(continuationIndentSizeField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
  93.174 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  93.175 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  93.176 -                    .addComponent(labelIndentLabel)
  93.177 -                    .addComponent(labelIndentField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
  93.178 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
  93.179 -                .addComponent(absoluteLabelIndentCheckBox)
  93.180 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  93.181 -                .addComponent(indentTopLevelClassMembersCheckBox)
  93.182 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  93.183 -                .addComponent(indentCasesFromSwitchCheckBox)
  93.184 -                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  93.185 -        );
  93.186 -    }// </editor-fold>//GEN-END:initComponents
  93.187 -    
  93.188 -    
  93.189 -    // Variables declaration - do not modify//GEN-BEGIN:variables
  93.190 -    private javax.swing.JCheckBox absoluteLabelIndentCheckBox;
  93.191 -    private javax.swing.JTextField continuationIndentSizeField;
  93.192 -    private javax.swing.JLabel continuationIndentSizeLabel;
  93.193 -    private javax.swing.JCheckBox indentCasesFromSwitchCheckBox;
  93.194 -    private javax.swing.JCheckBox indentTopLevelClassMembersCheckBox;
  93.195 -    private javax.swing.JTextField labelIndentField;
  93.196 -    private javax.swing.JLabel labelIndentLabel;
  93.197 -    // End of variables declaration//GEN-END:variables
  93.198 -    
  93.199 -}
    94.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtWrapping.form	Sat Sep 12 23:03:15 2015 -0700
    94.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.3 @@ -1,706 +0,0 @@
    94.4 -<?xml version="1.0" encoding="UTF-8" ?>
    94.5 -
    94.6 -<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    94.7 -  <Properties>
    94.8 -    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    94.9 -      <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_Wrapping" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   94.10 -    </Property>
   94.11 -    <Property name="opaque" type="boolean" value="false"/>
   94.12 -  </Properties>
   94.13 -  <AuxValues>
   94.14 -    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   94.15 -    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   94.16 -    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   94.17 -    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
   94.18 -    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   94.19 -    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
   94.20 -    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
   94.21 -    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   94.22 -    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   94.23 -    <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,45,0,0,1,42"/>
   94.24 -  </AuxValues>
   94.25 -
   94.26 -  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
   94.27 -  <SubComponents>
   94.28 -    <Container class="javax.swing.JScrollPane" name="scrollPane">
   94.29 -      <Properties>
   94.30 -        <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
   94.31 -          <Dimension value="[300, 200]"/>
   94.32 -        </Property>
   94.33 -        <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
   94.34 -          <Dimension value="[350, 600]"/>
   94.35 -        </Property>
   94.36 -      </Properties>
   94.37 -      <Constraints>
   94.38 -        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
   94.39 -          <BorderConstraints direction="Center"/>
   94.40 -        </Constraint>
   94.41 -      </Constraints>
   94.42 -
   94.43 -      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
   94.44 -      <SubComponents>
   94.45 -        <Container class="javax.swing.JPanel" name="panel1">
   94.46 -          <Properties>
   94.47 -            <Property name="opaque" type="boolean" value="false"/>
   94.48 -          </Properties>
   94.49 -
   94.50 -          <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
   94.51 -          <SubComponents>
   94.52 -            <Component class="javax.swing.JLabel" name="extendsImplemetsKeywordLabel">
   94.53 -              <Properties>
   94.54 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
   94.55 -                  <ComponentRef name="extendsImplementsKeywordCombo"/>
   94.56 -                </Property>
   94.57 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   94.58 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_extendsImplementsKeyword" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   94.59 -                </Property>
   94.60 -              </Properties>
   94.61 -              <Constraints>
   94.62 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
   94.63 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="8" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
   94.64 -                </Constraint>
   94.65 -              </Constraints>
   94.66 -            </Component>
   94.67 -            <Component class="javax.swing.JComboBox" name="extendsImplementsKeywordCombo">
   94.68 -              <Properties>
   94.69 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
   94.70 -                  <StringArray count="4">
   94.71 -                    <StringItem index="0" value="Item 1"/>
   94.72 -                    <StringItem index="1" value="Item 2"/>
   94.73 -                    <StringItem index="2" value="Item 3"/>
   94.74 -                    <StringItem index="3" value="Item 4"/>
   94.75 -                  </StringArray>
   94.76 -                </Property>
   94.77 -              </Properties>
   94.78 -              <Constraints>
   94.79 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
   94.80 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="8" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="1.0" weightY="0.0"/>
   94.81 -                </Constraint>
   94.82 -              </Constraints>
   94.83 -            </Component>
   94.84 -            <Component class="javax.swing.JLabel" name="extendsImplementsListLabel">
   94.85 -              <Properties>
   94.86 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
   94.87 -                  <ComponentRef name="extendsImplementsListCombo"/>
   94.88 -                </Property>
   94.89 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   94.90 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_extendsImplementsList" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   94.91 -                </Property>
   94.92 -              </Properties>
   94.93 -              <Constraints>
   94.94 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
   94.95 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
   94.96 -                </Constraint>
   94.97 -              </Constraints>
   94.98 -            </Component>
   94.99 -            <Component class="javax.swing.JComboBox" name="extendsImplementsListCombo">
  94.100 -              <Properties>
  94.101 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.102 -                  <StringArray count="4">
  94.103 -                    <StringItem index="0" value="Item 1"/>
  94.104 -                    <StringItem index="1" value="Item 2"/>
  94.105 -                    <StringItem index="2" value="Item 3"/>
  94.106 -                    <StringItem index="3" value="Item 4"/>
  94.107 -                  </StringArray>
  94.108 -                </Property>
  94.109 -              </Properties>
  94.110 -              <Constraints>
  94.111 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.112 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.113 -                </Constraint>
  94.114 -              </Constraints>
  94.115 -            </Component>
  94.116 -            <Component class="javax.swing.JLabel" name="methodParamsLabel">
  94.117 -              <Properties>
  94.118 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.119 -                  <ComponentRef name="methodParamsCombo"/>
  94.120 -                </Property>
  94.121 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.122 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_methodParameters" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.123 -                </Property>
  94.124 -              </Properties>
  94.125 -              <Constraints>
  94.126 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.127 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.128 -                </Constraint>
  94.129 -              </Constraints>
  94.130 -            </Component>
  94.131 -            <Component class="javax.swing.JComboBox" name="methodParamsCombo">
  94.132 -              <Properties>
  94.133 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.134 -                  <StringArray count="4">
  94.135 -                    <StringItem index="0" value="Item 1"/>
  94.136 -                    <StringItem index="1" value="Item 2"/>
  94.137 -                    <StringItem index="2" value="Item 3"/>
  94.138 -                    <StringItem index="3" value="Item 4"/>
  94.139 -                  </StringArray>
  94.140 -                </Property>
  94.141 -              </Properties>
  94.142 -              <Constraints>
  94.143 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.144 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.145 -                </Constraint>
  94.146 -              </Constraints>
  94.147 -            </Component>
  94.148 -            <Component class="javax.swing.JLabel" name="methodCallArgsLabel">
  94.149 -              <Properties>
  94.150 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.151 -                  <ComponentRef name="methodCallArgsCombo"/>
  94.152 -                </Property>
  94.153 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.154 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_methodCallArgs" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.155 -                </Property>
  94.156 -              </Properties>
  94.157 -              <Constraints>
  94.158 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.159 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.160 -                </Constraint>
  94.161 -              </Constraints>
  94.162 -            </Component>
  94.163 -            <Component class="javax.swing.JComboBox" name="methodCallArgsCombo">
  94.164 -              <Properties>
  94.165 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.166 -                  <StringArray count="4">
  94.167 -                    <StringItem index="0" value="Item 1"/>
  94.168 -                    <StringItem index="1" value="Item 2"/>
  94.169 -                    <StringItem index="2" value="Item 3"/>
  94.170 -                    <StringItem index="3" value="Item 4"/>
  94.171 -                  </StringArray>
  94.172 -                </Property>
  94.173 -              </Properties>
  94.174 -              <Constraints>
  94.175 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.176 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.177 -                </Constraint>
  94.178 -              </Constraints>
  94.179 -            </Component>
  94.180 -            <Component class="javax.swing.JLabel" name="annotationArgsLabel">
  94.181 -              <Properties>
  94.182 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.183 -                  <ComponentRef name="annotationArgsCombo"/>
  94.184 -                </Property>
  94.185 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.186 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_annotationArgs" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.187 -                </Property>
  94.188 -              </Properties>
  94.189 -              <Constraints>
  94.190 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.191 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.192 -                </Constraint>
  94.193 -              </Constraints>
  94.194 -            </Component>
  94.195 -            <Component class="javax.swing.JComboBox" name="annotationArgsCombo">
  94.196 -              <Properties>
  94.197 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.198 -                  <StringArray count="4">
  94.199 -                    <StringItem index="0" value="Item 1"/>
  94.200 -                    <StringItem index="1" value="Item 2"/>
  94.201 -                    <StringItem index="2" value="Item 3"/>
  94.202 -                    <StringItem index="3" value="Item 4"/>
  94.203 -                  </StringArray>
  94.204 -                </Property>
  94.205 -              </Properties>
  94.206 -              <Constraints>
  94.207 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.208 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.209 -                </Constraint>
  94.210 -              </Constraints>
  94.211 -            </Component>
  94.212 -            <Component class="javax.swing.JLabel" name="chainedMethodCallsLabel">
  94.213 -              <Properties>
  94.214 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.215 -                  <ComponentRef name="chainedMethodCallsCombo"/>
  94.216 -                </Property>
  94.217 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.218 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_chainedMethodCalls" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.219 -                </Property>
  94.220 -              </Properties>
  94.221 -              <Constraints>
  94.222 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.223 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.224 -                </Constraint>
  94.225 -              </Constraints>
  94.226 -            </Component>
  94.227 -            <Component class="javax.swing.JComboBox" name="chainedMethodCallsCombo">
  94.228 -              <Properties>
  94.229 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.230 -                  <StringArray count="4">
  94.231 -                    <StringItem index="0" value="Item 1"/>
  94.232 -                    <StringItem index="1" value="Item 2"/>
  94.233 -                    <StringItem index="2" value="Item 3"/>
  94.234 -                    <StringItem index="3" value="Item 4"/>
  94.235 -                  </StringArray>
  94.236 -                </Property>
  94.237 -              </Properties>
  94.238 -              <Constraints>
  94.239 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.240 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.241 -                </Constraint>
  94.242 -              </Constraints>
  94.243 -            </Component>
  94.244 -            <Component class="javax.swing.JLabel" name="throwsKeywordLabel">
  94.245 -              <Properties>
  94.246 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.247 -                  <ComponentRef name="throwsKeywordCombo"/>
  94.248 -                </Property>
  94.249 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.250 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_throwsKeyword" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.251 -                </Property>
  94.252 -              </Properties>
  94.253 -              <Constraints>
  94.254 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.255 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.256 -                </Constraint>
  94.257 -              </Constraints>
  94.258 -            </Component>
  94.259 -            <Component class="javax.swing.JComboBox" name="throwsKeywordCombo">
  94.260 -              <Properties>
  94.261 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.262 -                  <StringArray count="4">
  94.263 -                    <StringItem index="0" value="Item 1"/>
  94.264 -                    <StringItem index="1" value="Item 2"/>
  94.265 -                    <StringItem index="2" value="Item 3"/>
  94.266 -                    <StringItem index="3" value="Item 4"/>
  94.267 -                  </StringArray>
  94.268 -                </Property>
  94.269 -              </Properties>
  94.270 -              <Constraints>
  94.271 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.272 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.273 -                </Constraint>
  94.274 -              </Constraints>
  94.275 -            </Component>
  94.276 -            <Component class="javax.swing.JLabel" name="throwsListLabel">
  94.277 -              <Properties>
  94.278 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.279 -                  <ComponentRef name="throwsListCombo"/>
  94.280 -                </Property>
  94.281 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.282 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_throwsList" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.283 -                </Property>
  94.284 -              </Properties>
  94.285 -              <Constraints>
  94.286 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.287 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.288 -                </Constraint>
  94.289 -              </Constraints>
  94.290 -            </Component>
  94.291 -            <Component class="javax.swing.JComboBox" name="throwsListCombo">
  94.292 -              <Properties>
  94.293 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.294 -                  <StringArray count="4">
  94.295 -                    <StringItem index="0" value="Item 1"/>
  94.296 -                    <StringItem index="1" value="Item 2"/>
  94.297 -                    <StringItem index="2" value="Item 3"/>
  94.298 -                    <StringItem index="3" value="Item 4"/>
  94.299 -                  </StringArray>
  94.300 -                </Property>
  94.301 -              </Properties>
  94.302 -              <Constraints>
  94.303 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.304 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.305 -                </Constraint>
  94.306 -              </Constraints>
  94.307 -            </Component>
  94.308 -            <Component class="javax.swing.JLabel" name="arrayInitLabel">
  94.309 -              <Properties>
  94.310 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.311 -                  <ComponentRef name="arrayInitCombo"/>
  94.312 -                </Property>
  94.313 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.314 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_arrayInit" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.315 -                </Property>
  94.316 -              </Properties>
  94.317 -              <Constraints>
  94.318 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.319 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.320 -                </Constraint>
  94.321 -              </Constraints>
  94.322 -            </Component>
  94.323 -            <Component class="javax.swing.JComboBox" name="arrayInitCombo">
  94.324 -              <Properties>
  94.325 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.326 -                  <StringArray count="4">
  94.327 -                    <StringItem index="0" value="Item 1"/>
  94.328 -                    <StringItem index="1" value="Item 2"/>
  94.329 -                    <StringItem index="2" value="Item 3"/>
  94.330 -                    <StringItem index="3" value="Item 4"/>
  94.331 -                  </StringArray>
  94.332 -                </Property>
  94.333 -              </Properties>
  94.334 -              <Constraints>
  94.335 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.336 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.337 -                </Constraint>
  94.338 -              </Constraints>
  94.339 -            </Component>
  94.340 -            <Component class="javax.swing.JLabel" name="forLabel">
  94.341 -              <Properties>
  94.342 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.343 -                  <ComponentRef name="forCombo"/>
  94.344 -                </Property>
  94.345 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.346 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_for" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.347 -                </Property>
  94.348 -              </Properties>
  94.349 -              <Constraints>
  94.350 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.351 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.352 -                </Constraint>
  94.353 -              </Constraints>
  94.354 -            </Component>
  94.355 -            <Component class="javax.swing.JComboBox" name="forCombo">
  94.356 -              <Properties>
  94.357 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.358 -                  <StringArray count="4">
  94.359 -                    <StringItem index="0" value="Item 1"/>
  94.360 -                    <StringItem index="1" value="Item 2"/>
  94.361 -                    <StringItem index="2" value="Item 3"/>
  94.362 -                    <StringItem index="3" value="Item 4"/>
  94.363 -                  </StringArray>
  94.364 -                </Property>
  94.365 -              </Properties>
  94.366 -              <Constraints>
  94.367 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.368 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.369 -                </Constraint>
  94.370 -              </Constraints>
  94.371 -            </Component>
  94.372 -            <Component class="javax.swing.JLabel" name="forStatementLabel">
  94.373 -              <Properties>
  94.374 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.375 -                  <ComponentRef name="forStatementCombo"/>
  94.376 -                </Property>
  94.377 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.378 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_forStatement" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.379 -                </Property>
  94.380 -              </Properties>
  94.381 -              <Constraints>
  94.382 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.383 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.384 -                </Constraint>
  94.385 -              </Constraints>
  94.386 -            </Component>
  94.387 -            <Component class="javax.swing.JComboBox" name="forStatementCombo">
  94.388 -              <Properties>
  94.389 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.390 -                  <StringArray count="4">
  94.391 -                    <StringItem index="0" value="Item 1"/>
  94.392 -                    <StringItem index="1" value="Item 2"/>
  94.393 -                    <StringItem index="2" value="Item 3"/>
  94.394 -                    <StringItem index="3" value="Item 4"/>
  94.395 -                  </StringArray>
  94.396 -                </Property>
  94.397 -              </Properties>
  94.398 -              <Constraints>
  94.399 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.400 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="1.0" weightY="0.0"/>
  94.401 -                </Constraint>
  94.402 -              </Constraints>
  94.403 -            </Component>
  94.404 -            <Component class="javax.swing.JLabel" name="ifStatementLabel">
  94.405 -              <Properties>
  94.406 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.407 -                  <ComponentRef name="ifStatementCombo"/>
  94.408 -                </Property>
  94.409 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.410 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_ifStatement" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.411 -                </Property>
  94.412 -              </Properties>
  94.413 -              <Constraints>
  94.414 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.415 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.416 -                </Constraint>
  94.417 -              </Constraints>
  94.418 -            </Component>
  94.419 -            <Component class="javax.swing.JComboBox" name="ifStatementCombo">
  94.420 -              <Properties>
  94.421 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.422 -                  <StringArray count="4">
  94.423 -                    <StringItem index="0" value="Item 1"/>
  94.424 -                    <StringItem index="1" value="Item 2"/>
  94.425 -                    <StringItem index="2" value="Item 3"/>
  94.426 -                    <StringItem index="3" value="Item 4"/>
  94.427 -                  </StringArray>
  94.428 -                </Property>
  94.429 -              </Properties>
  94.430 -              <Constraints>
  94.431 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.432 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.433 -                </Constraint>
  94.434 -              </Constraints>
  94.435 -            </Component>
  94.436 -            <Component class="javax.swing.JLabel" name="whileStatementLabel">
  94.437 -              <Properties>
  94.438 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.439 -                  <ComponentRef name="whileStatementComboBox"/>
  94.440 -                </Property>
  94.441 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.442 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_whileStatement" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.443 -                </Property>
  94.444 -              </Properties>
  94.445 -              <Constraints>
  94.446 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.447 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.448 -                </Constraint>
  94.449 -              </Constraints>
  94.450 -            </Component>
  94.451 -            <Component class="javax.swing.JComboBox" name="whileStatementComboBox">
  94.452 -              <Properties>
  94.453 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.454 -                  <StringArray count="4">
  94.455 -                    <StringItem index="0" value="Item 1"/>
  94.456 -                    <StringItem index="1" value="Item 2"/>
  94.457 -                    <StringItem index="2" value="Item 3"/>
  94.458 -                    <StringItem index="3" value="Item 4"/>
  94.459 -                  </StringArray>
  94.460 -                </Property>
  94.461 -              </Properties>
  94.462 -              <Constraints>
  94.463 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.464 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.465 -                </Constraint>
  94.466 -              </Constraints>
  94.467 -            </Component>
  94.468 -            <Component class="javax.swing.JLabel" name="doWhileStatementLabel">
  94.469 -              <Properties>
  94.470 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.471 -                  <ComponentRef name="doWhileStatementCombo"/>
  94.472 -                </Property>
  94.473 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.474 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_doWhileStatement" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.475 -                </Property>
  94.476 -              </Properties>
  94.477 -              <Constraints>
  94.478 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.479 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.480 -                </Constraint>
  94.481 -              </Constraints>
  94.482 -            </Component>
  94.483 -            <Component class="javax.swing.JComboBox" name="doWhileStatementCombo">
  94.484 -              <Properties>
  94.485 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.486 -                  <StringArray count="4">
  94.487 -                    <StringItem index="0" value="Item 1"/>
  94.488 -                    <StringItem index="1" value="Item 2"/>
  94.489 -                    <StringItem index="2" value="Item 3"/>
  94.490 -                    <StringItem index="3" value="Item 4"/>
  94.491 -                  </StringArray>
  94.492 -                </Property>
  94.493 -              </Properties>
  94.494 -              <Constraints>
  94.495 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.496 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.497 -                </Constraint>
  94.498 -              </Constraints>
  94.499 -            </Component>
  94.500 -            <Component class="javax.swing.JLabel" name="assertLabel">
  94.501 -              <Properties>
  94.502 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.503 -                  <ComponentRef name="assertCombo"/>
  94.504 -                </Property>
  94.505 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.506 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_assert" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.507 -                </Property>
  94.508 -              </Properties>
  94.509 -              <Constraints>
  94.510 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.511 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.512 -                </Constraint>
  94.513 -              </Constraints>
  94.514 -            </Component>
  94.515 -            <Component class="javax.swing.JComboBox" name="assertCombo">
  94.516 -              <Properties>
  94.517 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.518 -                  <StringArray count="4">
  94.519 -                    <StringItem index="0" value="Item 1"/>
  94.520 -                    <StringItem index="1" value="Item 2"/>
  94.521 -                    <StringItem index="2" value="Item 3"/>
  94.522 -                    <StringItem index="3" value="Item 4"/>
  94.523 -                  </StringArray>
  94.524 -                </Property>
  94.525 -              </Properties>
  94.526 -              <Constraints>
  94.527 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.528 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.529 -                </Constraint>
  94.530 -              </Constraints>
  94.531 -            </Component>
  94.532 -            <Component class="javax.swing.JLabel" name="enumConstantsLabel">
  94.533 -              <Properties>
  94.534 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.535 -                  <ComponentRef name="enumConstantsCombo"/>
  94.536 -                </Property>
  94.537 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.538 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_enumConstants" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.539 -                </Property>
  94.540 -              </Properties>
  94.541 -              <Constraints>
  94.542 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.543 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.544 -                </Constraint>
  94.545 -              </Constraints>
  94.546 -            </Component>
  94.547 -            <Component class="javax.swing.JComboBox" name="enumConstantsCombo">
  94.548 -              <Properties>
  94.549 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.550 -                  <StringArray count="4">
  94.551 -                    <StringItem index="0" value="Item 1"/>
  94.552 -                    <StringItem index="1" value="Item 2"/>
  94.553 -                    <StringItem index="2" value="Item 3"/>
  94.554 -                    <StringItem index="3" value="Item 4"/>
  94.555 -                  </StringArray>
  94.556 -                </Property>
  94.557 -              </Properties>
  94.558 -              <Constraints>
  94.559 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.560 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.561 -                </Constraint>
  94.562 -              </Constraints>
  94.563 -            </Component>
  94.564 -            <Component class="javax.swing.JLabel" name="annotationsLabel">
  94.565 -              <Properties>
  94.566 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.567 -                  <ComponentRef name="annotationsCombo"/>
  94.568 -                </Property>
  94.569 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.570 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_annotations" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.571 -                </Property>
  94.572 -              </Properties>
  94.573 -              <Constraints>
  94.574 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.575 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.576 -                </Constraint>
  94.577 -              </Constraints>
  94.578 -            </Component>
  94.579 -            <Component class="javax.swing.JComboBox" name="annotationsCombo">
  94.580 -              <Properties>
  94.581 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.582 -                  <StringArray count="4">
  94.583 -                    <StringItem index="0" value="Item 1"/>
  94.584 -                    <StringItem index="1" value="Item 2"/>
  94.585 -                    <StringItem index="2" value="Item 3"/>
  94.586 -                    <StringItem index="3" value="Item 4"/>
  94.587 -                  </StringArray>
  94.588 -                </Property>
  94.589 -              </Properties>
  94.590 -              <Constraints>
  94.591 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.592 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.593 -                </Constraint>
  94.594 -              </Constraints>
  94.595 -            </Component>
  94.596 -            <Component class="javax.swing.JLabel" name="binaryOpsLabel">
  94.597 -              <Properties>
  94.598 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.599 -                  <ComponentRef name="binaryOpsCombo"/>
  94.600 -                </Property>
  94.601 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.602 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_binaryOps" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.603 -                </Property>
  94.604 -              </Properties>
  94.605 -              <Constraints>
  94.606 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.607 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.608 -                </Constraint>
  94.609 -              </Constraints>
  94.610 -            </Component>
  94.611 -            <Component class="javax.swing.JComboBox" name="binaryOpsCombo">
  94.612 -              <Properties>
  94.613 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.614 -                  <StringArray count="4">
  94.615 -                    <StringItem index="0" value="Item 1"/>
  94.616 -                    <StringItem index="1" value="Item 2"/>
  94.617 -                    <StringItem index="2" value="Item 3"/>
  94.618 -                    <StringItem index="3" value="Item 4"/>
  94.619 -                  </StringArray>
  94.620 -                </Property>
  94.621 -              </Properties>
  94.622 -              <Constraints>
  94.623 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.624 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.625 -                </Constraint>
  94.626 -              </Constraints>
  94.627 -            </Component>
  94.628 -            <Component class="javax.swing.JLabel" name="ternaryOpsLabel">
  94.629 -              <Properties>
  94.630 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.631 -                  <ComponentRef name="ternaryOpsCombo"/>
  94.632 -                </Property>
  94.633 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.634 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_ternaryOps" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.635 -                </Property>
  94.636 -              </Properties>
  94.637 -              <Constraints>
  94.638 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.639 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.640 -                </Constraint>
  94.641 -              </Constraints>
  94.642 -            </Component>
  94.643 -            <Component class="javax.swing.JComboBox" name="ternaryOpsCombo">
  94.644 -              <Properties>
  94.645 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.646 -                  <StringArray count="4">
  94.647 -                    <StringItem index="0" value="Item 1"/>
  94.648 -                    <StringItem index="1" value="Item 2"/>
  94.649 -                    <StringItem index="2" value="Item 3"/>
  94.650 -                    <StringItem index="3" value="Item 4"/>
  94.651 -                  </StringArray>
  94.652 -                </Property>
  94.653 -              </Properties>
  94.654 -              <Constraints>
  94.655 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.656 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.657 -                </Constraint>
  94.658 -              </Constraints>
  94.659 -            </Component>
  94.660 -            <Component class="javax.swing.JLabel" name="assignOpsLabel">
  94.661 -              <Properties>
  94.662 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  94.663 -                  <ComponentRef name="assignOpsCombo"/>
  94.664 -                </Property>
  94.665 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  94.666 -                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_assignOps" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  94.667 -                </Property>
  94.668 -              </Properties>
  94.669 -              <Constraints>
  94.670 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.671 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  94.672 -                </Constraint>
  94.673 -              </Constraints>
  94.674 -            </Component>
  94.675 -            <Component class="javax.swing.JComboBox" name="assignOpsCombo">
  94.676 -              <Properties>
  94.677 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  94.678 -                  <StringArray count="4">
  94.679 -                    <StringItem index="0" value="Item 1"/>
  94.680 -                    <StringItem index="1" value="Item 2"/>
  94.681 -                    <StringItem index="2" value="Item 3"/>
  94.682 -                    <StringItem index="3" value="Item 4"/>
  94.683 -                  </StringArray>
  94.684 -                </Property>
  94.685 -              </Properties>
  94.686 -              <Constraints>
  94.687 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.688 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
  94.689 -                </Constraint>
  94.690 -              </Constraints>
  94.691 -            </Component>
  94.692 -            <Container class="javax.swing.JPanel" name="spacerPanel1">
  94.693 -              <Properties>
  94.694 -                <Property name="opaque" type="boolean" value="false"/>
  94.695 -              </Properties>
  94.696 -              <Constraints>
  94.697 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  94.698 -                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="0" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="0" insetsRight="8" anchor="10" weightX="0.0" weightY="1.0"/>
  94.699 -                </Constraint>
  94.700 -              </Constraints>
  94.701 -
  94.702 -              <Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
  94.703 -            </Container>
  94.704 -          </SubComponents>
  94.705 -        </Container>
  94.706 -      </SubComponents>
  94.707 -    </Container>
  94.708 -  </SubComponents>
  94.709 -</Form>
    95.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtWrapping.java	Sat Sep 12 23:03:15 2015 -0700
    95.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.3 @@ -1,505 +0,0 @@
    95.4 -/*
    95.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    95.6 - *
    95.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    95.8 - *
    95.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   95.10 - * Other names may be trademarks of their respective owners.
   95.11 - *
   95.12 - * The contents of this file are subject to the terms of either the GNU
   95.13 - * General Public License Version 2 only ("GPL") or the Common
   95.14 - * Development and Distribution License("CDDL") (collectively, the
   95.15 - * "License"). You may not use this file except in compliance with the
   95.16 - * License. You can obtain a copy of the License at
   95.17 - * http://www.netbeans.org/cddl-gplv2.html
   95.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   95.19 - * specific language governing permissions and limitations under the
   95.20 - * License.  When distributing the software, include this License Header
   95.21 - * Notice in each file and include the License file at
   95.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   95.23 - * particular file as subject to the "Classpath" exception as provided
   95.24 - * by Oracle in the GPL Version 2 section of the License file that
   95.25 - * accompanied this code. If applicable, add the following below the
   95.26 - * License Header, with the fields enclosed by brackets [] replaced by
   95.27 - * your own identifying information:
   95.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   95.29 - *
   95.30 - * Contributor(s):
   95.31 - *
   95.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   95.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   95.34 - * Microsystems, Inc. All Rights Reserved.
   95.35 - *
   95.36 - * If you wish your version of this file to be governed by only the CDDL
   95.37 - * or only the GPL Version 2, indicate your decision by adding
   95.38 - * "[Contributor] elects to include this software in this distribution
   95.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   95.40 - * single choice of license, a recipient has the option to distribute
   95.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   95.42 - * to extend the choice of license to its licensees as provided above.
   95.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   95.44 - * Version 2 license, then the option applies only if the new code is
   95.45 - * made subject to such option by the copyright holder.
   95.46 - */
   95.47 -
   95.48 -package org.netbeans.modules.python.editor.options;
   95.49 -
   95.50 -import org.netbeans.modules.python.editor.options.CodeStyle;
   95.51 -import static org.netbeans.modules.python.editor.options.FmtOptions.*;
   95.52 -import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
   95.53 -import org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport;
   95.54 -import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
   95.55 -
   95.56 -
   95.57 -/**
   95.58 - *
   95.59 - * @author  phrebejk
   95.60 - */
   95.61 -public class FmtWrapping extends javax.swing.JPanel {
   95.62 -    
   95.63 -    /** Creates new form FmtWrapping */
   95.64 -    public FmtWrapping() {
   95.65 -        initComponents();
   95.66 -        
   95.67 -        scrollPane.getViewport().setBackground(java.awt.SystemColor.controlLtHighlight);
   95.68 -        
   95.69 -/*
   95.70 -        extendsImplementsKeywordCombo.putClientProperty(OPTION_ID, wrapExtendsImplementsKeyword);
   95.71 -        extendsImplementsListCombo.putClientProperty(OPTION_ID, wrapExtendsImplementsList);
   95.72 -        methodParamsCombo.putClientProperty(OPTION_ID, wrapMethodParams);
   95.73 -        methodCallArgsCombo.putClientProperty(OPTION_ID, wrapMethodCallArgs);
   95.74 -        annotationArgsCombo.putClientProperty(OPTION_ID, wrapAnnotationArgs);
   95.75 -        chainedMethodCallsCombo.putClientProperty(OPTION_ID, wrapChainedMethodCalls);
   95.76 -        throwsKeywordCombo.putClientProperty(OPTION_ID, wrapThrowsKeyword);
   95.77 -        throwsListCombo.putClientProperty(OPTION_ID, wrapThrowsList);
   95.78 -        arrayInitCombo.putClientProperty(OPTION_ID, wrapArrayInit);
   95.79 -        forCombo.putClientProperty(OPTION_ID, wrapFor);
   95.80 -        forStatementCombo.putClientProperty(OPTION_ID, wrapForStatement );
   95.81 -        ifStatementCombo.putClientProperty(OPTION_ID, wrapIfStatement);
   95.82 -        whileStatementComboBox.putClientProperty(OPTION_ID, wrapWhileStatement);
   95.83 -        doWhileStatementCombo.putClientProperty(OPTION_ID, wrapDoWhileStatement);
   95.84 -        assertCombo.putClientProperty(OPTION_ID, wrapAssert);
   95.85 -        enumConstantsCombo.putClientProperty(OPTION_ID, wrapEnumConstants);
   95.86 -        annotationsCombo.putClientProperty(OPTION_ID, wrapAnnotations);
   95.87 -        binaryOpsCombo.putClientProperty(OPTION_ID, wrapBinaryOps);
   95.88 -        ternaryOpsCombo.putClientProperty(OPTION_ID, wrapTernaryOps);
   95.89 -        assignOpsCombo.putClientProperty(OPTION_ID, wrapAssignOps);
   95.90 -    }
   95.91 -    
   95.92 -    public static PreferencesCustomizer.Factory getController() {
   95.93 -        return new CategorySupport.Factory("wrapping", FmtWrapping.class, //NOI18N
   95.94 -                org.openide.util.NbBundle.getMessage(FmtWrapping.class, "SAMPLE_Wrapping"), //NOI18N
   95.95 -                new String[] { FmtOptions.rightMargin, "30" } //NOI18N
   95.96 -//                new String[] { FmtOptions.redundantDoWhileBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() },
   95.97 -//                new String[] { FmtOptions.redundantForBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() },
   95.98 -//                new String[] { FmtOptions.redundantIfBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() },
   95.99 -//                new String[] { FmtOptions.redundantWhileBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() }
  95.100 -        ); // NOI18N
  95.101 - */
  95.102 -    }
  95.103 -    
  95.104 -    /** This method is called from within the constructor to
  95.105 -     * initialize the form.
  95.106 -     * WARNING: Do NOT modify this code. The content of this method is
  95.107 -     * always regenerated by the Form Editor.
  95.108 -     */
  95.109 -    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  95.110 -    private void initComponents() {
  95.111 -        java.awt.GridBagConstraints gridBagConstraints;
  95.112 -
  95.113 -        scrollPane = new javax.swing.JScrollPane();
  95.114 -        panel1 = new javax.swing.JPanel();
  95.115 -        extendsImplemetsKeywordLabel = new javax.swing.JLabel();
  95.116 -        extendsImplementsKeywordCombo = new javax.swing.JComboBox();
  95.117 -        extendsImplementsListLabel = new javax.swing.JLabel();
  95.118 -        extendsImplementsListCombo = new javax.swing.JComboBox();
  95.119 -        methodParamsLabel = new javax.swing.JLabel();
  95.120 -        methodParamsCombo = new javax.swing.JComboBox();
  95.121 -        methodCallArgsLabel = new javax.swing.JLabel();
  95.122 -        methodCallArgsCombo = new javax.swing.JComboBox();
  95.123 -        annotationArgsLabel = new javax.swing.JLabel();
  95.124 -        annotationArgsCombo = new javax.swing.JComboBox();
  95.125 -        chainedMethodCallsLabel = new javax.swing.JLabel();
  95.126 -        chainedMethodCallsCombo = new javax.swing.JComboBox();
  95.127 -        throwsKeywordLabel = new javax.swing.JLabel();
  95.128 -        throwsKeywordCombo = new javax.swing.JComboBox();
  95.129 -        throwsListLabel = new javax.swing.JLabel();
  95.130 -        throwsListCombo = new javax.swing.JComboBox();
  95.131 -        arrayInitLabel = new javax.swing.JLabel();
  95.132 -        arrayInitCombo = new javax.swing.JComboBox();
  95.133 -        forLabel = new javax.swing.JLabel();
  95.134 -        forCombo = new javax.swing.JComboBox();
  95.135 -        forStatementLabel = new javax.swing.JLabel();
  95.136 -        forStatementCombo = new javax.swing.JComboBox();
  95.137 -        ifStatementLabel = new javax.swing.JLabel();
  95.138 -        ifStatementCombo = new javax.swing.JComboBox();
  95.139 -        whileStatementLabel = new javax.swing.JLabel();
  95.140 -        whileStatementComboBox = new javax.swing.JComboBox();
  95.141 -        doWhileStatementLabel = new javax.swing.JLabel();
  95.142 -        doWhileStatementCombo = new javax.swing.JComboBox();
  95.143 -        assertLabel = new javax.swing.JLabel();
  95.144 -        assertCombo = new javax.swing.JComboBox();
  95.145 -        enumConstantsLabel = new javax.swing.JLabel();
  95.146 -        enumConstantsCombo = new javax.swing.JComboBox();
  95.147 -        annotationsLabel = new javax.swing.JLabel();
  95.148 -        annotationsCombo = new javax.swing.JComboBox();
  95.149 -        binaryOpsLabel = new javax.swing.JLabel();
  95.150 -        binaryOpsCombo = new javax.swing.JComboBox();
  95.151 -        ternaryOpsLabel = new javax.swing.JLabel();
  95.152 -        ternaryOpsCombo = new javax.swing.JComboBox();
  95.153 -        assignOpsLabel = new javax.swing.JLabel();
  95.154 -        assignOpsCombo = new javax.swing.JComboBox();
  95.155 -        spacerPanel1 = new javax.swing.JPanel();
  95.156 -
  95.157 -        setName(org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_Wrapping")); // NOI18N
  95.158 -        setOpaque(false);
  95.159 -        setLayout(new java.awt.BorderLayout());
  95.160 -
  95.161 -        scrollPane.setMinimumSize(new java.awt.Dimension(300, 200));
  95.162 -        scrollPane.setPreferredSize(new java.awt.Dimension(350, 600));
  95.163 -
  95.164 -        panel1.setOpaque(false);
  95.165 -        panel1.setLayout(new java.awt.GridBagLayout());
  95.166 -
  95.167 -        extendsImplemetsKeywordLabel.setLabelFor(extendsImplementsKeywordCombo);
  95.168 -        org.openide.awt.Mnemonics.setLocalizedText(extendsImplemetsKeywordLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_extendsImplementsKeyword")); // NOI18N
  95.169 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.170 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.171 -        gridBagConstraints.insets = new java.awt.Insets(8, 8, 4, 0);
  95.172 -        panel1.add(extendsImplemetsKeywordLabel, gridBagConstraints);
  95.173 -
  95.174 -        extendsImplementsKeywordCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.175 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.176 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.177 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.178 -        gridBagConstraints.weightx = 1.0;
  95.179 -        gridBagConstraints.insets = new java.awt.Insets(8, 6, 4, 8);
  95.180 -        panel1.add(extendsImplementsKeywordCombo, gridBagConstraints);
  95.181 -
  95.182 -        extendsImplementsListLabel.setLabelFor(extendsImplementsListCombo);
  95.183 -        org.openide.awt.Mnemonics.setLocalizedText(extendsImplementsListLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_extendsImplementsList")); // NOI18N
  95.184 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.185 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.186 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.187 -        panel1.add(extendsImplementsListLabel, gridBagConstraints);
  95.188 -
  95.189 -        extendsImplementsListCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.190 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.191 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.192 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.193 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.194 -        panel1.add(extendsImplementsListCombo, gridBagConstraints);
  95.195 -
  95.196 -        methodParamsLabel.setLabelFor(methodParamsCombo);
  95.197 -        org.openide.awt.Mnemonics.setLocalizedText(methodParamsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_methodParameters")); // NOI18N
  95.198 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.199 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.200 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.201 -        panel1.add(methodParamsLabel, gridBagConstraints);
  95.202 -
  95.203 -        methodParamsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.204 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.205 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.206 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.207 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.208 -        panel1.add(methodParamsCombo, gridBagConstraints);
  95.209 -
  95.210 -        methodCallArgsLabel.setLabelFor(methodCallArgsCombo);
  95.211 -        org.openide.awt.Mnemonics.setLocalizedText(methodCallArgsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_methodCallArgs")); // NOI18N
  95.212 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.213 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.214 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.215 -        panel1.add(methodCallArgsLabel, gridBagConstraints);
  95.216 -
  95.217 -        methodCallArgsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.218 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.219 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.220 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.221 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.222 -        panel1.add(methodCallArgsCombo, gridBagConstraints);
  95.223 -
  95.224 -        annotationArgsLabel.setLabelFor(annotationArgsCombo);
  95.225 -        org.openide.awt.Mnemonics.setLocalizedText(annotationArgsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_annotationArgs")); // NOI18N
  95.226 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.227 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.228 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.229 -        panel1.add(annotationArgsLabel, gridBagConstraints);
  95.230 -
  95.231 -        annotationArgsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.232 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.233 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.234 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.235 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.236 -        panel1.add(annotationArgsCombo, gridBagConstraints);
  95.237 -
  95.238 -        chainedMethodCallsLabel.setLabelFor(chainedMethodCallsCombo);
  95.239 -        org.openide.awt.Mnemonics.setLocalizedText(chainedMethodCallsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_chainedMethodCalls")); // NOI18N
  95.240 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.241 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.242 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.243 -        panel1.add(chainedMethodCallsLabel, gridBagConstraints);
  95.244 -
  95.245 -        chainedMethodCallsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.246 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.247 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.248 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.249 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.250 -        panel1.add(chainedMethodCallsCombo, gridBagConstraints);
  95.251 -
  95.252 -        throwsKeywordLabel.setLabelFor(throwsKeywordCombo);
  95.253 -        org.openide.awt.Mnemonics.setLocalizedText(throwsKeywordLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_throwsKeyword")); // NOI18N
  95.254 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.255 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.256 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.257 -        panel1.add(throwsKeywordLabel, gridBagConstraints);
  95.258 -
  95.259 -        throwsKeywordCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.260 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.261 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.262 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.263 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.264 -        panel1.add(throwsKeywordCombo, gridBagConstraints);
  95.265 -
  95.266 -        throwsListLabel.setLabelFor(throwsListCombo);
  95.267 -        org.openide.awt.Mnemonics.setLocalizedText(throwsListLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_throwsList")); // NOI18N
  95.268 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.269 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.270 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.271 -        panel1.add(throwsListLabel, gridBagConstraints);
  95.272 -
  95.273 -        throwsListCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.274 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.275 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.276 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.277 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.278 -        panel1.add(throwsListCombo, gridBagConstraints);
  95.279 -
  95.280 -        arrayInitLabel.setLabelFor(arrayInitCombo);
  95.281 -        org.openide.awt.Mnemonics.setLocalizedText(arrayInitLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_arrayInit")); // NOI18N
  95.282 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.283 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.284 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.285 -        panel1.add(arrayInitLabel, gridBagConstraints);
  95.286 -
  95.287 -        arrayInitCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.288 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.289 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.290 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.291 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.292 -        panel1.add(arrayInitCombo, gridBagConstraints);
  95.293 -
  95.294 -        forLabel.setLabelFor(forCombo);
  95.295 -        org.openide.awt.Mnemonics.setLocalizedText(forLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_for")); // NOI18N
  95.296 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.297 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.298 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.299 -        panel1.add(forLabel, gridBagConstraints);
  95.300 -
  95.301 -        forCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.302 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.303 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.304 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.305 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.306 -        panel1.add(forCombo, gridBagConstraints);
  95.307 -
  95.308 -        forStatementLabel.setLabelFor(forStatementCombo);
  95.309 -        org.openide.awt.Mnemonics.setLocalizedText(forStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_forStatement")); // NOI18N
  95.310 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.311 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.312 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.313 -        panel1.add(forStatementLabel, gridBagConstraints);
  95.314 -
  95.315 -        forStatementCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.316 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.317 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.318 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.319 -        gridBagConstraints.weightx = 1.0;
  95.320 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.321 -        panel1.add(forStatementCombo, gridBagConstraints);
  95.322 -
  95.323 -        ifStatementLabel.setLabelFor(ifStatementCombo);
  95.324 -        org.openide.awt.Mnemonics.setLocalizedText(ifStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_ifStatement")); // NOI18N
  95.325 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.326 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.327 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.328 -        panel1.add(ifStatementLabel, gridBagConstraints);
  95.329 -
  95.330 -        ifStatementCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.331 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.332 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.333 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.334 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.335 -        panel1.add(ifStatementCombo, gridBagConstraints);
  95.336 -
  95.337 -        whileStatementLabel.setLabelFor(whileStatementComboBox);
  95.338 -        org.openide.awt.Mnemonics.setLocalizedText(whileStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_whileStatement")); // NOI18N
  95.339 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.340 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.341 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.342 -        panel1.add(whileStatementLabel, gridBagConstraints);
  95.343 -
  95.344 -        whileStatementComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.345 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.346 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.347 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.348 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.349 -        panel1.add(whileStatementComboBox, gridBagConstraints);
  95.350 -
  95.351 -        doWhileStatementLabel.setLabelFor(doWhileStatementCombo);
  95.352 -        org.openide.awt.Mnemonics.setLocalizedText(doWhileStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_doWhileStatement")); // NOI18N
  95.353 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.354 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.355 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.356 -        panel1.add(doWhileStatementLabel, gridBagConstraints);
  95.357 -
  95.358 -        doWhileStatementCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.359 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.360 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.361 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.362 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.363 -        panel1.add(doWhileStatementCombo, gridBagConstraints);
  95.364 -
  95.365 -        assertLabel.setLabelFor(assertCombo);
  95.366 -        org.openide.awt.Mnemonics.setLocalizedText(assertLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_assert")); // NOI18N
  95.367 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.368 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.369 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.370 -        panel1.add(assertLabel, gridBagConstraints);
  95.371 -
  95.372 -        assertCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.373 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.374 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.375 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.376 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.377 -        panel1.add(assertCombo, gridBagConstraints);
  95.378 -
  95.379 -        enumConstantsLabel.setLabelFor(enumConstantsCombo);
  95.380 -        org.openide.awt.Mnemonics.setLocalizedText(enumConstantsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_enumConstants")); // NOI18N
  95.381 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.382 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.383 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.384 -        panel1.add(enumConstantsLabel, gridBagConstraints);
  95.385 -
  95.386 -        enumConstantsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.387 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.388 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.389 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.390 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.391 -        panel1.add(enumConstantsCombo, gridBagConstraints);
  95.392 -
  95.393 -        annotationsLabel.setLabelFor(annotationsCombo);
  95.394 -        org.openide.awt.Mnemonics.setLocalizedText(annotationsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_annotations")); // NOI18N
  95.395 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.396 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.397 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.398 -        panel1.add(annotationsLabel, gridBagConstraints);
  95.399 -
  95.400 -        annotationsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.401 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.402 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.403 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.404 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.405 -        panel1.add(annotationsCombo, gridBagConstraints);
  95.406 -
  95.407 -        binaryOpsLabel.setLabelFor(binaryOpsCombo);
  95.408 -        org.openide.awt.Mnemonics.setLocalizedText(binaryOpsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_binaryOps")); // NOI18N
  95.409 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.410 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.411 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.412 -        panel1.add(binaryOpsLabel, gridBagConstraints);
  95.413 -
  95.414 -        binaryOpsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.415 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.416 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.417 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.418 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.419 -        panel1.add(binaryOpsCombo, gridBagConstraints);
  95.420 -
  95.421 -        ternaryOpsLabel.setLabelFor(ternaryOpsCombo);
  95.422 -        org.openide.awt.Mnemonics.setLocalizedText(ternaryOpsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_ternaryOps")); // NOI18N
  95.423 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.424 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.425 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.426 -        panel1.add(ternaryOpsLabel, gridBagConstraints);
  95.427 -
  95.428 -        ternaryOpsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.429 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.430 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.431 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.432 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.433 -        panel1.add(ternaryOpsCombo, gridBagConstraints);
  95.434 -
  95.435 -        assignOpsLabel.setLabelFor(assignOpsCombo);
  95.436 -        org.openide.awt.Mnemonics.setLocalizedText(assignOpsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_assignOps")); // NOI18N
  95.437 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.438 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  95.439 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  95.440 -        panel1.add(assignOpsLabel, gridBagConstraints);
  95.441 -
  95.442 -        assignOpsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  95.443 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.444 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.445 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  95.446 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  95.447 -        panel1.add(assignOpsCombo, gridBagConstraints);
  95.448 -
  95.449 -        spacerPanel1.setOpaque(false);
  95.450 -        gridBagConstraints = new java.awt.GridBagConstraints();
  95.451 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  95.452 -        gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER;
  95.453 -        gridBagConstraints.weighty = 1.0;
  95.454 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 8);
  95.455 -        panel1.add(spacerPanel1, gridBagConstraints);
  95.456 -
  95.457 -        scrollPane.setViewportView(panel1);
  95.458 -
  95.459 -        add(scrollPane, java.awt.BorderLayout.CENTER);
  95.460 -    }// </editor-fold>//GEN-END:initComponents
  95.461 -    
  95.462 -    // Variables declaration - do not modify//GEN-BEGIN:variables
  95.463 -    private javax.swing.JComboBox annotationArgsCombo;
  95.464 -    private javax.swing.JLabel annotationArgsLabel;
  95.465 -    private javax.swing.JComboBox annotationsCombo;
  95.466 -    private javax.swing.JLabel annotationsLabel;
  95.467 -    private javax.swing.JComboBox arrayInitCombo;
  95.468 -    private javax.swing.JLabel arrayInitLabel;
  95.469 -    private javax.swing.JComboBox assertCombo;
  95.470 -    private javax.swing.JLabel assertLabel;
  95.471 -    private javax.swing.JComboBox assignOpsCombo;
  95.472 -    private javax.swing.JLabel assignOpsLabel;
  95.473 -    private javax.swing.JComboBox binaryOpsCombo;
  95.474 -    private javax.swing.JLabel binaryOpsLabel;
  95.475 -    private javax.swing.JComboBox chainedMethodCallsCombo;
  95.476 -    private javax.swing.JLabel chainedMethodCallsLabel;
  95.477 -    private javax.swing.JComboBox doWhileStatementCombo;
  95.478 -    private javax.swing.JLabel doWhileStatementLabel;
  95.479 -    private javax.swing.JComboBox enumConstantsCombo;
  95.480 -    private javax.swing.JLabel enumConstantsLabel;
  95.481 -    private javax.swing.JComboBox extendsImplementsKeywordCombo;
  95.482 -    private javax.swing.JComboBox extendsImplementsListCombo;
  95.483 -    private javax.swing.JLabel extendsImplementsListLabel;
  95.484 -    private javax.swing.JLabel extendsImplemetsKeywordLabel;
  95.485 -    private javax.swing.JComboBox forCombo;
  95.486 -    private javax.swing.JLabel forLabel;
  95.487 -    private javax.swing.JComboBox forStatementCombo;
  95.488 -    private javax.swing.JLabel forStatementLabel;
  95.489 -    private javax.swing.JComboBox ifStatementCombo;
  95.490 -    private javax.swing.JLabel ifStatementLabel;
  95.491 -    private javax.swing.JComboBox methodCallArgsCombo;
  95.492 -    private javax.swing.JLabel methodCallArgsLabel;
  95.493 -    private javax.swing.JComboBox methodParamsCombo;
  95.494 -    private javax.swing.JLabel methodParamsLabel;
  95.495 -    private javax.swing.JPanel panel1;
  95.496 -    private javax.swing.JScrollPane scrollPane;
  95.497 -    private javax.swing.JPanel spacerPanel1;
  95.498 -    private javax.swing.JComboBox ternaryOpsCombo;
  95.499 -    private javax.swing.JLabel ternaryOpsLabel;
  95.500 -    private javax.swing.JComboBox throwsKeywordCombo;
  95.501 -    private javax.swing.JLabel throwsKeywordLabel;
  95.502 -    private javax.swing.JComboBox throwsListCombo;
  95.503 -    private javax.swing.JLabel throwsListLabel;
  95.504 -    private javax.swing.JComboBox whileStatementComboBox;
  95.505 -    private javax.swing.JLabel whileStatementLabel;
  95.506 -    // End of variables declaration//GEN-END:variables
  95.507 -    
  95.508 -}
    96.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/NumericKeyListener.java	Sat Sep 12 23:03:15 2015 -0700
    96.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.3 @@ -1,74 +0,0 @@
    96.4 -/*
    96.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    96.6 - *
    96.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    96.8 - *
    96.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   96.10 - * Other names may be trademarks of their respective owners.
   96.11 - *
   96.12 - * The contents of this file are subject to the terms of either the GNU
   96.13 - * General Public License Version 2 only ("GPL") or the Common
   96.14 - * Development and Distribution License("CDDL") (collectively, the
   96.15 - * "License"). You may not use this file except in compliance with the
   96.16 - * License. You can obtain a copy of the License at
   96.17 - * http://www.netbeans.org/cddl-gplv2.html
   96.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   96.19 - * specific language governing permissions and limitations under the
   96.20 - * License.  When distributing the software, include this License Header
   96.21 - * Notice in each file and include the License file at
   96.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   96.23 - * particular file as subject to the "Classpath" exception as provided
   96.24 - * by Oracle in the GPL Version 2 section of the License file that
   96.25 - * accompanied this code. If applicable, add the following below the
   96.26 - * License Header, with the fields enclosed by brackets [] replaced by
   96.27 - * your own identifying information:
   96.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   96.29 - *
   96.30 - * If you wish your version of this file to be governed by only the CDDL
   96.31 - * or only the GPL Version 2, indicate your decision by adding
   96.32 - * "[Contributor] elects to include this software in this distribution
   96.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   96.34 - * single choice of license, a recipient has the option to distribute
   96.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   96.36 - * to extend the choice of license to its licensees as provided above.
   96.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   96.38 - * Version 2 license, then the option applies only if the new code is
   96.39 - * made subject to such option by the copyright holder.
   96.40 - *
   96.41 - * Contributor(s):
   96.42 - *
   96.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   96.44 - */
   96.45 -package org.netbeans.modules.python.editor.options;
   96.46 -
   96.47 -import java.awt.Component;
   96.48 -import java.awt.event.KeyEvent;
   96.49 -import java.awt.event.KeyListener;
   96.50 -
   96.51 -/**
   96.52 - *
   96.53 - * @author tester
   96.54 - */
   96.55 -public class NumericKeyListener implements KeyListener {
   96.56 -    public NumericKeyListener() {
   96.57 -    }
   96.58 -
   96.59 -    @Override
   96.60 -    public void keyPressed(KeyEvent evt) {
   96.61 -    }
   96.62 -
   96.63 -    @Override
   96.64 -    public void keyReleased(KeyEvent evt) {
   96.65 -    }
   96.66 -
   96.67 -    @Override
   96.68 -    public void keyTyped(KeyEvent evt) {
   96.69 -        if (!Character.isDigit(evt.getKeyChar()) && !Character.isISOControl(evt.getKeyChar())) {
   96.70 -            evt.consume();
   96.71 -            Component c = evt.getComponent();
   96.72 -            if (c != null) {
   96.73 -                c.getToolkit().beep();
   96.74 -            }
   96.75 -        }
   96.76 -    }
   96.77 -}
    97.1 --- a/python.editor/src/org/netbeans/modules/python/editor/refactoring/PythonElementCtx.java	Sat Sep 12 23:03:15 2015 -0700
    97.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/refactoring/PythonElementCtx.java	Sun Sep 13 11:47:42 2015 +0200
    97.3 @@ -32,15 +32,15 @@
    97.4  
    97.5  import java.util.Iterator;
    97.6  
    97.7 -import org.netbeans.modules.python.editor.elements.AstElement;
    97.8 -import org.netbeans.modules.python.editor.elements.Element;
    97.9 +import org.netbeans.modules.python.source.elements.AstElement;
   97.10 +import org.netbeans.modules.python.source.elements.Element;
   97.11  import org.netbeans.editor.BaseDocument;
   97.12  import org.netbeans.modules.csl.api.ElementKind;
   97.13  import org.netbeans.modules.csl.spi.GsfUtilities;
   97.14 -import org.netbeans.modules.python.editor.AstPath;
   97.15 -import org.netbeans.modules.python.editor.PythonAstUtils;
   97.16 -import org.netbeans.modules.python.editor.PythonParserResult;
   97.17 -import org.netbeans.modules.python.editor.elements.IndexedElement;
   97.18 +import org.netbeans.modules.python.source.AstPath;
   97.19 +import org.netbeans.modules.python.source.PythonAstUtils;
   97.20 +import org.netbeans.modules.python.source.PythonParserResult;
   97.21 +import org.netbeans.modules.python.source.elements.IndexedElement;
   97.22  import org.openide.filesystems.FileObject;
   97.23  import org.python.antlr.PythonTree;
   97.24  import org.python.antlr.ast.Assign;
    98.1 --- a/python.editor/src/org/netbeans/modules/python/editor/refactoring/PythonRefUtils.java	Sat Sep 12 23:03:15 2015 -0700
    98.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/refactoring/PythonRefUtils.java	Sun Sep 13 11:47:42 2015 +0200
    98.3 @@ -72,10 +72,10 @@
    98.4  import org.netbeans.modules.csl.api.ElementKind;
    98.5  import org.netbeans.modules.parsing.api.Source;
    98.6  import org.netbeans.modules.python.api.PythonMIMEResolver;
    98.7 -import org.netbeans.modules.python.editor.PythonAstUtils;
    98.8 -import org.netbeans.modules.python.editor.PythonParserResult;
    98.9 -import org.netbeans.modules.python.editor.PythonUtils;
   98.10 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   98.11 +import org.netbeans.modules.python.source.PythonAstUtils;
   98.12 +import org.netbeans.modules.python.source.PythonParserResult;
   98.13 +import org.netbeans.modules.python.source.PythonUtils;
   98.14 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
   98.15  import org.openide.cookies.EditorCookie;
   98.16  import org.openide.filesystems.FileObject;
   98.17  import org.openide.util.Lookup;
    99.1 --- a/python.editor/src/org/netbeans/modules/python/editor/refactoring/PythonRefactoringsFactory.java	Sat Sep 12 23:03:15 2015 -0700
    99.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/refactoring/PythonRefactoringsFactory.java	Sun Sep 13 11:47:42 2015 +0200
    99.3 @@ -43,7 +43,7 @@
    99.4   */
    99.5  package org.netbeans.modules.python.editor.refactoring;
    99.6  
    99.7 -import org.netbeans.modules.python.editor.PythonUtils;
    99.8 +import org.netbeans.modules.python.source.PythonUtils;
    99.9  import org.netbeans.modules.refactoring.api.AbstractRefactoring;
   99.10  import org.netbeans.modules.refactoring.api.RenameRefactoring;
   99.11  import org.netbeans.modules.refactoring.api.WhereUsedQuery;
   100.1 --- a/python.editor/src/org/netbeans/modules/python/editor/refactoring/WhereUsedElement.java	Sat Sep 12 23:03:15 2015 -0700
   100.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/refactoring/WhereUsedElement.java	Sun Sep 13 11:47:42 2015 +0200
   100.3 @@ -54,9 +54,9 @@
   100.4  import org.netbeans.modules.csl.api.OffsetRange;
   100.5  import org.netbeans.modules.csl.api.UiUtils;
   100.6  import org.netbeans.modules.csl.spi.GsfUtilities;
   100.7 -import org.netbeans.modules.python.editor.PythonAstUtils;
   100.8 -import org.netbeans.modules.python.editor.PythonParserResult;
   100.9 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
  100.10 +import org.netbeans.modules.python.source.PythonAstUtils;
  100.11 +import org.netbeans.modules.python.source.PythonParserResult;
  100.12 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  100.13  import org.netbeans.modules.python.editor.refactoring.ui.ElementGripFactory;
  100.14  import org.netbeans.modules.refactoring.spi.SimpleRefactoringElementImplementation;
  100.15  import org.openide.filesystems.FileObject;
   101.1 --- a/python.editor/src/org/netbeans/modules/python/editor/refactoring/ui/RefactoringActionsProvider.java	Sat Sep 12 23:03:15 2015 -0700
   101.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/refactoring/ui/RefactoringActionsProvider.java	Sun Sep 13 11:47:42 2015 +0200
   101.3 @@ -64,14 +64,14 @@
   101.4  import org.netbeans.modules.refactoring.spi.ui.UI;
   101.5  import org.netbeans.modules.refactoring.spi.ui.ActionsImplementationProvider;
   101.6  import org.netbeans.modules.refactoring.spi.ui.RefactoringUI;
   101.7 -import org.netbeans.modules.python.editor.PythonAstUtils;
   101.8 -import org.netbeans.modules.python.editor.PythonIndex;
   101.9 -import org.netbeans.modules.python.editor.PythonParserResult;
  101.10 -import org.netbeans.modules.python.editor.PythonStructureScanner;
  101.11 -import org.netbeans.modules.python.editor.PythonStructureScanner.AnalysisResult;
  101.12 -import org.netbeans.modules.python.editor.PythonUtils;
  101.13 -import org.netbeans.modules.python.editor.elements.AstElement;
  101.14 -import org.netbeans.modules.python.editor.elements.Element;
  101.15 +import org.netbeans.modules.python.source.PythonAstUtils;
  101.16 +import org.netbeans.modules.python.source.PythonIndex;
  101.17 +import org.netbeans.modules.python.source.PythonParserResult;
  101.18 +import org.netbeans.modules.python.source.PythonStructureScanner;
  101.19 +import org.netbeans.modules.python.source.PythonStructureScanner.AnalysisResult;
  101.20 +import org.netbeans.modules.python.source.PythonUtils;
  101.21 +import org.netbeans.modules.python.source.elements.AstElement;
  101.22 +import org.netbeans.modules.python.source.elements.Element;
  101.23  import org.openide.ErrorManager;
  101.24  import org.openide.cookies.EditorCookie;
  101.25  import org.openide.filesystems.FileObject;
   102.1 --- a/python.editor/src/org/netbeans/modules/python/editor/scopes/ArgListCompiler.java	Sat Sep 12 23:03:15 2015 -0700
   102.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   102.3 @@ -1,121 +0,0 @@
   102.4 -// Copyright (c) Corporation for National Research Initiatives
   102.5 -package org.netbeans.modules.python.editor.scopes;
   102.6 -
   102.7 -import java.util.ArrayList;
   102.8 -
   102.9 -import java.util.List;
  102.10 -import org.python.antlr.PythonTree;
  102.11 -import org.python.antlr.Visitor;
  102.12 -import org.python.antlr.ast.Assign;
  102.13 -import org.python.antlr.ast.Name;
  102.14 -import org.python.antlr.ast.Suite;
  102.15 -import org.python.antlr.ast.Tuple;
  102.16 -import org.python.antlr.ast.arguments;
  102.17 -import org.python.antlr.ast.expr_contextType;
  102.18 -import org.python.antlr.base.expr;
  102.19 -import org.python.antlr.base.stmt;
  102.20 -
  102.21 -/** Based on org.python.compiler.ArgListCompiler */
  102.22 -public class ArgListCompiler extends Visitor {
  102.23 -    public boolean arglist, keywordlist;
  102.24 -    public List<expr> defaults;
  102.25 -    public List<String> names;
  102.26 -    public ArrayList<PythonTree> nodes;
  102.27 -    public List<String> fpnames;
  102.28 -    public List<stmt> init_code;
  102.29 -    private SymbolTable symbolTable;
  102.30 -
  102.31 -    public ArgListCompiler(SymbolTable symbolTable) {
  102.32 -        this.symbolTable = symbolTable;
  102.33 -        arglist = keywordlist = false;
  102.34 -        defaults = null;
  102.35 -        names = new ArrayList<>();
  102.36 -        nodes = new ArrayList<>();
  102.37 -        fpnames = new ArrayList<>();
  102.38 -        init_code = new ArrayList<>();
  102.39 -    }
  102.40 -
  102.41 -    public void reset() {
  102.42 -        arglist = keywordlist = false;
  102.43 -        defaults = null;
  102.44 -        names.clear();
  102.45 -        nodes.clear();
  102.46 -        init_code.clear();
  102.47 -    }
  102.48 -
  102.49 -    public void appendInitCode(Suite node) {
  102.50 -        node.getInternalBody().addAll(0, init_code);
  102.51 -    }
  102.52 -
  102.53 -    public List<expr> getDefaults() {
  102.54 -        return defaults;
  102.55 -    }
  102.56 -
  102.57 -    public void visitArgs(arguments args) throws Exception {
  102.58 -        for (int i = 0; i < args.getInternalArgs().size(); i++) {
  102.59 -            expr node = args.getInternalArgs().get(i);
  102.60 -            String name = (String)visit(node);
  102.61 -            names.add(name);
  102.62 -            nodes.add(node);
  102.63 -            if (node instanceof Tuple) {
  102.64 -                List<expr> targets = new ArrayList<>();
  102.65 -                targets.add(node);
  102.66 -                Assign ass = new Assign(node,
  102.67 -                        targets,
  102.68 -                        new Name(node, name, expr_contextType.Load));
  102.69 -                init_code.add(ass);
  102.70 -            }
  102.71 -        }
  102.72 -        if (args.getInternalVararg() != null) {
  102.73 -            arglist = true;
  102.74 -            names.add(args.getInternalVararg());
  102.75 -            //nodes.add(null); // no corresponding node?
  102.76 -            nodes.add(args); // just use the corresponding args node instead
  102.77 -        }
  102.78 -        if (args.getInternalKwarg() != null) {
  102.79 -            keywordlist = true;
  102.80 -            names.add(args.getInternalKwarg());
  102.81 -            //nodes.add(null); // no corresponding node?
  102.82 -            nodes.add(args); // just use the corresponding args node instead
  102.83 -        }
  102.84 -
  102.85 -        defaults = args.getInternalDefaults();
  102.86 -        for (int i = 0; i < defaults.size(); i++) {
  102.87 -            if (defaults.get(i) == null) {
  102.88 -                symbolTable.error("non-default argument follows default argument", true,
  102.89 -                        args.getInternalArgs().get(args.getInternalArgs().size() - defaults.size() + i));
  102.90 -            }
  102.91 -        }
  102.92 -    }
  102.93 -
  102.94 -    @Override
  102.95 -    public Object visitName(Name node) throws Exception {
  102.96 -        //FIXME: do we need Store and Param, or just Param?
  102.97 -        if (node.getInternalCtx() != expr_contextType.Store && node.getInternalCtx() != expr_contextType.Param) {
  102.98 -            return null;
  102.99 -        }
 102.100 -
 102.101 -        if (fpnames.contains(node.getInternalId())) {
 102.102 -            symbolTable.error("duplicate argument name found: " +
 102.103 -                    node.getInternalId(), true, node);
 102.104 -        }
 102.105 -        fpnames.add(node.getInternalId());
 102.106 -        return node.getInternalId();
 102.107 -    }
 102.108 -
 102.109 -    @Override
 102.110 -    public Object visitTuple(Tuple node) throws Exception {
 102.111 -        StringBuffer name = new StringBuffer("(");
 102.112 -        List<expr> elts = node.getInternalElts();
 102.113 -        if (elts != null) {
 102.114 -            int n = elts.size();
 102.115 -            for (int i = 0; i < n - 1; i++) {
 102.116 -                name.append(visit(elts.get(i)));
 102.117 -                name.append(", ");
 102.118 -            }
 102.119 -            name.append(visit(elts.get(n - 1)));
 102.120 -        }
 102.121 -        name.append(")");
 102.122 -        return name.toString();
 102.123 -    }
 102.124 -}
   103.1 --- a/python.editor/src/org/netbeans/modules/python/editor/scopes/ScopeConstants.java	Sat Sep 12 23:03:15 2015 -0700
   103.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   103.3 @@ -1,28 +0,0 @@
   103.4 -package org.netbeans.modules.python.editor.scopes;
   103.5 -
   103.6 -/** Based on org.python.compiler.ScopeConstants in Jython */
   103.7 -public interface ScopeConstants {
   103.8 -    public final static int BOUND = 1 << 0;
   103.9 -    public final static int NGLOBAL = 1 << 1; // func scope expl global
  103.10 -    public final static int PARAM = 1 << 2;
  103.11 -    public final static int FROM_PARAM = 1 << 3;
  103.12 -    public final static int CELL = 1 << 4;
  103.13 -    public final static int FREE = 1 << 5;
  103.14 -    public final static int CLASS_GLOBAL = 1 << 6; // class scope expl global
  103.15 -    public final static int READ = 1 << 7;
  103.16 -    public final static int CALLED = 1 << 8;
  103.17 -    public final static int DEF = 1 << 9;
  103.18 -    public final static int IMPORTED = 1 << 10;
  103.19 -    public final static int CLASS = 1 << 11;
  103.20 -    public final static int FUNCTION = 1 << 12;
  103.21 -    public final static int MEMBER = 1 << 13;
  103.22 -    public final static int GENERATOR = 1 << 13; // it's a generator expression
  103.23 -    public final static int PRIVATE = 1 << 14;
  103.24 -    public final static int ALIAS = 1 << 15;
  103.25 -    public final static int PROTECTED = 1 << 16;
  103.26 -    public final static int BOUND_IN_CONSTRUCTOR = 1 << 17;
  103.27 -    public final static int GLOBAL = NGLOBAL | CLASS_GLOBAL; // all global
  103.28 -    public final static int TOPSCOPE = 0;
  103.29 -    public final static int FUNCSCOPE = 1;
  103.30 -    public final static int CLASSSCOPE = 2;
  103.31 -}
   104.1 --- a/python.editor/src/org/netbeans/modules/python/editor/scopes/ScopeInfo.java	Sat Sep 12 23:03:15 2015 -0700
   104.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   104.3 @@ -1,575 +0,0 @@
   104.4 -// (C) Copyright 2001 Samuele Pedroni
   104.5 -package org.netbeans.modules.python.editor.scopes;
   104.6 -
   104.7 -import java.util.ArrayList;
   104.8 -import java.util.Collections;
   104.9 -import java.util.HashMap;
  104.10 -import java.util.LinkedHashMap;
  104.11 -import java.util.Map;
  104.12 -import java.util.List;
  104.13 -
  104.14 -import org.netbeans.modules.python.editor.AstPath;
  104.15 -import org.netbeans.modules.python.editor.PythonAstUtils;
  104.16 -import org.python.antlr.ParseException;
  104.17 -import org.python.antlr.PythonTree;
  104.18 -import org.python.antlr.ast.Assign;
  104.19 -import org.python.antlr.ast.Attribute;
  104.20 -import org.python.antlr.ast.ClassDef;
  104.21 -import org.python.antlr.ast.Name;
  104.22 -import org.python.antlr.ast.Return;
  104.23 -import org.python.antlr.ast.Tuple;
  104.24 -import org.python.antlr.base.expr;
  104.25 -import static org.netbeans.modules.python.editor.scopes.ScopeConstants.*;
  104.26 -
  104.27 -/** 
  104.28 - * Based on org.python.compiler.ScopeInfo in Jython
  104.29 - *
  104.30 - * See {@link ScopesCompiler} for details on my modifications
  104.31 - */
  104.32 -@SuppressWarnings("unchecked")
  104.33 -public class ScopeInfo extends Object {
  104.34 -    public PythonTree scope_node;
  104.35 -    public String scope_name;
  104.36 -    public int level;
  104.37 -    public int func_level;
  104.38 -    public boolean hidden;
  104.39 -
  104.40 -    public String dump() {
  104.41 -        StringBuilder sb = new StringBuilder();
  104.42 -
  104.43 -        for (int i = 0; i < level; i++) {
  104.44 -            sb.append("    ");
  104.45 -        }
  104.46 -        sb.append("=============================================\n");
  104.47 -        for (int i = 0; i < level; i++) {
  104.48 -            sb.append("    ");
  104.49 -        }
  104.50 -        sb.append(((kind != CLASSSCOPE) ? scope_name : "class " +
  104.51 -                scope_name) + ": " + scope_node + " : " + PythonAstUtils.getRange(scope_node) + "\n");
  104.52 -        //for(int i=0; i<level; i++) sb.append("    ");
  104.53 -        //sb.append("UP=" + up);
  104.54 -        //sb.append("   NESTED=" + nested);
  104.55 -        //sb.append("\n");
  104.56 -
  104.57 -
  104.58 -        // Sort to make test output stable
  104.59 -        List<String> keys = new ArrayList<>(tbl.keySet());
  104.60 -        Collections.sort(keys);
  104.61 -        for (String name : keys) {
  104.62 -            SymInfo info = tbl.get(name);
  104.63 -            for (int i = 0; i < level; i++) {
  104.64 -                sb.append("    ");
  104.65 -            }
  104.66 -            sb.append(name);
  104.67 -            sb.append(" ");
  104.68 -            sb.append(info.dumpFlags(this));
  104.69 -            sb.append("\n");
  104.70 -        }
  104.71 -
  104.72 -        if (inner_free.size() > 0 || cellvars.size() > 0 || jy_paramcells.size() > 0 ||
  104.73 -                jy_npurecell != 0 /*|| cell != 0 || distance != 0 || up != null*/) {
  104.74 -            for (int i = 0; i < level; i++) {
  104.75 -                sb.append("    ");
  104.76 -            }
  104.77 -            sb.append("---------------------------------------------\n");
  104.78 -        }
  104.79 -
  104.80 -        if (inner_free.size() > 0) {
  104.81 -            List<String> sorted = new ArrayList<>();
  104.82 -            for (String s : inner_free.keySet()) {
  104.83 -                sorted.add(s + "=" + inner_free.get(s));
  104.84 -            }
  104.85 -            Collections.sort(sorted);
  104.86 -
  104.87 -            for (int i = 0; i < level; i++) {
  104.88 -                sb.append("    ");
  104.89 -            }
  104.90 -            sb.append("inner_free: {"); // NOI18N
  104.91 -            boolean first = true;
  104.92 -            for (String s : sorted) {
  104.93 -                if (first) {
  104.94 -                    first = false;
  104.95 -                } else {
  104.96 -                    sb.append(", "); // NOI18N
  104.97 -                }
  104.98 -                sb.append(s);
  104.99 -            }
 104.100 -            sb.append("}\n"); // NOI18N
 104.101 -        }
 104.102 -        if (cellvars.size() > 0) {
 104.103 -            Collections.sort(cellvars);
 104.104 -            for (int i = 0; i < level; i++) {
 104.105 -                sb.append("    ");
 104.106 -            }
 104.107 -            sb.append("cellvars: " + cellvars.toString() + "\n"); // TODO - sort
 104.108 -        }
 104.109 -        if (jy_paramcells.size() > 0) {
 104.110 -            Collections.sort(jy_paramcells);
 104.111 -            for (int i = 0; i < level; i++) {
 104.112 -                sb.append("    ");
 104.113 -            }
 104.114 -            sb.append("jy_paramcells: " + jy_paramcells.toString() + "\n"); // TODO - sort
 104.115 -        }
 104.116 -        if (jy_npurecell != 0) {
 104.117 -            for (int i = 0; i < level; i++) {
 104.118 -                sb.append("    ");
 104.119 -            }
 104.120 -            sb.append("jy_npurecell: " + jy_npurecell + "\n"); // TODO - sort
 104.121 -        }
 104.122 -        //if (cell != 0) {
 104.123 -        //    for(int i=0; i<level; i++) sb.append("    ");
 104.124 -        //    sb.append("cell: " + cell + "\n"); // TODO - sort
 104.125 -        //}
 104.126 -        //if (distance != 0) {
 104.127 -        //    for(int i=0; i<level; i++) sb.append("    ");
 104.128 -        //    sb.append("distance: " + distance + "\n"); // TODO - sort
 104.129 -        //}
 104.130 -        //if (up != null) {
 104.131 -        //    for(int i=0; i<level; i++) sb.append("    ");
 104.132 -        //    sb.append("up: " + up.scope_node);
 104.133 -        //}
 104.134 -
 104.135 -        if (attributes.size() > 0) {
 104.136 -            for (int i = 0; i < level; i++) {
 104.137 -                sb.append("    ");
 104.138 -            }
 104.139 -            sb.append("------ Attributes ---------------------------------------\n"); // NOI18N
 104.140 -            // Sort
 104.141 -            List<String> attributeNames = new ArrayList<>(attributes.keySet());
 104.142 -            Collections.sort(attributeNames);
 104.143 -            for (String attributeName : attributeNames) {
 104.144 -                for (int i = 0; i < level; i++) {
 104.145 -                    sb.append("    ");
 104.146 -                }
 104.147 -                sb.append(attributeName);
 104.148 -                sb.append(" : "); // NOI18N
 104.149 -                sb.append(attributes.get(attributeName));
 104.150 -                sb.append("\n"); // NOI18N
 104.151 -            }
 104.152 -        }
 104.153 -
 104.154 -        return sb.toString();
 104.155 -    }
 104.156 -
 104.157 -    public ScopeInfo(String name, PythonTree node, int level, int kind,
 104.158 -            int func_level, ArgListCompiler ac) {
 104.159 -        scope_name = name;
 104.160 -        scope_node = node;
 104.161 -        this.level = level;
 104.162 -        this.kind = kind;
 104.163 -        this.func_level = func_level;
 104.164 -        this.ac = ac;
 104.165 -    }
 104.166 -    public int kind;
 104.167 -    public boolean unqual_exec;
 104.168 -    public boolean exec;
 104.169 -    public boolean from_import_star;
 104.170 -    public boolean contains_ns_free_vars;
 104.171 -    public boolean generator;
 104.172 -    private boolean hasReturnWithValue;
 104.173 -    public int yield_count;
 104.174 -    public int max_with_count;
 104.175 -    public ArgListCompiler ac;
 104.176 -    public Map<String, SymInfo> tbl = new LinkedHashMap<>();
 104.177 -
 104.178 -    // define a separate dictionary for dynamic bounded variables
 104.179 -    public Map<String, SymInfo> attributes = new HashMap<>();
 104.180 -    public List<String> names = new ArrayList<>();
 104.181 -
 104.182 -    private void addAttributeEntry(String name, PythonTree node, int flags) {
 104.183 -        SymInfo info = attributes.get(name);
 104.184 -        if (info == null) {
 104.185 -            SymInfo entry = new SymInfo(flags);
 104.186 -            if (SymInfo.isPrivateName(name)) {
 104.187 -                entry.flags |= PRIVATE;
 104.188 -            } else if (SymInfo.isProtectedName(name)) {
 104.189 -                entry.flags |= PROTECTED;
 104.190 -            }
 104.191 -            entry.node = node;
 104.192 -            attributes.put(name, entry);
 104.193 -        }
 104.194 -    }
 104.195 -
 104.196 -    private void addToClassScope(String name, PythonTree node, boolean inConstructor) {
 104.197 -        int flags = CLASSSCOPE | BOUND | MEMBER;
 104.198 -        if (inConstructor) {
 104.199 -            flags |= BOUND_IN_CONSTRUCTOR;
 104.200 -        }
 104.201 -        addAttributeEntry(name, node, flags);
 104.202 -    }
 104.203 -
 104.204 -    public ScopeInfo getClassScope() {
 104.205 -        ScopeInfo cur = this;
 104.206 -        while ((cur != null) &&
 104.207 -                (!(cur.scope_node instanceof ClassDef))) {
 104.208 -            cur = cur.nested;
 104.209 -        }
 104.210 -        return cur;
 104.211 -    }
 104.212 -
 104.213 -    private boolean belongsToExprList(List<expr> types, expr cur) {
 104.214 -        return types != null && types.contains(cur);
 104.215 -    }
 104.216 -
 104.217 -    boolean isAttributeAssigment(AstPath path, Attribute attr) {
 104.218 -        PythonTree leaf = path.leaf();
 104.219 -        Assign assign = null;
 104.220 -        expr target = attr; // default to single
 104.221 -        if (leaf instanceof Assign) {
 104.222 -            assign = (Assign)leaf;
 104.223 -        } else if (leaf instanceof Tuple) {
 104.224 -            // check for tuple assignment
 104.225 -            Tuple tuple = (Tuple)leaf;
 104.226 -            PythonTree tupleParent = path.leafParent();
 104.227 -            if (belongsToExprList(tuple.getInternalElts(), attr)) {
 104.228 -                if (tupleParent instanceof Assign) {
 104.229 -                    assign = (Assign)tupleParent;
 104.230 -                    target = tuple; // tuple assignment target
 104.231 -                }
 104.232 -            }
 104.233 -        }
 104.234 -        // check if we got assignment
 104.235 -        if (assign == null) {
 104.236 -            return false;
 104.237 -        }
 104.238 -        if (belongsToExprList(assign.getInternalTargets(), target)) {
 104.239 -            return true;
 104.240 -        }
 104.241 -        return false;
 104.242 -    }
 104.243 -
 104.244 -    public void addAttribute(AstPath path, String name, PythonTree node) {
 104.245 -        // deeply check assignment context for attribute.
 104.246 -        Attribute curAttr = (Attribute)node;
 104.247 -
 104.248 -        if (curAttr.getInternalValue() instanceof Attribute) {
 104.249 -            // recursice attributes( x.y.z.w ) to be handled later
 104.250 -        } else if (curAttr.getInternalValue() instanceof Name) {
 104.251 -
 104.252 -            Name parentName = (Name)curAttr.getInternalValue();
 104.253 -
 104.254 -            ScopeInfo classScope = getClassScope();
 104.255 -            boolean inConstructor = false;
 104.256 -            String parName = parentName.getInternalId();
 104.257 -
 104.258 -            // for simplicity handle only at classScope in current source
 104.259 -            if (classScope != null) {
 104.260 -                // check for self or inherited parent name prefix
 104.261 -                if ((parName.equals("self")) ||
 104.262 -                        (PythonAstUtils.getParentClassFromNode(path, classScope.scope_node, parName) != null)) {
 104.263 -                    if (!(parName.equals("self"))) {
 104.264 -                        // check classname not overridden by local scope variable
 104.265 -                        if (tbl.get(parName) != null) {
 104.266 -                            return;
 104.267 -                        }
 104.268 -                    }
 104.269 -                    if (scope_name.equals("__init__") || scope_name.equals("__new__")) {
 104.270 -                        inConstructor = true; // set in constructor
 104.271 -                    }
 104.272 -                    //
 104.273 -                    // put in class scope
 104.274 -                    if (isAttributeAssigment(path, curAttr)) {
 104.275 -                        classScope.addToClassScope(name, node, inConstructor);
 104.276 -                    } else {
 104.277 -                        // store at current scope if parName is not overriding
 104.278 -                        // classname at current scope
 104.279 -                        int flags = CLASSSCOPE | READ;
 104.280 -                        addAttributeEntry(name, node, flags);
 104.281 -                    }
 104.282 -                }
 104.283 -            }
 104.284 -        }
 104.285 -    }
 104.286 -
 104.287 -    public int addGlobal(String name, PythonTree node) {
 104.288 -        // global kind = func vs. class
 104.289 -        int global = kind == CLASSSCOPE ? CLASS_GLOBAL : NGLOBAL;
 104.290 -        SymInfo info = tbl.get(name);
 104.291 -        if (info == null) {
 104.292 -            SymInfo entry = new SymInfo(global | BOUND);
 104.293 -            if (SymInfo.isPrivateName(name)) {
 104.294 -                entry.flags |= PRIVATE;
 104.295 -            } else if (SymInfo.isProtectedName(name)) {
 104.296 -                entry.flags |= PROTECTED;
 104.297 -            }
 104.298 -            entry.node = node;
 104.299 -            tbl.put(name, entry);
 104.300 -            return -1;
 104.301 -        }
 104.302 -        int prev = info.flags;
 104.303 -        info.flags |= global | BOUND;
 104.304 -        return prev;
 104.305 -    }
 104.306 -    public int local = 0;
 104.307 -
 104.308 -    public void addParam(String name, PythonTree node) {
 104.309 -        SymInfo entry = new SymInfo(PARAM | BOUND, local++);
 104.310 -        entry.node = node;
 104.311 -        tbl.put(name, entry);
 104.312 -        names.add(name);
 104.313 -    }
 104.314 -
 104.315 -    // <netbeans>
 104.316 -    public boolean isUnused(String name) {
 104.317 -        SymInfo info = tbl.get(name);
 104.318 -        if (info != null) {
 104.319 -            return info.isUnused(this);
 104.320 -        }
 104.321 -        return false;
 104.322 -    }
 104.323 -
 104.324 -    public boolean isParameter(String name) {
 104.325 -        SymInfo info = tbl.get(name);
 104.326 -        if (info != null) {
 104.327 -            return info.isParameter();
 104.328 -        }
 104.329 -        return false;
 104.330 -    }
 104.331 -    // </netbeans>
 104.332 -
 104.333 -    public void markFromParam() {
 104.334 -        for (SymInfo info : tbl.values()) {
 104.335 -            info.flags |= FROM_PARAM;
 104.336 -        }
 104.337 -    }
 104.338 -
 104.339 -    public SymInfo addBound(String name, PythonTree node) {
 104.340 -        SymInfo info = tbl.get(name);
 104.341 -        if (info == null) {
 104.342 -            info = new SymInfo(BOUND);
 104.343 -            if (SymInfo.isPrivateName(name)) {
 104.344 -                info.flags |= PRIVATE;
 104.345 -            } else if (SymInfo.isProtectedName(name)) {
 104.346 -                info.flags |= PROTECTED;
 104.347 -            }
 104.348 -            tbl.put(name, info);
 104.349 -            info.node = node;
 104.350 -            return info;
 104.351 -        }
 104.352 -        info.flags |= BOUND;
 104.353 -
 104.354 -        return info;
 104.355 -    }
 104.356 -
 104.357 -    public SymInfo addUsed(String name, PythonTree node) {
 104.358 -        SymInfo info = tbl.get(name);
 104.359 -        if (info == null) {
 104.360 -            // <netbeans>
 104.361 -            info = new SymInfo(0);
 104.362 -            tbl.put(name, info);
 104.363 -            info.node = node;
 104.364 -        }
 104.365 -        info.flags |= READ;
 104.366 -
 104.367 -        return info;
 104.368 -        // </netbeans>
 104.369 -    }
 104.370 -
 104.371 -
 104.372 -    // <netbeans>
 104.373 -    void markCall(String name) {
 104.374 -        SymInfo entry = tbl.get(name);
 104.375 -        if (entry != null) {
 104.376 -            entry.flags |= CALLED;
 104.377 -        }
 104.378 -    }
 104.379 -    // </netbeans>
 104.380 -    private final static String PRESENT = new String("PRESENT");
 104.381 -    public HashMap<String, String> inner_free = new HashMap<>();
 104.382 -    public List<String> cellvars = new ArrayList<>();
 104.383 -    public List<String> jy_paramcells = new ArrayList<>();
 104.384 -    public int jy_npurecell;
 104.385 -    public int cell, distance;
 104.386 -    public ScopeInfo up;
 104.387 -    public ScopeInfo nested;
 104.388 -
 104.389 -    //Resolve the names used in the given scope, and mark any freevars used in the up scope
 104.390 -    public void cook(ScopeInfo up, int distance, SymbolTable ctxt) throws Exception {
 104.391 -        if (up == null) {
 104.392 -            return; // top level => nop
 104.393 -        }
 104.394 -        this.up = up;
 104.395 -        this.distance = distance;
 104.396 -        boolean func = kind == FUNCSCOPE;
 104.397 -        List<String> purecells = new ArrayList<>();
 104.398 -        cell = 0;
 104.399 -        boolean some_inner_free = inner_free.size() > 0;
 104.400 -
 104.401 -        for (String name : inner_free.keySet()) {
 104.402 -
 104.403 -            SymInfo info = tbl.get(name);
 104.404 -            if (info == null) {
 104.405 -                tbl.put(name, new SymInfo(FREE));
 104.406 -                continue;
 104.407 -            }
 104.408 -            int flags = info.flags;
 104.409 -            if (func) {
 104.410 -                // not func global and bound ?
 104.411 -                if ((flags & NGLOBAL) == 0 && (flags & BOUND) != 0) {
 104.412 -                    info.flags |= CELL;
 104.413 -                    if ((info.flags & PARAM) != 0) {
 104.414 -                        jy_paramcells.add(name);
 104.415 -                    }
 104.416 -                    cellvars.add(name);
 104.417 -                    info.env_index = cell++;
 104.418 -                    if ((flags & PARAM) == 0) {
 104.419 -                        purecells.add(name);
 104.420 -                    }
 104.421 -                    continue;
 104.422 -                }
 104.423 -            } else {
 104.424 -                info.flags |= FREE;
 104.425 -            }
 104.426 -        }
 104.427 -        boolean some_free = false;
 104.428 -
 104.429 -        boolean nested = up.kind != TOPSCOPE;
 104.430 -        for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
 104.431 -            String name = entry.getKey();
 104.432 -            SymInfo info = entry.getValue();
 104.433 -            int flags = info.flags;
 104.434 -            if (nested && (flags & FREE) != 0) {
 104.435 -                up.inner_free.put(name, PRESENT);
 104.436 -            }
 104.437 -            if ((flags & (GLOBAL | PARAM | CELL)) == 0) {
 104.438 -                if ((flags & BOUND) != 0) { // ?? only func
 104.439 -                    // System.err.println("local: "+name);
 104.440 -                    names.add(name);
 104.441 -                    info.locals_index = local++;
 104.442 -                    continue;
 104.443 -                }
 104.444 -                info.flags |= FREE;
 104.445 -                some_free = true;
 104.446 -                if (nested) {
 104.447 -                    up.inner_free.put(name, PRESENT);
 104.448 -                }
 104.449 -            }
 104.450 -
 104.451 -            // <netbeans>
 104.452 -            if ((info.flags & FREE) != 0) {
 104.453 -                // Mark definition symbol as read as well
 104.454 -                ScopeInfo curr = up;
 104.455 -                while (curr != null) {
 104.456 -                    SymInfo s = curr.tbl.get(name);
 104.457 -                    if (s != null && ((s.flags & BOUND) != 0)) {
 104.458 -                        s.flags |= READ;
 104.459 -                        s.flags |= (info.flags & (CALLED));
 104.460 -                        break;
 104.461 -                    }
 104.462 -                    curr = curr.up;
 104.463 -                    while (curr != null && curr.kind == CLASSSCOPE) {
 104.464 -                        curr = curr.up;
 104.465 -                    }
 104.466 -                }
 104.467 -            }
 104.468 -
 104.469 -            // </netbeans>
 104.470 -        }
 104.471 -        if ((jy_npurecell = purecells.size()) > 0) {
 104.472 -            int sz = purecells.size();
 104.473 -            for (int i = 0; i < sz; i++) {
 104.474 -                names.add(purecells.get(i));
 104.475 -            }
 104.476 -        }
 104.477 -
 104.478 -        if (some_free && nested) {
 104.479 -            up.contains_ns_free_vars = true;
 104.480 -        }
 104.481 -        // XXX - this doesn't catch all cases - may depend subtly
 104.482 -        // on how visiting NOW works with antlr compared to javacc
 104.483 -        if ((unqual_exec || from_import_star)) {
 104.484 -            if (some_inner_free) {
 104.485 -                dynastuff_trouble(true, ctxt);
 104.486 -            } else if (func_level > 1 && some_free) {
 104.487 -                dynastuff_trouble(false, ctxt);
 104.488 -            }
 104.489 -        }
 104.490 -
 104.491 -    }
 104.492 -
 104.493 -    private void dynastuff_trouble(boolean inner_free,
 104.494 -            SymbolTable ctxt) throws Exception {
 104.495 -        String illegal;
 104.496 -        if (unqual_exec && from_import_star) {
 104.497 -            illegal = "function '" + scope_name +
 104.498 -                    "' uses import * and bare exec, which are illegal";
 104.499 -        } else if (unqual_exec) {
 104.500 -            illegal = "unqualified exec is not allowed in function '" +
 104.501 -                    scope_name + "'";
 104.502 -        } else {
 104.503 -            illegal = "import * is not allowed in function '" + scope_name + "'";
 104.504 -        }
 104.505 -        String why;
 104.506 -        if (inner_free) {
 104.507 -            why = " because it contains a function with free variables";
 104.508 -        } else {
 104.509 -            why = " because it contains free variables";
 104.510 -        }
 104.511 -        ctxt.error(illegal + why, true, scope_node);
 104.512 -    }
 104.513 -    public List<String> freevars = new ArrayList<>();
 104.514 -
 104.515 -    /**
 104.516 -     * setup the closure on this scope using the scope passed into cook as up as
 104.517 -     * the containing scope
 104.518 -     */
 104.519 -    public void setup_closure() {
 104.520 -        setup_closure(up);
 104.521 -    }
 104.522 -
 104.523 -    /**
 104.524 -     * setup the closure on this scope using the passed in scope. This is used
 104.525 -     * by jythonc to setup its closures.
 104.526 -     */
 104.527 -    public void setup_closure(ScopeInfo up) {
 104.528 -        int free = cell; // env = cell...,free...
 104.529 -        Map<String, SymInfo> up_tbl = up.tbl;
 104.530 -        boolean nested = up.kind != TOPSCOPE;
 104.531 -        for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
 104.532 -            String name = entry.getKey();
 104.533 -            SymInfo info = entry.getValue();
 104.534 -            int flags = info.flags;
 104.535 -            if ((flags & FREE) != 0) {
 104.536 -                SymInfo up_info = up_tbl.get(name);
 104.537 -                // ?? differs from CPython -- what is the intended behaviour?
 104.538 -                if (up_info != null) {
 104.539 -                    int up_flags = up_info.flags;
 104.540 -                    if ((up_flags & (CELL | FREE)) != 0) {
 104.541 -                        info.env_index = free++;
 104.542 -                        freevars.add(name);
 104.543 -                        continue;
 104.544 -                    }
 104.545 -                    // ! func global affect nested scopes
 104.546 -                    if (nested && (up_flags & NGLOBAL) != 0) {
 104.547 -                        info.flags = NGLOBAL | BOUND;
 104.548 -                        continue;
 104.549 -                    }
 104.550 -                }
 104.551 -                info.flags &= ~FREE;
 104.552 -            }
 104.553 -        }
 104.554 -
 104.555 -    }
 104.556 -
 104.557 -    @Override
 104.558 -    public String toString() {
 104.559 -        return "ScopeInfo[" + scope_name + " " + kind + "]@" +
 104.560 -                System.identityHashCode(this);
 104.561 -    }
 104.562 -
 104.563 -    public void defineAsGenerator(expr node) {
 104.564 -        generator = true;
 104.565 -        if (hasReturnWithValue) {
 104.566 -            throw new ParseException("'return' with argument " +
 104.567 -                    "inside generator", node);
 104.568 -        }
 104.569 -    }
 104.570 -
 104.571 -    public void noteReturnValue(Return node) {
 104.572 -        if (generator) {
 104.573 -            throw new ParseException("'return' with argument " +
 104.574 -                    "inside generator", node);
 104.575 -        }
 104.576 -        hasReturnWithValue = true;
 104.577 -    }
 104.578 -}
   105.1 --- a/python.editor/src/org/netbeans/modules/python/editor/scopes/ScopesCompiler.java	Sat Sep 12 23:03:15 2015 -0700
   105.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   105.3 @@ -1,641 +0,0 @@
   105.4 -// (C) Copyright 2001 Samuele Pedroni
   105.5 -package org.netbeans.modules.python.editor.scopes;
   105.6 -
   105.7 -import java.util.ArrayList;
   105.8 -import java.util.List;
   105.9 -import java.util.Map;
  105.10 -import java.util.Set;
  105.11 -import java.util.Stack;
  105.12 -import org.netbeans.modules.python.editor.AstPath;
  105.13 -import org.openide.util.Exceptions;
  105.14 -import org.python.antlr.PythonTree;
  105.15 -import org.python.antlr.Visitor;
  105.16 -import org.python.antlr.ast.Assign;
  105.17 -import org.python.antlr.ast.Attribute;
  105.18 -import org.python.antlr.ast.Call;
  105.19 -import org.python.antlr.ast.ClassDef;
  105.20 -import org.python.antlr.ast.Delete;
  105.21 -import org.python.antlr.ast.Exec;
  105.22 -import org.python.antlr.ast.Expression;
  105.23 -import org.python.antlr.ast.FunctionDef;
  105.24 -import org.python.antlr.ast.GeneratorExp;
  105.25 -import org.python.antlr.ast.Global;
  105.26 -import org.python.antlr.ast.Import;
  105.27 -import org.python.antlr.ast.ImportFrom;
  105.28 -import org.python.antlr.ast.Interactive;
  105.29 -import org.python.antlr.ast.Lambda;
  105.30 -import org.python.antlr.ast.ListComp;
  105.31 -import org.python.antlr.ast.Name;
  105.32 -import org.python.antlr.ast.Return;
  105.33 -import org.python.antlr.ast.Str;
  105.34 -import org.python.antlr.ast.With;
  105.35 -import org.python.antlr.ast.Yield;
  105.36 -import org.python.antlr.ast.alias;
  105.37 -import org.python.antlr.ast.arguments;
  105.38 -import org.python.antlr.base.expr;
  105.39 -import org.python.antlr.ast.expr_contextType;
  105.40 -import org.python.antlr.base.stmt;
  105.41 -
  105.42 -/** 
  105.43 - * Based on org.python.compiler.ScopesCompiler in Jython
  105.44 - *
  105.45 - * Modifications I've made:
  105.46 - * - Methods for finding all the free variables
  105.47 - * - Methods for identifying unused bound variables
  105.48 - * - Track whether symbols are referenced as calls or not
  105.49 - *   (so I can determine whether to look in the index for
  105.50 - *    functions or data etc. when trying to resolve imports)
  105.51 - * - Track variable reads/writes
  105.52 - * - Track imports etc.
  105.53 - * - Add nodes to each SymInfo
  105.54 - * - Replace old style Java (Hashtable, Vector, implements ScopeConstants) with
  105.55 - *   modern Java (HashMap, ArrayList, import static)
  105.56 - * 
  105.57 - */
  105.58 -@SuppressWarnings("unchecked")
  105.59 -public class ScopesCompiler extends Visitor implements ScopeConstants {
  105.60 -    private SymbolTable symbolTable;
  105.61 -    private Stack scopes;
  105.62 -    private ScopeInfo cur = null;
  105.63 -    private Map<PythonTree, ScopeInfo> nodeScopes;
  105.64 -    private int level = 0;
  105.65 -    private int func_level = 0;
  105.66 -    private List<Import> imports;
  105.67 -    private List<PythonTree> mainImports;
  105.68 -    private List<ImportFrom> importsFrom;
  105.69 -    private Set<PythonTree> topLevelImports;
  105.70 -    private PythonTree root;
  105.71 -    private PythonTree parent;
  105.72 -    private AstPath path = new AstPath();
  105.73 -    /** List of symbols registered via __all__ = [ "foo", "bar" ] or __all__.extend() or __all__.append() */
  105.74 -    private List<Str> publicSymbols;
  105.75 -    /** Set to true if we encountered manipulation on __all__ that I don't understand */
  105.76 -    private boolean invalidPublicSymbols;
  105.77 -
  105.78 -    public ScopesCompiler(SymbolTable symbolTable, Map<PythonTree, ScopeInfo> nodeScopes, PythonTree root,
  105.79 -            List<Import> imports, List<ImportFrom> importsFrom, List<PythonTree> mainImports, Set<PythonTree> topLevelImports) {
  105.80 -        this.symbolTable = symbolTable;
  105.81 -        this.nodeScopes = nodeScopes;
  105.82 -        scopes = new Stack();
  105.83 -        this.root = root;
  105.84 -
  105.85 -        this.imports = imports;
  105.86 -        this.importsFrom = importsFrom;
  105.87 -        this.mainImports = mainImports;
  105.88 -        this.topLevelImports = topLevelImports;
  105.89 -    }
  105.90 -
  105.91 -    @Override
  105.92 -    public void traverse(PythonTree node) throws Exception {
  105.93 -        // Jython's parser often doesn't set the parent references correctly
  105.94 -        // so try to fix that here
  105.95 -        node.setParent(parent);
  105.96 -
  105.97 -        PythonTree oldParent = parent;
  105.98 -        parent = node;
  105.99 -
 105.100 -        path.descend(node);
 105.101 -        super.traverse(node);
 105.102 -        parent = oldParent;
 105.103 -        path.ascend();
 105.104 -    }
 105.105 -
 105.106 -    public void beginScope(String name, int kind, PythonTree node,
 105.107 -            ArgListCompiler ac) {
 105.108 -        if (cur != null) {
 105.109 -            scopes.push(cur);
 105.110 -        }
 105.111 -        if (kind == FUNCSCOPE) {
 105.112 -            func_level++;
 105.113 -        }
 105.114 -        cur = new ScopeInfo(name, node, level++, kind, func_level, ac);
 105.115 -        nodeScopes.put(node, cur);
 105.116 -    }
 105.117 -
 105.118 -    public void endScope() throws Exception {
 105.119 -        if (cur.kind == FUNCSCOPE) {
 105.120 -            func_level--;
 105.121 -        }
 105.122 -        level--;
 105.123 -        ScopeInfo up = null;
 105.124 -        if (!scopes.empty()) {
 105.125 -            up = (ScopeInfo)scopes.pop();
 105.126 -        }
 105.127 -        //Go into the stack to find a non class containing scope to use making the closure
 105.128 -        //See PEP 227
 105.129 -        int dist = 1;
 105.130 -        ScopeInfo referenceable = up;
 105.131 -        for (int i = scopes.size() - 1; i >= 0 && referenceable.kind == CLASSSCOPE; i--, dist++) {
 105.132 -            referenceable = ((ScopeInfo)scopes.get(i));
 105.133 -        }
 105.134 -        cur.cook(referenceable, dist, symbolTable);
 105.135 -//        cur.dump(); // debug
 105.136 -        cur = up;
 105.137 -    }
 105.138 -
 105.139 -    public void parse() {
 105.140 -        try {
 105.141 -            visit(root);
 105.142 -        } catch (Throwable t) {
 105.143 -            Exceptions.printStackTrace(t);
 105.144 -            //throw org.python.core.ParserFacade.fixParseError(null, t,
 105.145 -            //        code_compiler.getFilename());
 105.146 -        }
 105.147 -    }
 105.148 -
 105.149 -    @Override
 105.150 -    public Object visitInteractive(Interactive node) throws Exception {
 105.151 -        beginScope("<single-top>", TOPSCOPE, node, null);
 105.152 -        PythonTree oldParent = parent;
 105.153 -        parent = node;
 105.154 -        suite(node.getInternalBody());
 105.155 -        parent = oldParent;
 105.156 -        endScope();
 105.157 -        return null;
 105.158 -    }
 105.159 -
 105.160 -    @Override
 105.161 -    public Object visitModule(org.python.antlr.ast.Module node)
 105.162 -            throws Exception {
 105.163 -        List<stmt> body = node.getInternalBody();
 105.164 -        if (body != null && body.size() > 0) {
 105.165 -            boolean foundFirst = false;
 105.166 -            for (stmt stmt : body) {
 105.167 -                if (stmt != null) {
 105.168 -                    if (stmt instanceof Import || stmt instanceof ImportFrom) {
 105.169 -                        if (!foundFirst) {
 105.170 -                            foundFirst = true;
 105.171 -                        }
 105.172 -                        mainImports.add(stmt);
 105.173 -                    } else if (foundFirst) {
 105.174 -                        break;
 105.175 -                    }
 105.176 -                }
 105.177 -            }
 105.178 -        }
 105.179 -
 105.180 -        beginScope("<file-top>", TOPSCOPE, node, null);
 105.181 -
 105.182 -        PythonTree oldParent = parent;
 105.183 -        parent = node;
 105.184 -        suite(node.getInternalBody());
 105.185 -        parent = oldParent;
 105.186 -
 105.187 -        endScope();
 105.188 -        return null;
 105.189 -    }
 105.190 -
 105.191 -    @Override
 105.192 -    public Object visitExpression(Expression node) throws Exception {
 105.193 -        beginScope("<eval-top>", TOPSCOPE, node, null);
 105.194 -        visit(new Return(node, node.getInternalBody()));
 105.195 -        endScope();
 105.196 -        return null;
 105.197 -    }
 105.198 -
 105.199 -    private void def(String name, int extraFlags, PythonTree node) {
 105.200 -        SymInfo info = cur.addBound(name, node);
 105.201 -        // <netbeans>
 105.202 -        info.flags |= (DEF | extraFlags);
 105.203 -        info.node = node;
 105.204 -        // </netbeans>
 105.205 -    }
 105.206 -
 105.207 -    @Override
 105.208 -    public Object visitAssign(Assign node) throws Exception {
 105.209 -        List<expr> targets = node.getInternalTargets();
 105.210 -        if (targets != null && targets.size() == 1 && targets.get(0) instanceof Name) {
 105.211 -            Name lhs = (Name)targets.get(0);
 105.212 -            if ("__all__".equals(lhs.getInternalId())) { // NOI18N
 105.213 -                expr nodeValue = node.getInternalValue();
 105.214 -                if (!invalidPublicSymbols && nodeValue instanceof org.python.antlr.ast.List) {
 105.215 -                    org.python.antlr.ast.List allList = (org.python.antlr.ast.List)nodeValue;
 105.216 -                    if (allList != null) {
 105.217 -                        for (expr expr : allList.getInternalElts()) {
 105.218 -                            if (expr instanceof Str) {
 105.219 -                                Str str = (Str)expr;
 105.220 -                                if (publicSymbols == null) {
 105.221 -                                    publicSymbols = new ArrayList<>();
 105.222 -                                }
 105.223 -                                publicSymbols.add(str);
 105.224 -                            } else {
 105.225 -                                invalidPublicSymbols = true;
 105.226 -                            }
 105.227 -                        }
 105.228 -                    }
 105.229 -                } else {
 105.230 -                    invalidPublicSymbols = true;
 105.231 -                }
 105.232 -            }
 105.233 -        }
 105.234 -
 105.235 -        if (targets.size() > 0) {
 105.236 -            List<Name> names = new ArrayList<>(targets.size());
 105.237 -            boolean valid = true;
 105.238 -            for (expr et : targets) {
 105.239 -                if (et instanceof Name) {
 105.240 -                    Name name = (Name)et;
 105.241 -                    names.add(name);
 105.242 -                } else {
 105.243 -                    valid = false;
 105.244 -                }
 105.245 -            }
 105.246 -            if (valid) {
 105.247 -                expr nodeValue = node.getInternalValue();
 105.248 -                if (nodeValue instanceof Name) {
 105.249 -                    Name value = (Name)nodeValue;
 105.250 -
 105.251 -                    SymInfo rhsSym = cur.tbl.get(value.getInternalId());
 105.252 -                    if (rhsSym != null && rhsSym.isDef()) {
 105.253 -                        for (Name name : names) {
 105.254 -                            visitName(name);
 105.255 -                            SymInfo sym = cur.tbl.get(name.getInternalId());
 105.256 -                            if (sym != null) {
 105.257 -                                sym.flags |= ALIAS;
 105.258 -                                sym.flags |= (rhsSym.flags & (CLASS | FUNCTION));
 105.259 -                                sym.node = rhsSym.node;
 105.260 -                            }
 105.261 -                        }
 105.262 -                    }
 105.263 -                }
 105.264 -            }
 105.265 -        }
 105.266 -
 105.267 -        return super.visitAssign(node);
 105.268 -    }
 105.269 -
 105.270 -    @Override
 105.271 -    public Object visitFunctionDef(FunctionDef node) throws Exception {
 105.272 -        def(node.getInternalName(), FUNCTION, node);
 105.273 -        ArgListCompiler ac = new ArgListCompiler(symbolTable);
 105.274 -        ac.visitArgs(node.getInternalArgs());
 105.275 -
 105.276 -        List<expr> defaults = ac.getDefaults();
 105.277 -        for (int i = 0; i < defaults.size(); i++) {
 105.278 -            visit(defaults.get(i));
 105.279 -        }
 105.280 -
 105.281 -        List<expr> decs = node.getInternalDecorator_list();
 105.282 -        for (int i = decs.size() - 1; i >= 0; i--) {
 105.283 -            visit(decs.get(i));
 105.284 -        }
 105.285 -
 105.286 -        ScopeInfo parentScope = cur;
 105.287 -        beginScope(node.getInternalName(), FUNCSCOPE, node, ac);
 105.288 -        cur.nested = parentScope;
 105.289 -
 105.290 -        int n = ac.names.size();
 105.291 -        for (int i = 0; i < n; i++) {
 105.292 -            cur.addParam(ac.names.get(i), ac.nodes.get(i));
 105.293 -        }
 105.294 -        for (int i = 0; i < ac.init_code.size(); i++) {
 105.295 -            visit(ac.init_code.get(i));
 105.296 -        }
 105.297 -        cur.markFromParam();
 105.298 -
 105.299 -        PythonTree oldParent = parent;
 105.300 -        parent = node;
 105.301 -        suite(node.getInternalBody());
 105.302 -        parent = oldParent;
 105.303 -
 105.304 -        endScope();
 105.305 -        return null;
 105.306 -    }
 105.307 -
 105.308 -    @Override
 105.309 -    public Object visitLambda(Lambda node) throws Exception {
 105.310 -        ArgListCompiler ac = new ArgListCompiler(symbolTable);
 105.311 -        ac.visitArgs(node.getInternalArgs());
 105.312 -
 105.313 -        List<expr> defaults = ac.getDefaults();
 105.314 -        for (expr expr : defaults) {
 105.315 -            visit(expr);
 105.316 -        }
 105.317 -
 105.318 -        beginScope("<lambda>", FUNCSCOPE, node, ac);
 105.319 -        assert ac.names.size() == ac.nodes.size();
 105.320 -        for (int i = 0; i < ac.names.size(); i++) {
 105.321 -            cur.addParam(ac.names.get(i), ac.nodes.get(i));
 105.322 -        }
 105.323 -        for (Object o : ac.init_code) {
 105.324 -            visit((stmt)o);
 105.325 -        }
 105.326 -        cur.markFromParam();
 105.327 -        visit(node.getInternalBody());
 105.328 -        endScope();
 105.329 -        return null;
 105.330 -    }
 105.331 -
 105.332 -    public void suite(List<stmt> stmts) throws Exception {
 105.333 -        if (stmts != null) {
 105.334 -            for (int i = 0; i < stmts.size(); i++) {
 105.335 -                stmt s = stmts.get(i);
 105.336 -                path.descend(s);
 105.337 -                visit(s);
 105.338 -                path.ascend();
 105.339 -            }
 105.340 -        }
 105.341 -    }
 105.342 -
 105.343 -    @Override
 105.344 -    public Object visitImport(Import node) throws Exception {
 105.345 -        if (parent == root) {
 105.346 -            topLevelImports.add(node);
 105.347 -        }
 105.348 -        imports.add(node);
 105.349 -
 105.350 -        List<alias> names = node.getInternalNames();
 105.351 -        if (names != null) {
 105.352 -            for (alias alias : names) {
 105.353 -                String asname = alias.getInternalAsname();
 105.354 -                if (asname != null) {
 105.355 -                    SymInfo entry = cur.addBound(asname, node);
 105.356 -                    entry.flags |= IMPORTED;
 105.357 -                } else {
 105.358 -                    String name = alias.getInternalName();
 105.359 -                    if (name.indexOf('.') > 0) {
 105.360 -                        name = name.substring(0, name.indexOf('.'));
 105.361 -                    }
 105.362 -                    SymInfo entry = cur.addBound(name, node);
 105.363 -                    entry.flags |= IMPORTED;
 105.364 -                }
 105.365 -            }
 105.366 -        }
 105.367 -        return null;
 105.368 -    }
 105.369 -
 105.370 -    @Override
 105.371 -    public Object visitImportFrom(ImportFrom node) throws Exception {
 105.372 -        if (parent == root) {
 105.373 -            topLevelImports.add(node);
 105.374 -        }
 105.375 -        importsFrom.add(node);
 105.376 -
 105.377 -        //Future.checkFromFuture(node); // future stmt support
 105.378 -        List<alias> names = node.getInternalNames();
 105.379 -        if (names == null || names.size() == 0) {
 105.380 -            cur.from_import_star = true;
 105.381 -            return null;
 105.382 -        }
 105.383 -        for (alias alias : names) {
 105.384 -            String asname = alias.getInternalAsname();
 105.385 -            if (asname != null) {
 105.386 -                SymInfo entry = cur.addBound(asname, node);
 105.387 -                entry.flags |= IMPORTED;
 105.388 -            } else {
 105.389 -                SymInfo entry = cur.addBound(alias.getInternalName(), node);
 105.390 -                entry.flags |= IMPORTED;
 105.391 -            }
 105.392 -        }
 105.393 -        return null;
 105.394 -    }
 105.395 -
 105.396 -    @Override
 105.397 -    public Object visitGlobal(Global node) throws Exception {
 105.398 -        List<String> names = node.getInternalNames();
 105.399 -        for (String name : names) {
 105.400 -            int prev = cur.addGlobal(name, node);
 105.401 -            if (prev >= 0) {
 105.402 -                if ((prev & FROM_PARAM) != 0) {
 105.403 -                    symbolTable.error("name '" + name + "' is local and global", true, node);
 105.404 -                }
 105.405 -                if ((prev & GLOBAL) != 0) {
 105.406 -                    continue;
 105.407 -                }
 105.408 -                String what;
 105.409 -                if ((prev & BOUND) != 0) {
 105.410 -                    what = "assignment";
 105.411 -                } else {
 105.412 -                    what = "use";
 105.413 -                }
 105.414 -                symbolTable.error("name '" + name + "' declared global after " + what, false, node);
 105.415 -            }
 105.416 -        }
 105.417 -        return null;
 105.418 -    }
 105.419 -
 105.420 -    @Override
 105.421 -    public Object visitExec(Exec node) throws Exception {
 105.422 -        cur.exec = true;
 105.423 -        if (node.getInternalGlobals() == null && node.getInternalLocals() == null) {
 105.424 -            cur.unqual_exec = true;
 105.425 -        }
 105.426 -        traverse(node);
 105.427 -        return null;
 105.428 -    }
 105.429 -
 105.430 -    @Override
 105.431 -    public Object visitClassDef(ClassDef node) throws Exception {
 105.432 -        String name = node.getInternalName();
 105.433 -        def(name, CLASS, node);
 105.434 -        List<expr> bases = node.getInternalBases();
 105.435 -        if (bases != null) {
 105.436 -            for (expr expr : bases) {
 105.437 -                visit(expr);
 105.438 -            }
 105.439 -        }
 105.440 -        ScopeInfo parentScope = cur;
 105.441 -        beginScope(name, CLASSSCOPE, node, null);
 105.442 -        cur.nested = parentScope;
 105.443 -        PythonTree oldParent = parent;
 105.444 -        parent = node;
 105.445 -        suite(node.getInternalBody());
 105.446 -        parent = oldParent;
 105.447 -        endScope();
 105.448 -        return null;
 105.449 -    }
 105.450 -
 105.451 -    @Override
 105.452 -    public Object visitName(Name node) throws Exception {
 105.453 -        // Jython's parser doesn't always initialize the parent references correctly;
 105.454 -        // try to correct that here.
 105.455 -        node.setParent(parent);
 105.456 -
 105.457 -        String name = node.getInternalId();
 105.458 -        if (node.getInternalCtx() != expr_contextType.Load) {
 105.459 -            if (name.equals("__debug__")) {
 105.460 -                symbolTable.error("can not assign to __debug__", true, node);
 105.461 -            }
 105.462 -            cur.addBound(name, node);
 105.463 -        } else {
 105.464 -            cur.addUsed(name, node);
 105.465 -        }
 105.466 -        return null;
 105.467 -    }
 105.468 -
 105.469 -    // <netbeans>
 105.470 -    @Override
 105.471 -    public Object visitCall(Call node) throws Exception {
 105.472 -        Object ret = super.visitCall(node);
 105.473 -
 105.474 -        expr func = node.getInternalFunc();
 105.475 -        if (func instanceof Name) {
 105.476 -            Name name = (Name)func;
 105.477 -            cur.markCall(name.getInternalId());
 105.478 -        } else if (func instanceof Attribute) {
 105.479 -            Attribute attr = (Attribute)func;
 105.480 -            if (cur.attributes != null) {
 105.481 -                SymInfo funcSymbol = cur.attributes.get(attr.getInternalAttr());
 105.482 -                if (funcSymbol != null) {
 105.483 -                    funcSymbol.flags |= FUNCTION | CALLED; // mark as func/method call
 105.484 -                }
 105.485 -            }
 105.486 -
 105.487 -        }
 105.488 -
 105.489 -        return ret;
 105.490 -    }
 105.491 -
 105.492 -    @Override
 105.493 -    public Object visitDelete(Delete node) throws Exception {
 105.494 -        for (expr et : node.getInternalTargets()) {
 105.495 -            if (et instanceof Name) {
 105.496 -                String name = ((Name)et).getInternalId();
 105.497 -                cur.addUsed(name, node);
 105.498 -            }
 105.499 -        }
 105.500 -
 105.501 -        return super.visitDelete(node);
 105.502 -    }
 105.503 -
 105.504 -    @Override
 105.505 -    public Object visitAttribute(Attribute node) throws Exception {
 105.506 -        if (parent instanceof Call && node.getInternalValue() instanceof Name &&
 105.507 -                ("__all__".equals(((Name)node.getInternalValue()).getInternalId()))) {
 105.508 -            // If you for example call
 105.509 -            //    __all__.extend("foo")
 105.510 -            // or
 105.511 -            //    __all__.append("bar")
 105.512 -            // then I don't want to try to analyze __all__
 105.513 -            String nodeAttr = node.getInternalAttr();
 105.514 -            if ("extend".equals(nodeAttr) || "append".equals(nodeAttr)) { // NOI18N
 105.515 -                Call call = (Call)parent;
 105.516 -                List<expr> callArgs = call.getInternalArgs();
 105.517 -                if (callArgs != null) {
 105.518 -                    for (expr expr : callArgs) {
 105.519 -                        if (expr instanceof Str) {
 105.520 -                            if (publicSymbols == null) {
 105.521 -                                publicSymbols = new ArrayList<>();
 105.522 -                            }
 105.523 -                            publicSymbols.add((Str)expr);
 105.524 -                        } else if (expr instanceof org.python.antlr.ast.List) {
 105.525 -                            org.python.antlr.ast.List list = (org.python.antlr.ast.List)expr;
 105.526 -                            if (list != null) {
 105.527 -                                List<expr> elts = list.getInternalElts();
 105.528 -                                if (elts != null) {
 105.529 -                                    for (expr ex : elts) {
 105.530 -                                        if (ex instanceof Str) {
 105.531 -                                            Str str = (Str)ex;
 105.532 -                                            if (publicSymbols == null) {
 105.533 -                                                publicSymbols = new ArrayList<>();
 105.534 -                                            }
 105.535 -                                            publicSymbols.add(str);
 105.536 -                                        } else {
 105.537 -                                            invalidPublicSymbols = true;
 105.538 -                                        }
 105.539 -                                    }
 105.540 -                                }
 105.541 -                            }
 105.542 -                        } else {
 105.543 -                            invalidPublicSymbols = true;
 105.544 -                            break;
 105.545 -                        }
 105.546 -                    }
 105.547 -                }
 105.548 -            } else {
 105.549 -                invalidPublicSymbols = true;
 105.550 -            }
 105.551 -        } else {
 105.552 -            String nodeAttr = node.getInternalAttr();
 105.553 -            if (nodeAttr != null) {
 105.554 -                cur.addAttribute(path, nodeAttr, node);
 105.555 -            }
 105.556 -        }
 105.557 -        return super.visitAttribute(node);
 105.558 -    }
 105.559 -    // </netbeans>
 105.560 -
 105.561 -    @Override
 105.562 -    public Object visitListComp(ListComp node) throws Exception {
 105.563 -        String tmp = "_[" + node.getLine() + "_" + node.getCharPositionInLine() + "]";
 105.564 -        cur.addBound(tmp, node);
 105.565 -        traverse(node);
 105.566 -        return null;
 105.567 -    }
 105.568 -
 105.569 -    @Override
 105.570 -    public Object visitYield(Yield node) throws Exception {
 105.571 -        cur.defineAsGenerator(node);
 105.572 -        cur.yield_count++;
 105.573 -        traverse(node);
 105.574 -        return null;
 105.575 -    }
 105.576 -
 105.577 -    @Override
 105.578 -    public Object visitReturn(Return node) throws Exception {
 105.579 -        if (node.getInternalValue() != null) {
 105.580 -            cur.noteReturnValue(node);
 105.581 -        }
 105.582 -        traverse(node);
 105.583 -        return null;
 105.584 -    }
 105.585 -
 105.586 -    @Override
 105.587 -    public Object visitGeneratorExp(GeneratorExp node) throws Exception {
 105.588 -        // The first iterator is evaluated in the outer scope
 105.589 -        if (node.getInternalGenerators() != null && node.getInternalGenerators().size() > 0) {
 105.590 -            visit(node.getInternalGenerators().get(0).getInternalIter());
 105.591 -        }
 105.592 -        String bound_exp = "_(x)";
 105.593 -        String tmp = "_(" + node.getLine() + "_" + node.getCharPositionInLine() + ")";
 105.594 -        def(tmp, GENERATOR, node);
 105.595 -        ArgListCompiler ac = new ArgListCompiler(symbolTable);
 105.596 -        List<expr> args = new ArrayList<>();
 105.597 -        Name argsName = new Name(node.getToken(), bound_exp, expr_contextType.Param);
 105.598 -        args.add(argsName);
 105.599 -        ac.visitArgs(new arguments(node, args, null, null, new ArrayList<expr>()));
 105.600 -        beginScope(tmp, FUNCSCOPE, node, ac);
 105.601 -        cur.addParam(bound_exp, argsName);
 105.602 -        cur.markFromParam();
 105.603 -
 105.604 -        cur.defineAsGenerator(node);
 105.605 -        cur.yield_count++;
 105.606 -        // The reset of the iterators are evaluated in the inner scope
 105.607 -        if (node.getInternalElt() != null) {
 105.608 -            visit(node.getInternalElt());
 105.609 -        }
 105.610 -        if (node.getInternalGenerators() != null) {
 105.611 -            for (int i = 0; i < node.getInternalGenerators().size(); i++) {
 105.612 -                if (node.getInternalGenerators().get(i) != null) {
 105.613 -                    if (i == 0) {
 105.614 -                        visit(node.getInternalGenerators().get(i).getInternalTarget());
 105.615 -                        if (node.getInternalGenerators().get(i).getInternalIfs() != null) {
 105.616 -                            for (expr cond : node.getInternalGenerators().get(i).getInternalIfs()) {
 105.617 -                                if (cond != null) {
 105.618 -                                    visit(cond);
 105.619 -                                }
 105.620 -                            }
 105.621 -                        }
 105.622 -                    } else {
 105.623 -                        visit(node.getInternalGenerators().get(i));
 105.624 -                    }
 105.625 -                }
 105.626 -            }
 105.627 -        }
 105.628 -
 105.629 -        endScope();
 105.630 -        return null;
 105.631 -    }
 105.632 -
 105.633 -    @Override
 105.634 -    public Object visitWith(With node) throws Exception {
 105.635 -        cur.max_with_count++;
 105.636 -        traverse(node);
 105.637 -
 105.638 -        return null;
 105.639 -    }
 105.640 -
 105.641 -    public List<Str> getPublicSymbols() {
 105.642 -        return invalidPublicSymbols ? null : publicSymbols;
 105.643 -    }
 105.644 -}
   106.1 --- a/python.editor/src/org/netbeans/modules/python/editor/scopes/SymInfo.java	Sat Sep 12 23:03:15 2015 -0700
   106.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   106.3 @@ -1,207 +0,0 @@
   106.4 -package org.netbeans.modules.python.editor.scopes;
   106.5 -
   106.6 -import org.python.antlr.PythonTree;
   106.7 -import static org.netbeans.modules.python.editor.scopes.ScopeConstants.*;
   106.8 -
   106.9 -public class SymInfo extends Object {
  106.10 -    public SymInfo(int flags) {
  106.11 -        this.flags = flags;
  106.12 -    }
  106.13 -
  106.14 -    public SymInfo(int flags, int locals_index) {
  106.15 -        this.flags = flags;
  106.16 -        this.locals_index = locals_index;
  106.17 -    }
  106.18 -    public int flags;
  106.19 -    public int locals_index;
  106.20 -    public int env_index;
  106.21 -    public PythonTree node;
  106.22 -
  106.23 -    @Override
  106.24 -    public String toString() {
  106.25 -        return "SymInfo[" + flags + " " + locals_index + " " +
  106.26 -                env_index + "]" + dumpFlags(null);
  106.27 -    }
  106.28 -
  106.29 -    public String dumpFlags(ScopeInfo info) {
  106.30 -        StringBuilder sb = new StringBuilder();
  106.31 -        if ((flags & BOUND) != 0) {
  106.32 -            sb.append("[bound]");
  106.33 -        }
  106.34 -        // func scope global (affect nested scopes)
  106.35 -        // vs. class scope global
  106.36 -        if ((flags & NGLOBAL) != 0) {
  106.37 -            sb.append("[func-global]");
  106.38 -        } else if ((flags & CLASS_GLOBAL) != 0) {
  106.39 -            sb.append("[class-global]");
  106.40 -        }
  106.41 -        if ((flags & PARAM) != 0) {
  106.42 -            sb.append("[param]");
  106.43 -        } else if ((flags & FROM_PARAM) != 0) {
  106.44 -            sb.append("[from-param]");
  106.45 -        }
  106.46 -        if ((flags & CELL) != 0) {
  106.47 -            sb.append("[cell]");
  106.48 -        }
  106.49 -        if ((flags & FREE) != 0) {
  106.50 -            sb.append("[free]");
  106.51 -        }
  106.52 -        if (isImported()) {
  106.53 -            sb.append("[imported]");
  106.54 -        }
  106.55 -        if (isPrivate()) {
  106.56 -            sb.append("[private]");
  106.57 -        }
  106.58 -        if (isClass()) {
  106.59 -            sb.append("[class]");
  106.60 -        }
  106.61 -        if (isFunction()) {
  106.62 -            sb.append("[function]");
  106.63 -        }
  106.64 -        if (isData()) {
  106.65 -            sb.append("[data]");
  106.66 -        }
  106.67 -        if (isMember()) {
  106.68 -            sb.append("[member]");
  106.69 -        }
  106.70 -        if (isDef()) {
  106.71 -            sb.append("[def]");
  106.72 -        }
  106.73 -        if (isRead()) {
  106.74 -            sb.append("[read]");
  106.75 -        }
  106.76 -        if (isAlias()) {
  106.77 -            sb.append("[alias]");
  106.78 -        }
  106.79 -        if (isGeneratorExp()) {
  106.80 -            sb.append("[generator]");
  106.81 -        }
  106.82 -        if (isCalled()) {
  106.83 -            sb.append("[called]");
  106.84 -        }
  106.85 -        if (isProtected()) {
  106.86 -            sb.append("[protected]");
  106.87 -        }
  106.88 -        if (isBoundInConstructor()) {
  106.89 -            sb.append("[bound-in-constructor]");
  106.90 -        }
  106.91 -        if (isUnused(info)) {
  106.92 -            sb.append("[unused]");
  106.93 -        }
  106.94 -        if (isUnresolved()) {
  106.95 -            sb.append("[UNRESOLVED]");
  106.96 -        }
  106.97 -        sb.append("[node=");
  106.98 -        if (node != null) {
  106.99 -            sb.append(node.getClass().getSimpleName());
 106.100 -        } else {
 106.101 -            sb.append("null");
 106.102 -        }
 106.103 -        sb.append("]");
 106.104 -
 106.105 -        return sb.toString();
 106.106 -    }
 106.107 -
 106.108 -    public boolean isUnused(ScopeInfo info) {
 106.109 -        return (info == null || info.kind == FUNCSCOPE) && (flags & (READ | BOUND | DEF)) == BOUND;
 106.110 -    }
 106.111 -
 106.112 -    public boolean isParameter() {
 106.113 -        return (flags & (PARAM | FROM_PARAM)) != 0;
 106.114 -    }
 106.115 -
 106.116 -    public boolean isUnresolved() {
 106.117 -        return (flags & (BOUND | FREE)) == 0;
 106.118 -    }
 106.119 -
 106.120 -    public boolean isImported() {
 106.121 -        return (flags & IMPORTED) != 0;
 106.122 -    }
 106.123 -
 106.124 -    public boolean isData() {
 106.125 -        return (flags & (BOUND | DEF | CLASS | FUNCTION)) == (BOUND);
 106.126 -    }
 106.127 -
 106.128 -    public boolean isClass() {
 106.129 -        return (flags & CLASS) != 0;
 106.130 -    }
 106.131 -
 106.132 -    public boolean isDef() {
 106.133 -        return (flags & DEF) != 0;
 106.134 -    }
 106.135 -
 106.136 -    public boolean isFunction() {
 106.137 -        return (flags & FUNCTION) != 0;
 106.138 -    }
 106.139 -
 106.140 -    public boolean isBound() {
 106.141 -        return (flags & BOUND) != 0;
 106.142 -    }
 106.143 -
 106.144 -    public boolean isMember() {
 106.145 -        return (flags & MEMBER) != 0;
 106.146 -    }
 106.147 -
 106.148 -    public boolean isCalled() {
 106.149 -        return (flags & CALLED) != 0;
 106.150 -    }
 106.151 -
 106.152 -    public boolean isRead() {
 106.153 -        return (flags & READ) != 0;
 106.154 -    }
 106.155 -
 106.156 -    public boolean isGeneratorExp() {
 106.157 -        return (flags & GENERATOR) != 0;
 106.158 -    }
 106.159 -
 106.160 -    public boolean isFree() {
 106.161 -        return (flags & FREE) != 0;
 106.162 -    }
 106.163 -
 106.164 -    public boolean isPrivate() {
 106.165 -        return (flags & PRIVATE) != 0;
 106.166 -    }
 106.167 -
 106.168 -    public boolean isProtected() {
 106.169 -        return (flags & PROTECTED) != 0;
 106.170 -    }
 106.171 -
 106.172 -    public boolean isBoundInConstructor() {
 106.173 -        return (flags & BOUND_IN_CONSTRUCTOR) != 0;
 106.174 -    }
 106.175 -
 106.176 -    public boolean isAlias() {
 106.177 -        return (flags & ALIAS) != 0;
 106.178 -    }
 106.179 -
 106.180 -    public boolean isVariable(boolean mustBeBound) {
 106.181 -        int mask = mustBeBound ? BOUND : 0;
 106.182 -        return (flags & (BOUND | CALLED | DEF | IMPORTED | CLASS | FUNCTION | MEMBER | GENERATOR)) == mask;
 106.183 -    }
 106.184 -
 106.185 -    public static boolean isPrivateName(String name) {
 106.186 -        // Private variables: start with __ but doesn't end with __
 106.187 -        // Section 9.6 Private Variables - http://docs.python.org/tut/node11.html
 106.188 -        if (name.startsWith("__") && !name.endsWith("__")) { // NOI18N
 106.189 -            return true;
 106.190 -        } else if (name != null && name.startsWith("_") && !name.endsWith("_")) { // NOI18N
 106.191 -            // From PEP8: Single_leading_underscore: weak "internal use" indicator
 106.192 -            // (e.g. "from M import *" does not import objects whose name
 106.193 -            // starts with an underscore).
 106.194 -            return true;
 106.195 -        }
 106.196 -
 106.197 -        return false;
 106.198 -    }
 106.199 -
 106.200 -    public static boolean isProtectedName(String name) {
 106.201 -        // Protected variable starts with a single _
 106.202 -        // this is a convention only
 106.203 -        if (!name.startsWith("__")) { // NOI18N
 106.204 -            if (name.startsWith("_")) { // NOI18N
 106.205 -                return true;
 106.206 -            }
 106.207 -        }
 106.208 -        return false;
 106.209 -    }
 106.210 -}
   107.1 --- a/python.editor/src/org/netbeans/modules/python/editor/scopes/SymbolTable.java	Sat Sep 12 23:03:15 2015 -0700
   107.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   107.3 @@ -1,1249 +0,0 @@
   107.4 -/*
   107.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   107.6 - *
   107.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   107.8 - *
   107.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  107.10 - * Other names may be trademarks of their respective owners.
  107.11 - *
  107.12 - * The contents of this file are subject to the terms of either the GNU
  107.13 - * General Public License Version 2 only ("GPL") or the Common
  107.14 - * Development and Distribution License("CDDL") (collectively, the
  107.15 - * "License"). You may not use this file except in compliance with the
  107.16 - * License. You can obtain a copy of the License at
  107.17 - * http://www.netbeans.org/cddl-gplv2.html
  107.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  107.19 - * specific language governing permissions and limitations under the
  107.20 - * License.  When distributing the software, include this License Header
  107.21 - * Notice in each file and include the License file at
  107.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  107.23 - * particular file as subject to the "Classpath" exception as provided
  107.24 - * by Oracle in the GPL Version 2 section of the License file that
  107.25 - * accompanied this code. If applicable, add the following below the
  107.26 - * License Header, with the fields enclosed by brackets [] replaced by
  107.27 - * your own identifying information:
  107.28 - * "Portions Copyrighted [year] [name of copyright owner]"
  107.29 - *
  107.30 - * If you wish your version of this file to be governed by only the CDDL
  107.31 - * or only the GPL Version 2, indicate your decision by adding
  107.32 - * "[Contributor] elects to include this software in this distribution
  107.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  107.34 - * single choice of license, a recipient has the option to distribute
  107.35 - * your version of this file under either the CDDL, the GPL Version 2 or
  107.36 - * to extend the choice of license to its licensees as provided above.
  107.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  107.38 - * Version 2 license, then the option applies only if the new code is
  107.39 - * made subject to such option by the copyright holder.
  107.40 - *
  107.41 - * Contributor(s):
  107.42 - *
  107.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
  107.44 - */
  107.45 -package org.netbeans.modules.python.editor.scopes;
  107.46 -
  107.47 -import java.util.ArrayList;
  107.48 -import java.util.Collections;
  107.49 -import java.util.HashMap;
  107.50 -import java.util.HashSet;
  107.51 -import java.util.List;
  107.52 -import java.util.Map;
  107.53 -import java.util.Set;
  107.54 -import org.netbeans.modules.csl.api.ElementKind;
  107.55 -import org.netbeans.modules.csl.api.OffsetRange;
  107.56 -import org.netbeans.modules.csl.api.Severity;
  107.57 -import org.netbeans.modules.csl.api.Error;
  107.58 -import org.netbeans.modules.csl.spi.DefaultError;
  107.59 -import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
  107.60 -import org.netbeans.modules.python.editor.PythonAstUtils;
  107.61 -import org.netbeans.modules.python.editor.PythonIndex;
  107.62 -import org.netbeans.modules.python.editor.PythonIndexer;
  107.63 -import org.netbeans.modules.python.editor.PythonParserResult;
  107.64 -import org.netbeans.modules.python.editor.PythonUtils;
  107.65 -import org.netbeans.modules.python.editor.elements.AstElement;
  107.66 -import org.netbeans.modules.python.editor.elements.Element;
  107.67 -import org.netbeans.modules.python.editor.elements.IndexedElement;
  107.68 -import org.netbeans.modules.python.editor.imports.ImportEntry;
  107.69 -import org.netbeans.modules.python.editor.imports.ImportManager;
  107.70 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
  107.71 -import org.openide.filesystems.FileObject;
  107.72 -import org.openide.filesystems.FileStateInvalidException;
  107.73 -import org.openide.filesystems.FileUtil;
  107.74 -import org.openide.util.Exceptions;
  107.75 -import org.python.antlr.PythonTree;
  107.76 -import org.python.antlr.Visitor;
  107.77 -import org.python.antlr.ast.Attribute;
  107.78 -import org.python.antlr.ast.ClassDef;
  107.79 -import org.python.antlr.ast.Expression;
  107.80 -import org.python.antlr.ast.FunctionDef;
  107.81 -import org.python.antlr.ast.GeneratorExp;
  107.82 -import org.python.antlr.ast.Import;
  107.83 -import org.python.antlr.ast.ImportFrom;
  107.84 -import org.python.antlr.ast.Interactive;
  107.85 -import org.python.antlr.ast.Lambda;
  107.86 -import org.python.antlr.ast.Name;
  107.87 -import org.python.antlr.ast.Str;
  107.88 -import org.python.antlr.ast.alias;
  107.89 -import org.python.antlr.base.expr;
  107.90 -import static org.netbeans.modules.python.editor.scopes.ScopeConstants.*;
  107.91 -
  107.92 -/**
  107.93 - * A symbol table tracks a bunch of scopes and can answer questions about defined
  107.94 - * symbols.
  107.95 - *
  107.96 - * Based on Jython's ScopeManager.
  107.97 - *
  107.98 - * @author Tor Norbye
  107.99 - */
 107.100 -public class SymbolTable {
 107.101 -    private final static int YES = 1;
 107.102 -    private final static int NO = 0;
 107.103 -    private final static int CIRCULAR = -1;
 107.104 -    private Map<PythonTree, ScopeInfo> scopes = new HashMap<>();
 107.105 -    private PythonTree root;
 107.106 -    private FileObject fileObject;
 107.107 -    private List<Import> imports = new ArrayList<>();
 107.108 -    private List<ImportFrom> importsFrom = new ArrayList<>();
 107.109 -    private List<PythonTree> mainImports = new ArrayList<>();
 107.110 -    private Set<PythonTree> topLevelImports = new HashSet<>();
 107.111 -    private List<Error> errors;
 107.112 -    /** List of symbols registered via __all__ = [ "foo", "bar" ] or __all__.extend() or __all__.append() */
 107.113 -    private List<Str> publicSymbols;
 107.114 -    private final static HashMap<String, String> classAttributes = new HashMap<String, String>() {
 107.115 -        {
 107.116 -            put("__class__", "__class__");
 107.117 -            put("__bases__", "__bases__");
 107.118 -            put("__dict__", "__dict__");
 107.119 -            put("__doc__", "__doc__");
 107.120 -            put("__name__", "__bases");
 107.121 -        }
 107.122 -    };
 107.123 -    private HashMap<String, ClassDef> classes = new HashMap<>();
 107.124 -    // TODO - use WeakHashMap?
 107.125 -    static Map<String, Set<IndexedElement>> importedElements = new HashMap<>();
 107.126 -
 107.127 -    private HashMap<String, ClassDef> buildLocalClasses() {
 107.128 -        HashMap<String, ClassDef> localClasses = new HashMap<>();
 107.129 -        for (PythonTree cur : scopes.keySet()) {
 107.130 -            if (cur instanceof ClassDef) {
 107.131 -                ClassDef curClass = (ClassDef)cur;
 107.132 -                localClasses.put(curClass.getInternalName(), curClass);
 107.133 -            }
 107.134 -        }
 107.135 -        return localClasses;
 107.136 -    }
 107.137 -
 107.138 -    public SymbolTable(PythonTree root, FileObject fileObject) {
 107.139 -        this.root = root;
 107.140 -        this.fileObject = fileObject;
 107.141 -
 107.142 -        if (root != null) {
 107.143 -            try {
 107.144 -                ScopesCompiler compiler = new ScopesCompiler(this, scopes, root, imports, importsFrom, mainImports, topLevelImports);
 107.145 -                compiler.parse();
 107.146 -                publicSymbols = compiler.getPublicSymbols();
 107.147 -                classes = buildLocalClasses();
 107.148 -                if (publicSymbols != null) {
 107.149 -                    // Mark all other symbols private!
 107.150 -                    Set<String> names = new HashSet<>(publicSymbols.size() + 1);
 107.151 -                    names.add("__all__"); // __all__ itself is exported!
 107.152 -                    for (Str str : publicSymbols) {
 107.153 -                        String name = PythonAstUtils.getStrContent(str);
 107.154 -                        if (name != null) {
 107.155 -                            names.add(name);
 107.156 -                        }
 107.157 -                    }
 107.158 -
 107.159 -                    ScopeInfo topScope = scopes.get(root);
 107.160 -                    if (topScope != null) {
 107.161 -                        for (Map.Entry<String, SymInfo> entry : topScope.tbl.entrySet()) {
 107.162 -                            String name = entry.getKey();
 107.163 -                            if (!names.contains(name)) {
 107.164 -                                SymInfo sym = entry.getValue();
 107.165 -                                sym.flags |= PRIVATE;
 107.166 -                                if (sym.isDef() && sym.node != null) {
 107.167 -                                    ScopeInfo scope = scopes.get(sym.node);
 107.168 -                                    scope.hidden = true;
 107.169 -                                }
 107.170 -                            }
 107.171 -                        }
 107.172 -                    }
 107.173 -
 107.174 -                    for (Map.Entry<PythonTree, ScopeInfo> entry : scopes.entrySet()) {
 107.175 -                        ScopeInfo scope = entry.getValue();
 107.176 -                        boolean isHidden = false;
 107.177 -                        ScopeInfo curr = scope;
 107.178 -                        while (curr != null) {
 107.179 -                            if (curr.hidden) {
 107.180 -                                isHidden = true;
 107.181 -                                break;
 107.182 -                            }
 107.183 -                            if (curr.nested != null) {
 107.184 -                                curr = curr.nested;
 107.185 -                            } else {
 107.186 -                                curr = curr.up;
 107.187 -                            }
 107.188 -
 107.189 -                        }
 107.190 -                        if (isHidden) {
 107.191 -                            scope.hidden = true;
 107.192 -                        }
 107.193 -                    }
 107.194 -
 107.195 -                    // Mark all symbols private, unless the scope is a direct descendant
 107.196 -                    // of a public symbol
 107.197 -                    for (ScopeInfo scope : scopes.values()) {
 107.198 -                        if (scope.hidden) {
 107.199 -                            for (SymInfo sym : scope.tbl.values()) {
 107.200 -                                sym.flags |= PRIVATE;
 107.201 -                            }
 107.202 -                        }
 107.203 -                    }
 107.204 -                }
 107.205 -            } catch (Exception ex) {
 107.206 -                Exceptions.printStackTrace(ex);
 107.207 -            }
 107.208 -        }
 107.209 -    }
 107.210 -
 107.211 -    public boolean isPrivate(PythonTree node, String name) {
 107.212 -        ScopeInfo scope = scopes.get(node);
 107.213 -        if (scope == null) {
 107.214 -            scope = scopes.get(root);
 107.215 -        }
 107.216 -        if (scope != null) {
 107.217 -            if (scope.up != null) {
 107.218 -                if (scope.hidden) {
 107.219 -                    return true;
 107.220 -                }
 107.221 -                // Look in parent's scope table
 107.222 -                if (scope.nested != null) {
 107.223 -                    scope = scope.nested;
 107.224 -                } else {
 107.225 -                    scope = scope.up;
 107.226 -                }
 107.227 -                if (scope != null) {
 107.228 -                    SymInfo sym = scope.tbl.get(name);
 107.229 -                    if (sym != null) {
 107.230 -                        return sym.isPrivate();
 107.231 -                    }
 107.232 -                }
 107.233 -            } else {
 107.234 -                SymInfo sym = scope.tbl.get(name);
 107.235 -                if (sym != null) {
 107.236 -                    return sym.isPrivate();
 107.237 -                }
 107.238 -            }
 107.239 -        }
 107.240 -
 107.241 -        return false;
 107.242 -    }
 107.243 -
 107.244 -    public SymInfo findDeclaration(PythonTree scope, String name, boolean allowFree) {
 107.245 -        ScopeInfo scopeInfo = getScopeInfo(scope);
 107.246 -        if (scopeInfo != null) {
 107.247 -            SymInfo sym = scopeInfo.tbl.get(name);
 107.248 -            SymInfo orig = sym;
 107.249 -            while (sym != null && sym.isFree()) {
 107.250 -                scopeInfo = scopeInfo.up;
 107.251 -                while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 107.252 -                    scopeInfo = scopeInfo.up;
 107.253 -                }
 107.254 -                sym = scopeInfo.tbl.get(name);
 107.255 -            }
 107.256 -
 107.257 -            if (allowFree && sym == null && orig != null) {
 107.258 -                // Free variable -- might have to resolve it
 107.259 -                return orig;
 107.260 -            }
 107.261 -
 107.262 -            // Look for attributes too
 107.263 -            if (sym == null) {
 107.264 -                sym = scopeInfo.attributes.get(name);
 107.265 -                orig = sym;
 107.266 -                while (sym != null && sym.isFree()) {
 107.267 -                    scopeInfo = scopeInfo.up;
 107.268 -                    while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 107.269 -                        scopeInfo = scopeInfo.up;
 107.270 -                    }
 107.271 -                    sym = scopeInfo.tbl.get(name);
 107.272 -                }
 107.273 -
 107.274 -                if (allowFree && sym == null && orig != null) {
 107.275 -                    // Free variable -- might have to resolve it
 107.276 -                    return orig;
 107.277 -                }
 107.278 -            }
 107.279 -
 107.280 -            return sym;
 107.281 -        }
 107.282 -
 107.283 -        return null;
 107.284 -    }
 107.285 -
 107.286 -    public ScopeInfo getScopeInfo(PythonTree node) {
 107.287 -        return scopes.get(node);
 107.288 -    }
 107.289 -
 107.290 -    public List<Error> getErrors() {
 107.291 -        return errors != null ? errors : Collections.<Error>emptyList();
 107.292 -    }
 107.293 -
 107.294 -    public SymInfo findBySignature(ElementKind kind, String signature) {
 107.295 -        PythonTree scope = root;
 107.296 -        String name = signature;
 107.297 -        int dot = signature.lastIndexOf('.');
 107.298 -        if (dot != -1) {
 107.299 -            String clz = signature.substring(0, dot);
 107.300 -            name = signature.substring(dot + 1);
 107.301 -            SymInfo sym = findDeclaration(root, clz, true);
 107.302 -            if (sym != null && sym.node != null) {
 107.303 -                scope = sym.node;
 107.304 -            }
 107.305 -        }
 107.306 -        SymInfo sym = findDeclaration(scope, name, true);
 107.307 -
 107.308 -        return sym;
 107.309 -    }
 107.310 -
 107.311 -    private List<String> getModulesToStarImport() {
 107.312 -        List<String> modules = new ArrayList<>();
 107.313 -
 107.314 -        for (ImportFrom from : importsFrom) {
 107.315 -            List<alias> names = from.getInternalNames();
 107.316 -            if (names != null) {
 107.317 -                for (alias at : names) {
 107.318 -                    if ("*".equals(at.getInternalName())) { // NOI18N
 107.319 -                        modules.add(from.getInternalModule());
 107.320 -                    }
 107.321 -                }
 107.322 -            }
 107.323 -        }
 107.324 -
 107.325 -        modules.addAll(PythonIndex.BUILTIN_MODULES);
 107.326 -
 107.327 -        return modules;
 107.328 -    }
 107.329 -
 107.330 -    private void addSymbolsFromModule(PythonParserResult info, String module, String prefix, QuerySupport.Kind kind, Set<? super IndexedElement> result) {
 107.331 -        if (PythonIndex.isBuiltinModule(module)) {
 107.332 -            Set<IndexedElement> all = getAllSymbolsFromModule(info, module);
 107.333 -            for (IndexedElement e : all) {
 107.334 -                if (kind == QuerySupport.Kind.PREFIX) {
 107.335 -                    if (e.getName().startsWith(prefix)) {
 107.336 -                        result.add(e);
 107.337 -                    }
 107.338 -                } else if (kind == QuerySupport.Kind.EXACT) {
 107.339 -                    if (prefix.equals(e.getName())) {
 107.340 -                        result.add(e);
 107.341 -                    }
 107.342 -                } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX) {
 107.343 -                    if (e.getName().regionMatches(true, 0, prefix, 0, prefix.length())) {
 107.344 -                        result.add(e);
 107.345 -                    }
 107.346 -                }
 107.347 -            }
 107.348 -        } else {
 107.349 -            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 107.350 -            Set<IndexedElement> elements = index.getImportedElements(prefix, kind, Collections.singleton(module), null);
 107.351 -            for (IndexedElement e : elements) {
 107.352 -                result.add(e);
 107.353 -            }
 107.354 -        }
 107.355 -    }
 107.356 -
 107.357 -    private Set<IndexedElement> getAllSymbolsFromModule(PythonParserResult info, String module) {
 107.358 -        Set<IndexedElement> elements = importedElements.get(module);
 107.359 -        if (elements == null) {
 107.360 -            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 107.361 -            Set<String> systemHolder = new HashSet<>(3);
 107.362 -            elements = index.getImportedElements("", QuerySupport.Kind.PREFIX, Collections.singleton(module), systemHolder);
 107.363 -            // Cache system modules - don't cache local modules
 107.364 -            if (!systemHolder.isEmpty()) {
 107.365 -                importedElements.put(module, elements);
 107.366 -            }
 107.367 -        }
 107.368 -
 107.369 -        return elements;
 107.370 -    }
 107.371 -
 107.372 -    public Set<Element> getDefinedElements(PythonParserResult info, PythonTree scope, String prefix, QuerySupport.Kind kind) {
 107.373 -        Set<Element> elements = new HashSet<>(300);
 107.374 -        ScopeInfo scopeInfo = scopes.get(scope);
 107.375 -        String module = PythonUtils.getModuleName(fileObject);
 107.376 -        String url = fileObject.toURL().toExternalForm();
 107.377 -
 107.378 -        // Get builtin symbols
 107.379 -        for (String mod : getModulesToStarImport()) {
 107.380 -            addSymbolsFromModule(info, mod, prefix, kind, elements);
 107.381 -        }
 107.382 -
 107.383 -        // I can't just search the scope table for all variables in scope because this
 107.384 -        // will only include the local -bound- variables and the -used- free variables.
 107.385 -        // I need to find potential free variables as well. This means I should walk up
 107.386 -        // the scope chain and compute all eligible names. By keep track of the ones I've
 107.387 -        // already added I avoid adding references to variables I have re-bound in closer
 107.388 -        // scopes.
 107.389 -
 107.390 -        Set<String> added = new HashSet<>();
 107.391 -
 107.392 -        while (scopeInfo != null) {
 107.393 -            for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 107.394 -                String name = entry.getKey();
 107.395 -                if (added.contains(name)) {
 107.396 -                    // Something in narrower scope already processed this one
 107.397 -                    continue;
 107.398 -                }
 107.399 -                if (kind == QuerySupport.Kind.EXACT) {
 107.400 -                    if (!(name.equals(prefix))) {
 107.401 -                        continue;
 107.402 -                    }
 107.403 -                } else if (kind == QuerySupport.Kind.PREFIX) {
 107.404 -                    if (!name.startsWith(prefix)) {
 107.405 -                        continue;
 107.406 -                    }
 107.407 -                } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX) {
 107.408 -                    if (!name.regionMatches(true, 0, prefix, 0, prefix.length())) {
 107.409 -                        continue;
 107.410 -                    }
 107.411 -                }
 107.412 -                SymInfo sym = entry.getValue();
 107.413 -
 107.414 -                ScopeInfo curr = scopeInfo;
 107.415 -                while (sym != null && sym.isFree()) {
 107.416 -                    curr = curr.up;
 107.417 -                    while (curr != null && curr.kind == CLASSSCOPE) {
 107.418 -                        curr = curr.up;
 107.419 -                    }
 107.420 -                    if (curr == null) {
 107.421 -                        sym = null;
 107.422 -                        break;
 107.423 -                    }
 107.424 -                    sym = scopeInfo.tbl.get(name);
 107.425 -                }
 107.426 -                if (sym == null) {
 107.427 -                    continue;
 107.428 -                }
 107.429 -                if (sym.isUnresolved()) {
 107.430 -                    // Don't add completion items for stuff we're not sure about
 107.431 -                    continue;
 107.432 -                }
 107.433 -
 107.434 -                PythonTree node = sym.node;
 107.435 -                if (node == null) {
 107.436 -                    continue;
 107.437 -                }
 107.438 -
 107.439 -
 107.440 -                if (sym.isImported()) {
 107.441 -                    Element element = new AstElement(this, node, name, Character.isUpperCase(name.charAt(0)) ? ElementKind.CLASS : ElementKind.MODULE);
 107.442 -                    elements.add(element);
 107.443 -                } else if (sym.isDef()) {
 107.444 -                    String signature;
 107.445 -                    if (sym.isClass() && node instanceof ClassDef) {
 107.446 -                        signature = PythonIndexer.computeClassSig((ClassDef)node, sym);
 107.447 -                    } else if (sym.isFunction() && node instanceof FunctionDef) {
 107.448 -                        assert sym.isFunction() && node instanceof FunctionDef : name + ";" + sym + " in " + module;
 107.449 -                        signature = PythonIndexer.computeFunctionSig(name, (FunctionDef)node, sym);
 107.450 -                    } else {
 107.451 -                        // Probably a generator expression
 107.452 -                        continue;
 107.453 -                    }
 107.454 -                    //Element element = AstElement.create(null, node);
 107.455 -                    IndexedElement element = IndexedElement.create(signature, module, url, null);
 107.456 -                    element.setSmart(true);
 107.457 -                    elements.add(element);
 107.458 -                } else {
 107.459 -                    // TODO - class attributes?
 107.460 -                    Element element = new AstElement(this, node, name, ElementKind.VARIABLE);
 107.461 -                    elements.add(element);
 107.462 -                }
 107.463 -
 107.464 -                added.add(name);
 107.465 -            }
 107.466 -
 107.467 -            scopeInfo = scopeInfo.up;
 107.468 -            while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 107.469 -                scopeInfo = scopeInfo.up;
 107.470 -            }
 107.471 -        }
 107.472 -
 107.473 -        return elements;
 107.474 -    }
 107.475 -
 107.476 -    // Return all node references to the given name
 107.477 -    // This will include imports, calls, definitions, etc.
 107.478 -    public List<PythonTree> getOccurrences(PythonTree scope, String name, boolean abortOnFree) {
 107.479 -        ScopeInfo scopeInfo = scopes.get(scope);
 107.480 -        if (scopeInfo != null) {
 107.481 -            SymInfo sym = scopeInfo.tbl.get(name);
 107.482 -            while (sym != null && sym.isFree()) {
 107.483 -                if (abortOnFree) {
 107.484 -                    return null;
 107.485 -                }
 107.486 -                scopeInfo = scopeInfo.up;
 107.487 -                while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 107.488 -                    scopeInfo = scopeInfo.up;
 107.489 -                }
 107.490 -                sym = scopeInfo.tbl.get(name);
 107.491 -            }
 107.492 -
 107.493 -            if (sym != null) {
 107.494 -                NameNodeFinder finder = new NameNodeFinder(name, scopeInfo.scope_node);
 107.495 -                finder.run();
 107.496 -                return finder.getNodes();
 107.497 -            }
 107.498 -        }
 107.499 -
 107.500 -        return Collections.emptyList();
 107.501 -    }
 107.502 -
 107.503 -    /** Return a list of the variables visible from a given scope */
 107.504 -    public Set<String> getVarNames(PythonTree scope, boolean mustBeBound) {
 107.505 -        ScopeInfo scopeInfo = scopes.get(scope);
 107.506 -        Set<String> names = new HashSet<>();
 107.507 -        while (scopeInfo != null) {
 107.508 -            for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 107.509 -                String name = entry.getKey();
 107.510 -                SymInfo sym = entry.getValue();
 107.511 -                if (sym.isVariable(mustBeBound)) {
 107.512 -                    names.add(name);
 107.513 -                }
 107.514 -            }
 107.515 -            scopeInfo = scopeInfo.up;
 107.516 -            while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 107.517 -                scopeInfo = scopeInfo.up;
 107.518 -            }
 107.519 -        }
 107.520 -
 107.521 -        return names;
 107.522 -    }
 107.523 -
 107.524 -    public List<ImportEntry> getUnusedImports() {
 107.525 -        List<ImportEntry> unused = new ArrayList<>();
 107.526 -        ScopeInfo scopeInfo = scopes.get(root);
 107.527 -        for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 107.528 -            SymInfo sym = entry.getValue();
 107.529 -            if (sym.isImported() && !sym.isRead()) {
 107.530 -                String name = entry.getKey();
 107.531 -                if (name.equals("*")) { // NOI18N
 107.532 -                    // Not detecting usages of wildcard imports yet...
 107.533 -                    continue;
 107.534 -                }
 107.535 -                PythonTree node = sym.node;
 107.536 -                if (node instanceof Import) {
 107.537 -                    Import imp = (Import)node;
 107.538 -                    int ordinal = 0;
 107.539 -                    String module = null;
 107.540 -                    String asName = null;
 107.541 -                    List<alias> names = imp.getInternalNames();
 107.542 -                    if (names != null) {
 107.543 -                        for (alias at : names) {
 107.544 -                            if (name.equals(at.getInternalAsname())) {
 107.545 -                                module = at.getInternalName();
 107.546 -                                asName = at.getInternalAsname();
 107.547 -                                break;
 107.548 -                            } else if (name.equals(at.getInternalName())) {
 107.549 -                                module = at.getInternalName();
 107.550 -                                break;
 107.551 -                            }
 107.552 -                        }
 107.553 -                        if (module == null) {
 107.554 -                            // For imports with dotted names, like wsgiref.handlers,
 107.555 -                            // the symbol table entry is just "wsgiref", yet I have to match
 107.556 -                            // the symbols, so try again more carefully
 107.557 -                            for (alias at : names) {
 107.558 -                                if (at.getInternalAsname() != null && at.getInternalAsname().startsWith(name) &&
 107.559 -                                        at.getInternalAsname().charAt(name.length()) == '.') {
 107.560 -                                    module = at.getInternalName();
 107.561 -                                    asName = at.getInternalAsname();
 107.562 -                                    break;
 107.563 -                                } else if (at.getInternalName().startsWith(name) &&
 107.564 -                                        at.getInternalName().charAt(name.length()) == '.') {
 107.565 -                                    module = at.getInternalName();
 107.566 -                                    break;
 107.567 -                                }
 107.568 -                            }
 107.569 -                        }
 107.570 -                    }
 107.571 -                    unused.add(new ImportEntry(module, asName, true, imp, imp.getCharStartIndex() + (ordinal++)));
 107.572 -                } else if (node instanceof ImportFrom) {
 107.573 -                    ImportFrom imp = (ImportFrom)node;
 107.574 -                    if (ImportManager.isFutureImport(imp)) {
 107.575 -                        continue;
 107.576 -                    }
 107.577 -                    String module = imp.getInternalModule();
 107.578 -                    String origName = null;
 107.579 -                    String asName = null;
 107.580 -                    int ordinal = 0;
 107.581 -                    List<alias> names = imp.getInternalNames();
 107.582 -                    if (names != null) {
 107.583 -                        for (alias at : names) {
 107.584 -                            if (name.equals(at.getInternalAsname())) {
 107.585 -                                origName = at.getInternalName();
 107.586 -                                asName = at.getInternalAsname();
 107.587 -                                break;
 107.588 -                            } else if (name.equals(at.getInternalName())) {
 107.589 -                                origName = at.getInternalName();
 107.590 -                                break;
 107.591 -                            }
 107.592 -                        }
 107.593 -                        if (origName == null) {
 107.594 -                            // For imports with dotted names, like wsgiref.handlers,
 107.595 -                            // the symbol table entry is just "wsgiref", yet I have to match
 107.596 -                            // the symbols, so try again more carefully
 107.597 -                            for (alias at : names) {
 107.598 -                                if (at.getInternalAsname() != null && at.getInternalAsname().startsWith(name) &&
 107.599 -                                        at.getInternalAsname().charAt(name.length()) == '.') {
 107.600 -                                    origName = at.getInternalName();
 107.601 -                                    asName = at.getInternalAsname();
 107.602 -                                    break;
 107.603 -                                } else if (at.getInternalName().startsWith(name) &&
 107.604 -                                        at.getInternalName().charAt(name.length()) == '.') {
 107.605 -                                    origName = at.getInternalName();
 107.606 -                                    break;
 107.607 -                                }
 107.608 -                            }
 107.609 -                        }
 107.610 -                    }
 107.611 -                    unused.add(new ImportEntry(module, origName, asName, true, imp, imp.getCharStartIndex() + (ordinal++)));
 107.612 -                }
 107.613 -            }
 107.614 -        }
 107.615 -
 107.616 -        return unused;
 107.617 -    }
 107.618 -
 107.619 -    private class NameNodeFinder extends Visitor {
 107.620 -        private List<PythonTree> nodes = new ArrayList<>();
 107.621 -        private PythonTree startScope;
 107.622 -        private String name;
 107.623 -
 107.624 -        public NameNodeFinder(String name, PythonTree startScope) {
 107.625 -            this.name = name;
 107.626 -            this.startScope = startScope;
 107.627 -        }
 107.628 -
 107.629 -        public void run() {
 107.630 -            try {
 107.631 -                visit(startScope);
 107.632 -            } catch (Exception ex) {
 107.633 -                Exceptions.printStackTrace(ex);
 107.634 -            }
 107.635 -        }
 107.636 -
 107.637 -        @Override
 107.638 -        public Object visitImport(Import imp) throws Exception {
 107.639 -            List<alias> names = imp.getInternalNames();
 107.640 -            if (names != null && names.size() > 0) {
 107.641 -                boolean found = false;
 107.642 -                for (alias at : names) {
 107.643 -                    String asName = at.getInternalAsname();
 107.644 -                    if (asName != null) {
 107.645 -                        if (name.equals(asName)) {
 107.646 -                            found = true;
 107.647 -                            break;
 107.648 -                        }
 107.649 -                    } else if (name.equals(at.getInternalName())) {
 107.650 -                        found = true;
 107.651 -                        break;
 107.652 -                    }
 107.653 -                }
 107.654 -                if (found) {
 107.655 -                    nodes.add(imp);
 107.656 -                }
 107.657 -            }
 107.658 -            return super.visitImport(imp);
 107.659 -        }
 107.660 -
 107.661 -        @Override
 107.662 -        public Object visitImportFrom(ImportFrom imp) throws Exception {
 107.663 -            List<alias> names = imp.getInternalNames();
 107.664 -            if (names != null && names.size() > 0) {
 107.665 -                boolean found = false;
 107.666 -                for (alias at : names) {
 107.667 -                    String asName = at.getInternalAsname();
 107.668 -                    if (asName != null) {
 107.669 -                        if (name.equals(asName)) {
 107.670 -                            found = true;
 107.671 -                            break;
 107.672 -                        }
 107.673 -                    } else if (name.equals(at.getInternalName())) {
 107.674 -                        found = true;
 107.675 -                        break;
 107.676 -                    }
 107.677 -                }
 107.678 -                if (found) {
 107.679 -                    nodes.add(imp);
 107.680 -                }
 107.681 -            }
 107.682 -
 107.683 -            return super.visitImportFrom(imp);
 107.684 -        }
 107.685 -
 107.686 -        @Override
 107.687 -        public Object visitName(Name node) throws Exception {
 107.688 -            if (node.getInternalId().equals(name)) {
 107.689 -                nodes.add(node);
 107.690 -            }
 107.691 -            return super.visitName(node);
 107.692 -        }
 107.693 -
 107.694 -        @Override
 107.695 -        public Object visitFunctionDef(FunctionDef node) throws Exception {
 107.696 -            if (name.equals(node.getInternalName())) {
 107.697 -                nodes.add(node);
 107.698 -            }
 107.699 -
 107.700 -            if (isIncludedScope(node)) {
 107.701 -                return super.visitFunctionDef(node);
 107.702 -            } else {
 107.703 -                return null;
 107.704 -            }
 107.705 -        }
 107.706 -
 107.707 -        @Override
 107.708 -        public Object visitClassDef(ClassDef node) throws Exception {
 107.709 -            if (name.equals(node.getInternalName())) {
 107.710 -                nodes.add(node);
 107.711 -            }
 107.712 -
 107.713 -            if (isIncludedScope(node)) {
 107.714 -                return super.visitClassDef(node);
 107.715 -            } else {
 107.716 -                return null;
 107.717 -            }
 107.718 -        }
 107.719 -
 107.720 -        @Override
 107.721 -        public Object visitExpression(Expression node) throws Exception {
 107.722 -            if (isIncludedScope(node)) {
 107.723 -                return super.visitExpression(node);
 107.724 -            } else {
 107.725 -                return null;
 107.726 -            }
 107.727 -        }
 107.728 -
 107.729 -        @Override
 107.730 -        public Object visitInteractive(Interactive node) throws Exception {
 107.731 -            if (isIncludedScope(node)) {
 107.732 -                return super.visitInteractive(node);
 107.733 -            } else {
 107.734 -                return null;
 107.735 -            }
 107.736 -        }
 107.737 -
 107.738 -        @Override
 107.739 -        public Object visitLambda(Lambda node) throws Exception {
 107.740 -            if (isIncludedScope(node)) {
 107.741 -                return super.visitLambda(node);
 107.742 -            } else {
 107.743 -                return null;
 107.744 -            }
 107.745 -        }
 107.746 -
 107.747 -        @Override
 107.748 -        public Object visitGeneratorExp(GeneratorExp node) throws Exception {
 107.749 -            if (isIncludedScope(node)) {
 107.750 -                return super.visitGeneratorExp(node);
 107.751 -            } else {
 107.752 -                return null;
 107.753 -            }
 107.754 -        }
 107.755 -
 107.756 -        private boolean isIncludedScope(PythonTree node) {
 107.757 -            if (node == startScope) {
 107.758 -                return true;
 107.759 -            }
 107.760 -
 107.761 -            ScopeInfo info = scopes.get(node);
 107.762 -            if (info == null) {
 107.763 -                return false;
 107.764 -            }
 107.765 -
 107.766 -            SymInfo sym = info.tbl.get(name);
 107.767 -            // Skip scopes that redefine the variable
 107.768 -            if (sym != null && sym.isBound()) {
 107.769 -                return false;
 107.770 -            }
 107.771 -
 107.772 -            return true;
 107.773 -        }
 107.774 -
 107.775 -        public List<PythonTree> getNodes() {
 107.776 -            return nodes;
 107.777 -        }
 107.778 -    }
 107.779 -
 107.780 -    public Map<String, SymInfo> getUnresolvedNames(PythonParserResult info) {
 107.781 -        Map<String, SymInfo> unresolved = new HashMap<>();
 107.782 -        Set<String> builtin = getBuiltin(info);
 107.783 -
 107.784 -        for (ScopeInfo scopeInfo : scopes.values()) {
 107.785 -            Map<String, SymInfo> tbl = scopeInfo.tbl;
 107.786 -            for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
 107.787 -                SymInfo symInfo = entry.getValue();
 107.788 -                boolean isUnresolved = symInfo.isUnresolved();
 107.789 -                if (!isUnresolved && symInfo.isFree()) {
 107.790 -                    // Peek up scope stack
 107.791 -                    String name = entry.getKey();
 107.792 -                    SymInfo sym = symInfo;
 107.793 -                    ScopeInfo scope = scopeInfo;
 107.794 -                    while (sym != null && sym.isFree()) {
 107.795 -                        scope = scope.up;
 107.796 -                        while (scope != null && scope.kind == CLASSSCOPE) {
 107.797 -                            scope = scope.up;
 107.798 -                        }
 107.799 -                        sym = scope.tbl.get(name);
 107.800 -                    }
 107.801 -                    if (sym == null) {
 107.802 -                        isUnresolved = true;
 107.803 -                    } else {
 107.804 -                        isUnresolved = sym.isUnresolved();
 107.805 -                    }
 107.806 -                }
 107.807 -                if (isUnresolved) {
 107.808 -                    String key = entry.getKey();
 107.809 -                    if (!builtin.contains(key)) {
 107.810 -                        unresolved.put(key, symInfo);
 107.811 -                    }
 107.812 -                }
 107.813 -            }
 107.814 -        }
 107.815 -
 107.816 -        return unresolved;
 107.817 -    }
 107.818 -
 107.819 -    public List<Attribute> getNotInInitAttributes(PythonParserResult info) {
 107.820 -        List<Attribute> notInInitAttribs = new ArrayList<>();
 107.821 -        for (ScopeInfo scopeInfo : scopes.values()) {
 107.822 -            if (scopeInfo.scope_node instanceof ClassDef) {
 107.823 -                if (scopeInfo.attributes != null) {
 107.824 -                    for (Map.Entry<String, SymInfo> entry : scopeInfo.attributes.entrySet()) {
 107.825 -                        SymInfo symInfo = entry.getValue();
 107.826 -                        if (!symInfo.isBoundInConstructor()) {
 107.827 -                            notInInitAttribs.add((Attribute)symInfo.node);
 107.828 -                        }
 107.829 -                    }
 107.830 -                }
 107.831 -            }
 107.832 -        }
 107.833 -        return notInInitAttribs;
 107.834 -    }
 107.835 -
 107.836 -    private ScopeInfo getClassScope(String className) {
 107.837 -        for (ScopeInfo scopeInfo : scopes.values()) {
 107.838 -            if (scopeInfo.scope_node instanceof ClassDef) {
 107.839 -                ClassDef curClass = (ClassDef)scopeInfo.scope_node;
 107.840 -                if (curClass.getInternalName().equals(className)) {
 107.841 -                    return scopeInfo;
 107.842 -                }
 107.843 -            }
 107.844 -        }
 107.845 -        return null;
 107.846 -    }
 107.847 -
 107.848 -    private int belongsToParents(ClassDef cls, String name, HashMap<String, String> cycling) {
 107.849 -        List<expr> bases = cls.getInternalBases();
 107.850 -        if (bases == null || bases.size() == 0) {
 107.851 -            return NO; // no parents
 107.852 -        }
 107.853 -        for (expr base : bases) {
 107.854 -            String className = null;
 107.855 -            if (base instanceof Name) {
 107.856 -                className = ((Name)base).getInternalId();
 107.857 -            } else {
 107.858 -                // should be Attribute here( module.className form )
 107.859 -                // which imply imported from external scope
 107.860 -                // So we give up on scope returning optimistaically True
 107.861 -                return YES;
 107.862 -            }
 107.863 -            assert (className != null);
 107.864 -            if (cycling.get(className) != null) {
 107.865 -                cycling.clear();
 107.866 -                // put parent child conficting back in cycling
 107.867 -                cycling.put(className, cls.getInternalName());
 107.868 -                return CIRCULAR;
 107.869 -            }
 107.870 -            cycling.put(className, className);
 107.871 -            ScopeInfo localClassScope = getClassScope(className);
 107.872 -            if (localClassScope == null) {
 107.873 -                // return true (success) when at least one parent is outside module scope
 107.874 -                // just to notify caller to be optimistic and assume that
 107.875 -                // name is resolved by imported classes inheritance
 107.876 -                // scanning imported classed from here is discouraged for
 107.877 -                // performances reasons
 107.878 -                return YES;
 107.879 -            } else {
 107.880 -                if ((name != null) &&
 107.881 -                        (localClassScope.attributes.get(name) != null)) {
 107.882 -                    return YES;
 107.883 -                }
 107.884 -                // try recurse parentage to resolve attribute
 107.885 -                ClassDef parentClass = (ClassDef)localClassScope.scope_node;
 107.886 -                int recResult = belongsToParents(parentClass, name, cycling);
 107.887 -                if (recResult != NO) // stop on FOUND(YES) or CIRCULAR error
 107.888 -                {
 107.889 -                    return recResult;
 107.890 -                }
 107.891 -            }
 107.892 -        }
 107.893 -        return NO;
 107.894 -    }
 107.895 -
 107.896 -    private boolean isImported(String moduleName) {
 107.897 -        for (Import imported : imports) {
 107.898 -            List<alias> names = imported.getInternalNames();
 107.899 -            if (names != null) {
 107.900 -                for (alias cur : names) {
 107.901 -                    String name = cur.getInternalName();
 107.902 -                    String asName = cur.getInternalAsname();
 107.903 -                    if (((name != null) && (name.equals(moduleName))) ||
 107.904 -                            ((asName != null) && (asName.equals(moduleName)))) {
 107.905 -                        return true;
 107.906 -                    }
 107.907 -                }
 107.908 -            }
 107.909 -        }
 107.910 -        return false;
 107.911 -    }
 107.912 -
 107.913 -    private boolean isImportedFrom(String className) {
 107.914 -        for (ImportFrom importedFrom : importsFrom) {
 107.915 -            List<alias> names = importedFrom.getInternalNames();
 107.916 -            if (names != null) {
 107.917 -                for (alias cur : names) {
 107.918 -                    String name = cur.getInternalName();
 107.919 -                    String asName = cur.getInternalAsname();
 107.920 -                    if (((name != null) && (name.equals(className))) ||
 107.921 -                            ((asName != null) && (asName.equals(className)))) {
 107.922 -                        return true;
 107.923 -                    }
 107.924 -                }
 107.925 -            }
 107.926 -        }
 107.927 -        return false;
 107.928 -    }
 107.929 -
 107.930 -    public List<PythonTree> getUnresolvedParents(PythonParserResult info) {
 107.931 -        // deal with unresolved parents in inherit trees
 107.932 -        List<PythonTree> unresolvedParents = new ArrayList<>();
 107.933 -        PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 107.934 -
 107.935 -        for (String cur : classes.keySet()) {
 107.936 -            ClassDef cls = classes.get(cur);
 107.937 -            List<expr> bases = cls.getInternalBases();
 107.938 -            if (bases == null || bases.size() > 0) {
 107.939 -                // has parents
 107.940 -                for (expr base : bases) {
 107.941 -                    if (base instanceof Name) {
 107.942 -                        String className = ((Name)base).getInternalId();
 107.943 -                        Set<String> builtin = getBuiltin(info);
 107.944 -                        if ((!classes.containsKey(className)) &&
 107.945 -                                (!builtin.contains(className))) {
 107.946 -                            // check in from imports
 107.947 -                            if (!isImportedFrom(className)) {
 107.948 -                                unresolvedParents.add(base);
 107.949 -                            }
 107.950 -                        }
 107.951 -                    } else {
 107.952 -                        // should be Attribute here( module.className form )
 107.953 -                        // which imply imported from external scope
 107.954 -                        Attribute attr = (Attribute)base;
 107.955 -                        String clsName = attr.getInternalAttr();
 107.956 -                        if (attr.getInternalValue() instanceof Name) {
 107.957 -                            String moduleName = ((Name)(attr.getInternalValue())).getInternalId();
 107.958 -                            // check that import is resolved first
 107.959 -                            if (!isImported(moduleName)) {
 107.960 -                                unresolvedParents.add(base);
 107.961 -                            } else {
 107.962 -                                Set<IndexedElement> found = index.getImportedElements(clsName, QuerySupport.Kind.EXACT, Collections.<String>singleton(moduleName), null);
 107.963 -                                if (found.size() == 0) {
 107.964 -                                    unresolvedParents.add(base);
 107.965 -                                }
 107.966 -                            }
 107.967 -                        } else {
 107.968 -                            unresolvedParents.add(base);
 107.969 -                        }
 107.970 -                    }
 107.971 -                }
 107.972 -            }
 107.973 -        }
 107.974 -        return unresolvedParents;
 107.975 -    }
 107.976 -
 107.977 -    public HashMap<ClassDef, String> getClassesCyclingRedundancies(PythonParserResult info) {
 107.978 -        HashMap<ClassDef, String> cyclingRedundancies = new HashMap<>();
 107.979 -        for (String cur : classes.keySet()) {
 107.980 -            HashMap<String, String> returned = new HashMap<>();
 107.981 -            ClassDef curClass = classes.get(cur);
 107.982 -            if (!cyclingRedundancies.containsKey(curClass)) {
 107.983 -                if (belongsToParents(curClass, null, returned) == CIRCULAR) {
 107.984 -                    // store hashMap returned
 107.985 -                    Map.Entry<String, String> cycling = returned.entrySet().iterator().next();
 107.986 -                    cyclingRedundancies.put(curClass, cycling.getKey());
 107.987 -                }
 107.988 -            }
 107.989 -        }
 107.990 -        return cyclingRedundancies;
 107.991 -    }
 107.992 -
 107.993 -    public List<PythonTree> getUnresolvedAttributes(PythonParserResult info) {
 107.994 -        List<PythonTree> unresolvedNodes = new ArrayList<>();
 107.995 -        for (ScopeInfo scopeInfo : scopes.values()) {
 107.996 -            Set<String> unresolved = new HashSet<>();
 107.997 -            Map<String, SymInfo> tbl = scopeInfo.tbl;
 107.998 -            // unresolved attributes in local classes
 107.999 -            Map<String, SymInfo> attribs = scopeInfo.attributes;
107.1000 -            for (Map.Entry<String, SymInfo> curAttr : attribs.entrySet()) {
107.1001 -                SymInfo symInfo = curAttr.getValue();
107.1002 -                if (symInfo.isRead()) {
107.1003 -                    // check for builtin attribs first
107.1004 -                    if (classAttributes.get(curAttr.getKey()) == null) {
107.1005 -                        // not a builtin attribute
107.1006 -                        ScopeInfo parentScope = scopeInfo.getClassScope();
107.1007 -                        if (parentScope != null) {
107.1008 -                            // limit scope to Classes for self and inherited
107.1009 -                            Map<String, SymInfo> parentattribs = parentScope.attributes;
107.1010 -                            SymInfo classAttr = parentattribs.get(curAttr.getKey());
107.1011 -                            tbl = parentScope.tbl;
107.1012 -                            if (classAttr == null) {
107.1013 -                                // may be  also a reference to a method
107.1014 -                                classAttr = tbl.get(curAttr.getKey());
107.1015 -                            }
107.1016 -                            if (classAttr == null) {
107.1017 -                                // do not bother with method since they are
107.1018 -                                // managed by completion
107.1019 -                                ClassDef curClass = (ClassDef)parentScope.scope_node;
107.1020 -                                if (belongsToParents(curClass, curAttr.getKey(), new HashMap()) == NO) {
107.1021 -                                    if (!symInfo.isCalled()) {
107.1022 -                                        // no corresponding attributes
107.1023 -                                        //PythonTree tree = symInfo.node ;
107.1024 -                                        Attribute attr = (Attribute)symInfo.node;
107.1025 -                                        // Name name = new Name(tree.getToken(),attr.getInternalAttr(),attr.ctx) ;
107.1026 -                                        unresolvedNodes.add(attr);
107.1027 -                                    }
107.1028 -                                }
107.1029 -                            }
107.1030 -                        }
107.1031 -                    }
107.1032 -                }
107.1033 -            }
107.1034 -            if (unresolved.size() > 0) {
107.1035 -                NameFinder finder = new NameFinder(unresolved);
107.1036 -                List<Name> nodes = finder.run(scopeInfo.scope_node);
107.1037 -                unresolvedNodes.addAll(nodes);
107.1038 -            }
107.1039 -
107.1040 -        }
107.1041 -
107.1042 -        if (unresolvedNodes.size() > 1) {
107.1043 -            Collections.sort(unresolvedNodes, PythonUtils.ATTRIBUTE_NAME_NODE_COMPARATOR);
107.1044 -            //Collections.sort(unusedNodes, PythonUtils.NODE_POS_COMPARATOR);
107.1045 -        }
107.1046 -
107.1047 -        return unresolvedNodes;
107.1048 -    }
107.1049 -
107.1050 -    public List<PythonTree> getUnresolved(PythonParserResult info) {
107.1051 -        List<PythonTree> unresolvedNodes = new ArrayList<>();
107.1052 -        Set<String> builtin = getBuiltin(info);
107.1053 -
107.1054 -        for (ScopeInfo scopeInfo : scopes.values()) {
107.1055 -            Set<String> unresolved = new HashSet<>();
107.1056 -            Map<String, SymInfo> tbl = scopeInfo.tbl;
107.1057 -            for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
107.1058 -                SymInfo symInfo = entry.getValue();
107.1059 -                boolean isUnresolved = symInfo.isUnresolved();
107.1060 -                if (!isUnresolved && symInfo.isFree()) {
107.1061 -                    // Peek up scope stack
107.1062 -                    String name = entry.getKey();
107.1063 -                    SymInfo sym = symInfo;
107.1064 -                    ScopeInfo scope = scopeInfo;
107.1065 -                    while (sym != null && sym.isFree()) {
107.1066 -                        scope = scope.up;
107.1067 -                        while (scope != null && scope.kind == CLASSSCOPE) {
107.1068 -                            scope = scope.up;
107.1069 -                        }
107.1070 -                        sym = scope.tbl.get(name);
107.1071 -                    }
107.1072 -                    if (sym == null) {
107.1073 -                        isUnresolved = true;
107.1074 -                    } else {
107.1075 -                        isUnresolved = sym.isUnresolved();
107.1076 -                    }
107.1077 -                }
107.1078 -                if (isUnresolved) {
107.1079 -                    String key = entry.getKey();
107.1080 -                    if (!builtin.contains(key)) {
107.1081 -                        unresolved.add(key);
107.1082 -                    }
107.1083 -                }
107.1084 -            }
107.1085 -
107.1086 -
107.1087 -            if (unresolved.size() > 0) {
107.1088 -                // Check imports and see if it's resolved by existing imports
107.1089 -                PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
107.1090 -                // TODO - cache system libraries!
107.1091 -                // TODO - make method which doesn't create elements for these guys!
107.1092 -//                Set<IndexedElement> elements = index.getImportedElements("", NameKind.PREFIX, PythonIndex.ALL_SCOPE, imports, importsFrom);
107.1093 -//                for (IndexedElement e : elements) {
107.1094 -//                    unresolved.remove(e.getName());
107.1095 -//                }
107.1096 -                Set<String> wildcarded = index.getImportedFromWildcards(importsFrom);
107.1097 -                unresolved.removeAll(wildcarded);
107.1098 -
107.1099 -                if (unresolved.size() > 0) {
107.1100 -                    NameFinder finder = new NameFinder(unresolved);
107.1101 -                    List<Name> nodes = finder.run(scopeInfo.scope_node);
107.1102 -                    unresolvedNodes.addAll(nodes);
107.1103 -                }
107.1104 -            }
107.1105 -        }
107.1106 -
107.1107 -        if (unresolvedNodes.size() > 1) {
107.1108 -            Collections.sort(unresolvedNodes, PythonUtils.ATTRIBUTE_NAME_NODE_COMPARATOR);
107.1109 -            //Collections.sort(unusedNodes, PythonUtils.NODE_POS_COMPARATOR);
107.1110 -        }
107.1111 -
107.1112 -        return unresolvedNodes;
107.1113 -    }
107.1114 -
107.1115 -    public List<PythonTree> getUnused(boolean skipSelf, boolean skipParams) { // not used for unused imports, see separate method
107.1116 -        List<PythonTree> unusedNodes = new ArrayList<>();
107.1117 -
107.1118 -        for (ScopeInfo scopeInfo : scopes.values()) {
107.1119 -            if (scopeInfo.kind != FUNCSCOPE) {
107.1120 -                continue;
107.1121 -            }
107.1122 -            Set<String> unused = new HashSet<>();
107.1123 -            Map<String, SymInfo> tbl = scopeInfo.tbl;
107.1124 -            for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
107.1125 -                SymInfo symInfo = entry.getValue();
107.1126 -                if (symInfo.isUnused(scopeInfo) && (!skipParams || !symInfo.isParameter())) {
107.1127 -                    String key = entry.getKey();
107.1128 -                    if (skipSelf && "self".equals(key)) { // NOI18N
107.1129 -                        continue;
107.1130 -                    }
107.1131 -                    unused.add(key);
107.1132 -                }
107.1133 -            }
107.1134 -
107.1135 -            if (unused.size() > 0) {
107.1136 -                NameFinder finder = new NameFinder(unused);
107.1137 -                List<Name> nodes = finder.run(scopeInfo.scope_node);
107.1138 -                unusedNodes.addAll(nodes);
107.1139 -            }
107.1140 -        }
107.1141 -
107.1142 -        if (unusedNodes.size() > 1) {
107.1143 -            Collections.sort(unusedNodes, PythonUtils.NAME_NODE_COMPARATOR);
107.1144 -            //Collections.sort(unusedNodes, PythonUtils.NODE_POS_COMPARATOR);
107.1145 -        }
107.1146 -
107.1147 -        return unusedNodes;
107.1148 -    }
107.1149 -
107.1150 -    private static class NameFinder extends Visitor {
107.1151 -        private Set<String> names;
107.1152 -        private List<Name> nodes = new ArrayList<>();
107.1153 -        private PythonTree acceptDef;
107.1154 -
107.1155 -        private NameFinder(Set<String> names) {
107.1156 -            this.names = names;
107.1157 -        }
107.1158 -
107.1159 -        @Override
107.1160 -        public Object visitClassDef(ClassDef node) throws Exception {
107.1161 -            // Don't look in nested scopes
107.1162 -            if (node != acceptDef) {
107.1163 -                return null;
107.1164 -            }
107.1165 -            return super.visitClassDef(node);
107.1166 -        }
107.1167 -
107.1168 -        @Override
107.1169 -        public Object visitFunctionDef(FunctionDef node) throws Exception {
107.1170 -            // Don't look in nested scopes
107.1171 -            if (node != acceptDef) {
107.1172 -                return null;
107.1173 -            }
107.1174 -            return super.visitFunctionDef(node);
107.1175 -        }
107.1176 -
107.1177 -        @Override
107.1178 -        public Object visitName(Name node) throws Exception {
107.1179 -            String name = node.getInternalId();
107.1180 -            if (names.contains(name)) {
107.1181 -                nodes.add(node);
107.1182 -            }
107.1183 -
107.1184 -            return super.visitName(node);
107.1185 -        }
107.1186 -
107.1187 -        public List<Name> run(PythonTree node) {
107.1188 -            this.acceptDef = node;
107.1189 -            try {
107.1190 -                visit(node);
107.1191 -            } catch (Exception ex) {
107.1192 -                Exceptions.printStackTrace(ex);
107.1193 -            }
107.1194 -
107.1195 -            return nodes;
107.1196 -        }
107.1197 -    }
107.1198 -    private static Set<String> builtinSymbols;
107.1199 -
107.1200 -    private Set<String> getBuiltin(PythonParserResult info) {
107.1201 -        if (builtinSymbols == null) {
107.1202 -            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
107.1203 -            builtinSymbols = index.getBuiltinSymbols();
107.1204 -        }
107.1205 -
107.1206 -        return builtinSymbols;
107.1207 -    }
107.1208 -
107.1209 -    public void error(String msg, boolean err, PythonTree node) throws Exception {
107.1210 -        assert node != null;
107.1211 -        // TODO - record and register with the hints manager?
107.1212 -        OffsetRange range = PythonAstUtils.getRange(node);
107.1213 -
107.1214 -        if (errors == null) {
107.1215 -            errors = new ArrayList<>();
107.1216 -        }
107.1217 -        Error error = new DefaultError(null, msg, null, fileObject, range.getStart(), range.getEnd(), err ? Severity.ERROR : Severity.WARNING);
107.1218 -        errors.add(error);
107.1219 -    }
107.1220 -
107.1221 -    public String getFilename() {
107.1222 -        return FileUtil.getFileDisplayName(fileObject);
107.1223 -    }
107.1224 -
107.1225 -    public Map<PythonTree, ScopeInfo> getScopes() {
107.1226 -        return scopes;
107.1227 -    }
107.1228 -
107.1229 -    public List<Import> getImports() {
107.1230 -        return imports;
107.1231 -    }
107.1232 -
107.1233 -    public List<ImportFrom> getImportsFrom() {
107.1234 -        return importsFrom;
107.1235 -    }
107.1236 -
107.1237 -    public boolean isTopLevel(PythonTree node) {
107.1238 -        return topLevelImports.contains(node);
107.1239 -    }
107.1240 -
107.1241 -    public List<PythonTree> getMainImports() {
107.1242 -        return mainImports;
107.1243 -    }
107.1244 -
107.1245 -    public Set<PythonTree> getTopLevelImports() {
107.1246 -        return topLevelImports;
107.1247 -    }
107.1248 -
107.1249 -    public List<Str> getPublicSymbols() {
107.1250 -        return publicSymbols;
107.1251 -    }
107.1252 -}
   108.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   108.2 +++ b/python.hints/build.xml	Sun Sep 13 11:47:42 2015 +0200
   108.3 @@ -0,0 +1,5 @@
   108.4 +<?xml version="1.0" encoding="UTF-8"?>
   108.5 +<project basedir="." default="netbeans" name="contrib/python.hints">
   108.6 +    <description>Builds, tests, and runs the project org.netbeans.modules.python.hints</description>
   108.7 +    <import file="../../nbbuild/templates/projectized.xml"/>
   108.8 +</project>
   109.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   109.2 +++ b/python.hints/manifest.mf	Sun Sep 13 11:47:42 2015 +0200
   109.3 @@ -0,0 +1,7 @@
   109.4 +Manifest-Version: 1.0
   109.5 +AutoUpdate-Show-In-Client: true
   109.6 +OpenIDE-Module: org.netbeans.modules.python.hints
   109.7 +OpenIDE-Module-Layer: org/netbeans/modules/python/hints/layer.xml
   109.8 +OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/python/hints/Bundle.properties
   109.9 +OpenIDE-Module-Specification-Version: 1.0
  109.10 +
   110.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.2 +++ b/python.hints/nbproject/project.properties	Sun Sep 13 11:47:42 2015 +0200
   110.3 @@ -0,0 +1,2 @@
   110.4 +javac.source=1.7
   110.5 +javac.compilerargs=-Xlint -Xlint:-serial
   111.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.2 +++ b/python.hints/nbproject/project.xml	Sun Sep 13 11:47:42 2015 +0200
   111.3 @@ -0,0 +1,157 @@
   111.4 +<?xml version="1.0" encoding="UTF-8"?>
   111.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
   111.6 +    <type>org.netbeans.modules.apisupport.project</type>
   111.7 +    <configuration>
   111.8 +        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
   111.9 +            <code-name-base>org.netbeans.modules.python.hints</code-name-base>
  111.10 +            <module-dependencies>
  111.11 +                <dependency>
  111.12 +                    <code-name-base>org.jython</code-name-base>
  111.13 +                    <build-prerequisite/>
  111.14 +                    <compile-dependency/>
  111.15 +                    <run-dependency>
  111.16 +                        <release-version>2</release-version>
  111.17 +                        <specification-version>2.12</specification-version>
  111.18 +                    </run-dependency>
  111.19 +                </dependency>
  111.20 +                <dependency>
  111.21 +                    <code-name-base>org.netbeans.modules.csl.api</code-name-base>
  111.22 +                    <build-prerequisite/>
  111.23 +                    <compile-dependency/>
  111.24 +                    <run-dependency>
  111.25 +                        <release-version>2</release-version>
  111.26 +                        <specification-version>2.51</specification-version>
  111.27 +                    </run-dependency>
  111.28 +                </dependency>
  111.29 +                <dependency>
  111.30 +                    <code-name-base>org.netbeans.modules.editor.codetemplates</code-name-base>
  111.31 +                    <build-prerequisite/>
  111.32 +                    <compile-dependency/>
  111.33 +                    <run-dependency>
  111.34 +                        <release-version>1</release-version>
  111.35 +                        <specification-version>1.41</specification-version>
  111.36 +                    </run-dependency>
  111.37 +                </dependency>
  111.38 +                <dependency>
  111.39 +                    <code-name-base>org.netbeans.modules.editor.document</code-name-base>
  111.40 +                    <build-prerequisite/>
  111.41 +                    <compile-dependency/>
  111.42 +                    <run-dependency>
  111.43 +                        <specification-version>1.5</specification-version>
  111.44 +                    </run-dependency>
  111.45 +                </dependency>
  111.46 +                <dependency>
  111.47 +                    <code-name-base>org.netbeans.modules.editor.indent</code-name-base>
  111.48 +                    <build-prerequisite/>
  111.49 +                    <compile-dependency/>
  111.50 +                    <run-dependency>
  111.51 +                        <release-version>2</release-version>
  111.52 +                        <specification-version>1.42</specification-version>
  111.53 +                    </run-dependency>
  111.54 +                </dependency>
  111.55 +                <dependency>
  111.56 +                    <code-name-base>org.netbeans.modules.editor.lib</code-name-base>
  111.57 +                    <build-prerequisite/>
  111.58 +                    <compile-dependency/>
  111.59 +                    <run-dependency>
  111.60 +                        <release-version>3</release-version>
  111.61 +                        <specification-version>4.3</specification-version>
  111.62 +                    </run-dependency>
  111.63 +                </dependency>
  111.64 +                <dependency>
  111.65 +                    <code-name-base>org.netbeans.modules.lexer</code-name-base>
  111.66 +                    <build-prerequisite/>
  111.67 +                    <compile-dependency/>
  111.68 +                    <run-dependency>
  111.69 +                        <release-version>2</release-version>
  111.70 +                        <specification-version>1.62</specification-version>
  111.71 +                    </run-dependency>
  111.72 +                </dependency>
  111.73 +                <dependency>
  111.74 +                    <code-name-base>org.netbeans.modules.options.api</code-name-base>
  111.75 +                    <build-prerequisite/>
  111.76 +                    <compile-dependency/>
  111.77 +                    <run-dependency>
  111.78 +                        <release-version>1</release-version>
  111.79 +                        <specification-version>1.44</specification-version>
  111.80 +                    </run-dependency>
  111.81 +                </dependency>
  111.82 +                <dependency>
  111.83 +                    <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
  111.84 +                    <build-prerequisite/>
  111.85 +                    <compile-dependency/>
  111.86 +                    <run-dependency>
  111.87 +                        <release-version>1</release-version>
  111.88 +                        <specification-version>9.5</specification-version>
  111.89 +                    </run-dependency>
  111.90 +                </dependency>
  111.91 +                <dependency>
  111.92 +                    <code-name-base>org.netbeans.modules.parsing.indexing</code-name-base>
  111.93 +                    <build-prerequisite/>
  111.94 +                    <compile-dependency/>
  111.95 +                    <run-dependency>
  111.96 +                        <specification-version>9.7</specification-version>
  111.97 +                    </run-dependency>
  111.98 +                </dependency>
  111.99 +                <dependency>
 111.100 +                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
 111.101 +                    <build-prerequisite/>
 111.102 +                    <compile-dependency/>
 111.103 +                    <run-dependency>
 111.104 +                        <release-version>1</release-version>
 111.105 +                        <specification-version>1.65</specification-version>
 111.106 +                    </run-dependency>
 111.107 +                </dependency>
 111.108 +                <dependency>
 111.109 +                    <code-name-base>org.netbeans.modules.python.core</code-name-base>
 111.110 +                    <build-prerequisite/>
 111.111 +                    <compile-dependency/>
 111.112 +                    <run-dependency>
 111.113 +                        <specification-version>1.4</specification-version>
 111.114 +                    </run-dependency>
 111.115 +                </dependency>
 111.116 +                <dependency>
 111.117 +                    <code-name-base>org.netbeans.modules.python.editor</code-name-base>
 111.118 +                    <build-prerequisite/>
 111.119 +                    <compile-dependency/>
 111.120 +                    <run-dependency>
 111.121 +                        <specification-version>1.8.2</specification-version>
 111.122 +                    </run-dependency>
 111.123 +                </dependency>
 111.124 +                <dependency>
 111.125 +                    <code-name-base>org.netbeans.modules.python.source</code-name-base>
 111.126 +                    <build-prerequisite/>
 111.127 +                    <compile-dependency/>
 111.128 +                    <run-dependency>
 111.129 +                        <specification-version>1.1</specification-version>
 111.130 +                    </run-dependency>
 111.131 +                </dependency>
 111.132 +                <dependency>
 111.133 +                    <code-name-base>org.openide.filesystems</code-name-base>
 111.134 +                    <build-prerequisite/>
 111.135 +                    <compile-dependency/>
 111.136 +                    <run-dependency>
 111.137 +                        <specification-version>9.8</specification-version>
 111.138 +                    </run-dependency>
 111.139 +                </dependency>
 111.140 +                <dependency>
 111.141 +                    <code-name-base>org.openide.util</code-name-base>
 111.142 +                    <build-prerequisite/>
 111.143 +                    <compile-dependency/>
 111.144 +                    <run-dependency>
 111.145 +                        <specification-version>9.5</specification-version>
 111.146 +                    </run-dependency>
 111.147 +                </dependency>
 111.148 +                <dependency>
 111.149 +                    <code-name-base>org.openide.util.lookup</code-name-base>
 111.150 +                    <build-prerequisite/>
 111.151 +                    <compile-dependency/>
 111.152 +                    <run-dependency>
 111.153 +                        <specification-version>8.32</specification-version>
 111.154 +                    </run-dependency>
 111.155 +                </dependency>
 111.156 +            </module-dependencies>
 111.157 +            <public-packages/>
 111.158 +        </data>
 111.159 +    </configuration>
 111.160 +</project>
   112.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/AccessToProtected.java	Sun Sep 13 11:47:42 2015 +0200
   112.3 @@ -0,0 +1,150 @@
   112.4 +/*
   112.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   112.6 + *
   112.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   112.8 + *
   112.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  112.10 + * Other names may be trademarks of their respective owners.
  112.11 + *
  112.12 + * The contents of this file are subject to the terms of either the GNU
  112.13 + * General Public License Version 2 only ("GPL") or the Common
  112.14 + * Development and Distribution License("CDDL") (collectively, the
  112.15 + * "License"). You may not use this file except in compliance with the
  112.16 + * License. You can obtain a copy of the License at
  112.17 + * http://www.netbeans.org/cddl-gplv2.html
  112.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  112.19 + * specific language governing permissions and limitations under the
  112.20 + * License.  When distributing the software, include this License Header
  112.21 + * Notice in each file and include the License file at
  112.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  112.23 + * particular file as subject to the "Classpath" exception as provided
  112.24 + * by Oracle in the GPL Version 2 section of the License file that
  112.25 + * accompanied this code. If applicable, add the following below the
  112.26 + * License Header, with the fields enclosed by brackets [] replaced by
  112.27 + * your own identifying information:
  112.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  112.29 + *
  112.30 + * If you wish your version of this file to be governed by only the CDDL
  112.31 + * or only the GPL Version 2, indicate your decision by adding
  112.32 + * "[Contributor] elects to include this software in this distribution
  112.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  112.34 + * single choice of license, a recipient has the option to distribute
  112.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  112.36 + * to extend the choice of license to its licensees as provided above.
  112.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  112.38 + * Version 2 license, then the option applies only if the new code is
  112.39 + * made subject to such option by the copyright holder.
  112.40 + *
  112.41 + * Contributor(s):
  112.42 + *
  112.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  112.44 + */
  112.45 +package org.netbeans.modules.python.hints;
  112.46 +
  112.47 +import java.util.Collections;
  112.48 +import java.util.List;
  112.49 +import java.util.Set;
  112.50 +import java.util.prefs.Preferences;
  112.51 +import javax.swing.JComponent;
  112.52 +import org.netbeans.modules.csl.api.Hint;
  112.53 +import org.netbeans.modules.csl.api.HintFix;
  112.54 +import org.netbeans.modules.csl.api.HintSeverity;
  112.55 +import org.netbeans.modules.csl.api.OffsetRange;
  112.56 +import org.netbeans.modules.csl.api.RuleContext;
  112.57 +import org.netbeans.modules.python.source.PythonAstUtils;
  112.58 +import org.netbeans.modules.python.source.PythonParserResult;
  112.59 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  112.60 +import org.netbeans.modules.python.source.NameStyle;
  112.61 +import org.openide.util.NbBundle;
  112.62 +import org.python.antlr.ast.Attribute;
  112.63 +import org.python.antlr.ast.Name;
  112.64 +import org.python.antlr.base.expr;
  112.65 +
  112.66 +/**
  112.67 + * Check direct acces to parent protected variables or methods
  112.68 + * @author jean-yves Mengant
  112.69 + */
  112.70 +public class AccessToProtected extends PythonAstRule {
  112.71 +    private final static String ACCESS_PROTECTED_ID = "AccessProtected"; // NOI18N
  112.72 +    private final static String ACCESS_PROTECTED_VARIABLE = "AccessProtectedVariable"; // NOI18N
  112.73 +    private final static String ACCESS_PROTECTED_DESC = "AccessProtectedDesc"; // NOI18N
  112.74 +
  112.75 +    @Override
  112.76 +    public Set<Class> getKinds() {
  112.77 +        return Collections.<Class>singleton(Attribute.class);
  112.78 +    }
  112.79 +
  112.80 +    @Override
  112.81 +    public void run(PythonRuleContext context, List<Hint> result) {
  112.82 +        PythonParserResult info = (PythonParserResult) context.parserResult;
  112.83 +        Attribute cur = (Attribute)context.node;
  112.84 +        String curAttr = cur.getInternalAttr();
  112.85 +        if (curAttr == null) {
  112.86 +            return;
  112.87 +        }
  112.88 +
  112.89 +        if (NameStyle.isProtectedName(curAttr)) {
  112.90 +            expr curValue = cur.getInternalValue();
  112.91 +            if (curValue instanceof Name) {
  112.92 +                Name nam = (Name)curValue;
  112.93 +                String id = nam.getInternalId();
  112.94 +                if (id.equals("self")) { // NOI18N
  112.95 +                    return; // normal access from class instance
  112.96 +                }
  112.97 +                if (PythonAstUtils.getParentClassFromNode(context.path, null, id) != null) {
  112.98 +                    return; // parent access
  112.99 +                }
 112.100 +                // we should warn here : Access to protected Attributes from non child
 112.101 +                // classes
 112.102 +                OffsetRange range = PythonAstUtils.getRange(cur);
 112.103 +                range = PythonLexerUtils.getLexerOffsets(info, range);
 112.104 +                if (range != OffsetRange.NONE) {
 112.105 +                    List<HintFix> fixList = Collections.emptyList();
 112.106 +                    String message = NbBundle.getMessage(NameRule.class, ACCESS_PROTECTED_VARIABLE, curAttr);
 112.107 +                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
 112.108 +                    result.add(desc);
 112.109 +                }
 112.110 +            }
 112.111 +        }
 112.112 +    }
 112.113 +
 112.114 +    @Override
 112.115 +    public String getId() {
 112.116 +        return ACCESS_PROTECTED_ID;
 112.117 +    }
 112.118 +
 112.119 +    @Override
 112.120 +    public String getDescription() {
 112.121 +        return NbBundle.getMessage(RelativeImports.class, ACCESS_PROTECTED_DESC);
 112.122 +    }
 112.123 +
 112.124 +    @Override
 112.125 +    public boolean getDefaultEnabled() {
 112.126 +        return false;
 112.127 +    }
 112.128 +
 112.129 +    @Override
 112.130 +    public JComponent getCustomizer(Preferences node) {
 112.131 +        return null;
 112.132 +    }
 112.133 +
 112.134 +    @Override
 112.135 +    public boolean appliesTo(RuleContext context) {
 112.136 +        return true;
 112.137 +    }
 112.138 +
 112.139 +    @Override
 112.140 +    public String getDisplayName() {
 112.141 +        return NbBundle.getMessage(AccessToProtected.class, ACCESS_PROTECTED_ID);
 112.142 +    }
 112.143 +
 112.144 +    @Override
 112.145 +    public boolean showInTasklist() {
 112.146 +        return true;
 112.147 +    }
 112.148 +
 112.149 +    @Override
 112.150 +    public HintSeverity getDefaultSeverity() {
 112.151 +        return HintSeverity.WARNING;
 112.152 +    }
 112.153 +}
   113.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/AllAssignExists.java	Sun Sep 13 11:47:42 2015 +0200
   113.3 @@ -0,0 +1,148 @@
   113.4 +/*
   113.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   113.6 + *
   113.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   113.8 + *
   113.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  113.10 + * Other names may be trademarks of their respective owners.
  113.11 + *
  113.12 + * The contents of this file are subject to the terms of either the GNU
  113.13 + * General Public License Version 2 only ("GPL") or the Common
  113.14 + * Development and Distribution License("CDDL") (collectively, the
  113.15 + * "License"). You may not use this file except in compliance with the
  113.16 + * License. You can obtain a copy of the License at
  113.17 + * http://www.netbeans.org/cddl-gplv2.html
  113.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  113.19 + * specific language governing permissions and limitations under the
  113.20 + * License.  When distributing the software, include this License Header
  113.21 + * Notice in each file and include the License file at
  113.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  113.23 + * particular file as subject to the "Classpath" exception as provided
  113.24 + * by Oracle in the GPL Version 2 section of the License file that
  113.25 + * accompanied this code. If applicable, add the following below the
  113.26 + * License Header, with the fields enclosed by brackets [] replaced by
  113.27 + * your own identifying information:
  113.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  113.29 + *
  113.30 + * If you wish your version of this file to be governed by only the CDDL
  113.31 + * or only the GPL Version 2, indicate your decision by adding
  113.32 + * "[Contributor] elects to include this software in this distribution
  113.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  113.34 + * single choice of license, a recipient has the option to distribute
  113.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  113.36 + * to extend the choice of license to its licensees as provided above.
  113.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  113.38 + * Version 2 license, then the option applies only if the new code is
  113.39 + * made subject to such option by the copyright holder.
  113.40 + *
  113.41 + * Contributor(s):
  113.42 + *
  113.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  113.44 + */
  113.45 +package org.netbeans.modules.python.hints;
  113.46 +
  113.47 +import java.util.Collections;
  113.48 +import java.util.List;
  113.49 +import java.util.Set;
  113.50 +import java.util.prefs.Preferences;
  113.51 +import javax.swing.JComponent;
  113.52 +import org.netbeans.modules.csl.api.Hint;
  113.53 +import org.netbeans.modules.csl.api.HintFix;
  113.54 +import org.netbeans.modules.csl.api.HintSeverity;
  113.55 +import org.netbeans.modules.csl.api.OffsetRange;
  113.56 +import org.netbeans.modules.csl.api.RuleContext;
  113.57 +import org.netbeans.modules.python.source.PythonAstUtils;
  113.58 +import org.netbeans.modules.python.source.PythonParserResult;
  113.59 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  113.60 +import org.netbeans.modules.python.source.scopes.ScopeInfo;
  113.61 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  113.62 +import org.netbeans.modules.python.source.scopes.SymInfo;
  113.63 +import org.openide.util.NbBundle;
  113.64 +import org.python.antlr.ast.Module;
  113.65 +import org.python.antlr.ast.Str;
  113.66 +
  113.67 +/**
  113.68 + *
  113.69 + * @author Tor Norbye
  113.70 + */
  113.71 +public class AllAssignExists extends PythonAstRule {
  113.72 +    @Override
  113.73 +    public Set<Class> getKinds() {
  113.74 +        return Collections.<Class>singleton(Module.class);
  113.75 +    }
  113.76 +
  113.77 +    @Override
  113.78 +    public void run(PythonRuleContext context, List<Hint> result) {
  113.79 +        PythonParserResult ppr = (PythonParserResult)context.parserResult;
  113.80 +        SymbolTable symbolTable = ppr.getSymbolTable();
  113.81 +        List<Str> publicSymbols = symbolTable.getPublicSymbols();
  113.82 +        if (publicSymbols != null) {
  113.83 +            // Check that we actually have all the symbols called for
  113.84 +            // by the all-list
  113.85 +
  113.86 +            ScopeInfo topScope = symbolTable.getScopeInfo(context.node);
  113.87 +            assert topScope != null;
  113.88 +
  113.89 +            // Mark all other symbols private!
  113.90 +            for (Str str : publicSymbols) {
  113.91 +                //String name = PythonAstUtils.getExprName(expr);
  113.92 +                String name = PythonAstUtils.getStrContent(str);
  113.93 +                if (name != null) {
  113.94 +                    SymInfo sym = topScope.tbl.get(name);
  113.95 +                    if (sym == null) {
  113.96 +                        // Uh oh -- missing!
  113.97 +                        PythonParserResult info = (PythonParserResult) context.parserResult;
  113.98 +                        OffsetRange range = PythonAstUtils.getNameRange(info, str);
  113.99 +                        range = PythonLexerUtils.getLexerOffsets(info, range);
 113.100 +                        if (range != OffsetRange.NONE) {
 113.101 +                            List<HintFix> fixList = Collections.emptyList();
 113.102 +                            String message = NbBundle.getMessage(AllAssignExists.class, "AllAssignExistsMsg", name);
 113.103 +                            Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 205);
 113.104 +                            result.add(desc);
 113.105 +                        }
 113.106 +                    }
 113.107 +                }
 113.108 +            }
 113.109 +        }
 113.110 +    }
 113.111 +
 113.112 +    @Override
 113.113 +    public String getId() {
 113.114 +        return "AllAssignExists"; // NOI18N
 113.115 +    }
 113.116 +
 113.117 +    @Override
 113.118 +    public String getDescription() {
 113.119 +        return NbBundle.getMessage(AllAssignExists.class, "AllAssignExistsDesc");
 113.120 +    }
 113.121 +
 113.122 +    @Override
 113.123 +    public boolean getDefaultEnabled() {
 113.124 +        return true;
 113.125 +    }
 113.126 +
 113.127 +    @Override
 113.128 +    public JComponent getCustomizer(Preferences node) {
 113.129 +        return null;
 113.130 +    }
 113.131 +
 113.132 +    @Override
 113.133 +    public boolean appliesTo(RuleContext context) {
 113.134 +        return true;
 113.135 +    }
 113.136 +
 113.137 +    @Override
 113.138 +    public String getDisplayName() {
 113.139 +        return NbBundle.getMessage(AllAssignExists.class, "AllAssignExists");
 113.140 +    }
 113.141 +
 113.142 +    @Override
 113.143 +    public boolean showInTasklist() {
 113.144 +        return true;
 113.145 +    }
 113.146 +
 113.147 +    @Override
 113.148 +    public HintSeverity getDefaultSeverity() {
 113.149 +        return HintSeverity.ERROR;
 113.150 +    }
 113.151 +}
   114.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   114.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/AssignToVariable.java	Sun Sep 13 11:47:42 2015 +0200
   114.3 @@ -0,0 +1,245 @@
   114.4 +/*
   114.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   114.6 + *
   114.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   114.8 + *
   114.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  114.10 + * Other names may be trademarks of their respective owners.
  114.11 + *
  114.12 + * The contents of this file are subject to the terms of either the GNU
  114.13 + * General Public License Version 2 only ("GPL") or the Common
  114.14 + * Development and Distribution License("CDDL") (collectively, the
  114.15 + * "License"). You may not use this file except in compliance with the
  114.16 + * License. You can obtain a copy of the License at
  114.17 + * http://www.netbeans.org/cddl-gplv2.html
  114.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  114.19 + * specific language governing permissions and limitations under the
  114.20 + * License.  When distributing the software, include this License Header
  114.21 + * Notice in each file and include the License file at
  114.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  114.23 + * particular file as subject to the "Classpath" exception as provided
  114.24 + * by Oracle in the GPL Version 2 section of the License file that
  114.25 + * accompanied this code. If applicable, add the following below the
  114.26 + * License Header, with the fields enclosed by brackets [] replaced by
  114.27 + * your own identifying information:
  114.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  114.29 + *
  114.30 + * If you wish your version of this file to be governed by only the CDDL
  114.31 + * or only the GPL Version 2, indicate your decision by adding
  114.32 + * "[Contributor] elects to include this software in this distribution
  114.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  114.34 + * single choice of license, a recipient has the option to distribute
  114.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  114.36 + * to extend the choice of license to its licensees as provided above.
  114.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  114.38 + * Version 2 license, then the option applies only if the new code is
  114.39 + * made subject to such option by the copyright holder.
  114.40 + *
  114.41 + * Contributor(s):
  114.42 + *
  114.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  114.44 + */
  114.45 +package org.netbeans.modules.python.hints;
  114.46 +
  114.47 +import java.util.ArrayList;
  114.48 +import java.util.Collections;
  114.49 +import java.util.List;
  114.50 +import java.util.Set;
  114.51 +import java.util.prefs.Preferences;
  114.52 +import javax.swing.JComponent;
  114.53 +import javax.swing.text.BadLocationException;
  114.54 +import javax.swing.text.JTextComponent;
  114.55 +import javax.swing.text.Position;
  114.56 +import org.netbeans.modules.python.source.PythonAstUtils;
  114.57 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  114.58 +import org.netbeans.editor.BaseDocument;
  114.59 +import org.netbeans.editor.Utilities;
  114.60 +import org.netbeans.modules.csl.api.EditList;
  114.61 +import org.netbeans.modules.csl.api.Hint;
  114.62 +import org.netbeans.modules.csl.api.HintFix;
  114.63 +import org.netbeans.modules.csl.api.HintSeverity;
  114.64 +import org.netbeans.modules.csl.api.OffsetRange;
  114.65 +import org.netbeans.modules.csl.api.PreviewableFix;
  114.66 +import org.netbeans.modules.csl.api.RuleContext;
  114.67 +import org.netbeans.modules.csl.spi.GsfUtilities;
  114.68 +import org.netbeans.modules.python.source.PythonParserResult;
  114.69 +import org.openide.util.Exceptions;
  114.70 +import org.openide.util.NbBundle;
  114.71 +import org.python.antlr.PythonTree;
  114.72 +import org.python.antlr.ast.Call;
  114.73 +import org.python.antlr.ast.Expr;
  114.74 +import org.python.antlr.ast.FunctionDef;
  114.75 +import org.python.antlr.ast.Str;
  114.76 +import org.python.antlr.base.expr;
  114.77 +import org.python.antlr.base.stmt;
  114.78 +
  114.79 +/**
  114.80 + * Assign an expression to a variable
  114.81 + *
  114.82 + * @author Tor Norbye
  114.83 + */
  114.84 +public class AssignToVariable extends PythonAstRule {
  114.85 +    @Override
  114.86 +    public Set<Class> getKinds() {
  114.87 +        return Collections.singleton((Class)Expr.class);
  114.88 +    }
  114.89 +
  114.90 +    @Override
  114.91 +    public void run(PythonRuleContext context, List<Hint> result) {
  114.92 +        PythonTree node = context.node;
  114.93 +        Expr expr = (Expr)node;
  114.94 +        expr exprValue = expr.getInternalValue();
  114.95 +        if (exprValue instanceof Str) {
  114.96 +            // Skip triple-quoted strings (typically doc strings)
  114.97 +            Str str = (Str)exprValue;
  114.98 +            String s = str.getText();
  114.99 +            if (s.startsWith("'''") || s.startsWith("\"\"\"")) { // NOI18N
 114.100 +                return;
 114.101 +            }
 114.102 +            PythonTree grandParent = context.path.leafGrandParent();
 114.103 +            if (grandParent instanceof FunctionDef) {
 114.104 +                FunctionDef def = (FunctionDef)grandParent;
 114.105 +                List<stmt> body = def.getInternalBody();
 114.106 +                if (body != null && body.size() > 0 && body.get(0) == expr) {
 114.107 +                    // First string in a function -- it's a docstring
 114.108 +                    return;
 114.109 +                }
 114.110 +            }
 114.111 +        }
 114.112 +        if (exprValue instanceof Call) {
 114.113 +            // Skip calls - they may have side effects
 114.114 +            // ...unless it looks like a "getter" style Python method
 114.115 +            Call call = (Call)exprValue;
 114.116 +            if (!PythonAstUtils.isGetter(call, false)) {
 114.117 +                return;
 114.118 +            }
 114.119 +        }
 114.120 +        PythonParserResult info = (PythonParserResult) context.parserResult;
 114.121 +        OffsetRange astOffsets = PythonAstUtils.getNameRange(info, node);
 114.122 +        OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
 114.123 +        BaseDocument doc = context.doc;
 114.124 +        try {
 114.125 +            if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
 114.126 +                    (context.caretOffset == -1 ||
 114.127 +                    Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
 114.128 +                List<HintFix> fixList = new ArrayList<>();
 114.129 +                fixList.add(new AssignToVariableFix(context, node));
 114.130 +                String displayName = getDisplayName();
 114.131 +                Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
 114.132 +                result.add(desc);
 114.133 +            }
 114.134 +        } catch (BadLocationException ex) {
 114.135 +            Exceptions.printStackTrace(ex);
 114.136 +        }
 114.137 +    }
 114.138 +
 114.139 +    @Override
 114.140 +    public String getId() {
 114.141 +        return "AssignToVariable"; // NOI18N
 114.142 +    }
 114.143 +
 114.144 +    @Override
 114.145 +    public String getDisplayName() {
 114.146 +        return NbBundle.getMessage(AssignToVariable.class, "AssignToVariable");
 114.147 +    }
 114.148 +
 114.149 +    @Override
 114.150 +    public String getDescription() {
 114.151 +        return NbBundle.getMessage(AssignToVariable.class, "AssignToVariableDesc");
 114.152 +    }
 114.153 +
 114.154 +    @Override
 114.155 +    public boolean getDefaultEnabled() {
 114.156 +        return true;
 114.157 +    }
 114.158 +
 114.159 +    @Override
 114.160 +    public JComponent getCustomizer(Preferences node) {
 114.161 +        return null;
 114.162 +    }
 114.163 +
 114.164 +    @Override
 114.165 +    public boolean appliesTo(RuleContext context) {
 114.166 +        return true;
 114.167 +    }
 114.168 +
 114.169 +    @Override
 114.170 +    public boolean showInTasklist() {
 114.171 +        return false;
 114.172 +    }
 114.173 +
 114.174 +    @Override
 114.175 +    public HintSeverity getDefaultSeverity() {
 114.176 +        return HintSeverity.CURRENT_LINE_WARNING;
 114.177 +    }
 114.178 +
 114.179 +    private static class AssignToVariableFix implements PreviewableFix {
 114.180 +        private final PythonRuleContext context;
 114.181 +        private final PythonTree node;
 114.182 +        private int varOffset;
 114.183 +        private String varName;
 114.184 +
 114.185 +        private AssignToVariableFix(PythonRuleContext context, PythonTree node) {
 114.186 +            this.context = context;
 114.187 +            this.node = node;
 114.188 +        }
 114.189 +
 114.190 +        @Override
 114.191 +        public String getDescription() {
 114.192 +            return NbBundle.getMessage(AssignToVariable.class, "AssignToVariableFix");
 114.193 +        }
 114.194 +
 114.195 +        @Override
 114.196 +        public boolean canPreview() {
 114.197 +            return true;
 114.198 +        }
 114.199 +
 114.200 +        @Override
 114.201 +        public EditList getEditList() throws Exception {
 114.202 +            BaseDocument doc = context.doc;
 114.203 +            EditList edits = new EditList(doc);
 114.204 +
 114.205 +            OffsetRange astRange = PythonAstUtils.getRange(node);
 114.206 +            if (astRange != OffsetRange.NONE) {
 114.207 +                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets((PythonParserResult) context.parserResult, astRange);
 114.208 +                if (lexRange != OffsetRange.NONE) {
 114.209 +                    int offset = lexRange.getStart();
 114.210 +                    StringBuilder sb = new StringBuilder();
 114.211 +                    varName = NbBundle.getMessage(AssignToVariable.class, "VarName");
 114.212 +                    sb.append(varName);
 114.213 +                    sb.append(" = "); // NOI18N
 114.214 +                    varOffset = offset;
 114.215 +                    edits.replace(offset, 0, sb.toString(), false, 0);
 114.216 +                }
 114.217 +            }
 114.218 +
 114.219 +            return edits;
 114.220 +        }
 114.221 +
 114.222 +        @Override
 114.223 +        public void implement() throws Exception {
 114.224 +            EditList edits = getEditList();
 114.225 +
 114.226 +            Position pos = edits.createPosition(varOffset);
 114.227 +            edits.apply();
 114.228 +            if (pos != null && pos.getOffset() != -1) {
 114.229 +                JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
 114.230 +                if (target != null) {
 114.231 +                    int start = pos.getOffset();
 114.232 +                    int end = start + varName.length();
 114.233 +                    target.select(start, end);
 114.234 +                }
 114.235 +            }
 114.236 +        }
 114.237 +
 114.238 +        @Override
 114.239 +        public boolean isSafe() {
 114.240 +            return true;
 114.241 +        }
 114.242 +
 114.243 +        @Override
 114.244 +        public boolean isInteractive() {
 114.245 +            return false;
 114.246 +        }
 114.247 +    }
 114.248 +}
   115.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/AttributeDefinedOutsideInit.java	Sun Sep 13 11:47:42 2015 +0200
   115.3 @@ -0,0 +1,140 @@
   115.4 +/*
   115.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   115.6 + *
   115.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   115.8 + *
   115.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  115.10 + * Other names may be trademarks of their respective owners.
  115.11 + *
  115.12 + * The contents of this file are subject to the terms of either the GNU
  115.13 + * General Public License Version 2 only ("GPL") or the Common
  115.14 + * Development and Distribution License("CDDL") (collectively, the
  115.15 + * "License"). You may not use this file except in compliance with the
  115.16 + * License. You can obtain a copy of the License at
  115.17 + * http://www.netbeans.org/cddl-gplv2.html
  115.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  115.19 + * specific language governing permissions and limitations under the
  115.20 + * License.  When distributing the software, include this License Header
  115.21 + * Notice in each file and include the License file at
  115.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  115.23 + * particular file as subject to the "Classpath" exception as provided
  115.24 + * by Oracle in the GPL Version 2 section of the License file that
  115.25 + * accompanied this code. If applicable, add the following below the
  115.26 + * License Header, with the fields enclosed by brackets [] replaced by
  115.27 + * your own identifying information:
  115.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  115.29 + *
  115.30 + * If you wish your version of this file to be governed by only the CDDL
  115.31 + * or only the GPL Version 2, indicate your decision by adding
  115.32 + * "[Contributor] elects to include this software in this distribution
  115.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  115.34 + * single choice of license, a recipient has the option to distribute
  115.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  115.36 + * to extend the choice of license to its licensees as provided above.
  115.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  115.38 + * Version 2 license, then the option applies only if the new code is
  115.39 + * made subject to such option by the copyright holder.
  115.40 + *
  115.41 + * Contributor(s):
  115.42 + *
  115.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  115.44 + */
  115.45 +package org.netbeans.modules.python.hints;
  115.46 +
  115.47 +import java.util.Collections;
  115.48 +import java.util.List;
  115.49 +import java.util.Set;
  115.50 +import java.util.prefs.Preferences;
  115.51 +import javax.swing.JComponent;
  115.52 +import org.netbeans.modules.csl.api.Hint;
  115.53 +import org.netbeans.modules.csl.api.HintFix;
  115.54 +import org.netbeans.modules.csl.api.HintSeverity;
  115.55 +import org.netbeans.modules.csl.api.OffsetRange;
  115.56 +import org.netbeans.modules.csl.api.RuleContext;
  115.57 +import org.netbeans.modules.python.source.PythonAstUtils;
  115.58 +import org.netbeans.modules.python.source.PythonParserResult;
  115.59 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  115.60 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  115.61 +import org.openide.util.NbBundle;
  115.62 +import org.python.antlr.ast.Attribute;
  115.63 +import org.python.antlr.ast.Module;
  115.64 +
  115.65 +/**
  115.66 + *
  115.67 + * @author Jean-Yves Mengant
  115.68 + */
  115.69 +public class AttributeDefinedOutsideInit extends PythonAstRule {
  115.70 +    private final static String ATTRIBUTE_DEFINED_OUTSIDE_INIT = "AttributeDefinedOutsideInit";
  115.71 +    private final static String ATTRIBUTE_DEFINED_OUTSITE_INIT_VAR = "AttributeDefinedOutsideInitVariable";
  115.72 +    private final static String ATTRIBUTE_DEFINED_OUTSIDE_INIT_DESC = "AttributeDefinedOutsideInitDesc";
  115.73 +
  115.74 +    @Override
  115.75 +    public Set<Class> getKinds() {
  115.76 +        return Collections.<Class>singleton(Module.class);
  115.77 +    }
  115.78 +
  115.79 +    @Override
  115.80 +    public void run(PythonRuleContext context, List<Hint> result) {
  115.81 +        PythonParserResult info = (PythonParserResult) context.parserResult;
  115.82 +        PythonParserResult pr = PythonAstUtils.getParseResult(info);
  115.83 +        SymbolTable symbolTable = pr.getSymbolTable();
  115.84 +
  115.85 +
  115.86 +        List<Attribute> notInIntBound = symbolTable.getNotInInitAttributes(info);
  115.87 +        if (notInIntBound.size() > 0) {
  115.88 +            for (Attribute cur : notInIntBound) {
  115.89 +                OffsetRange range = PythonAstUtils.getRange(cur);
  115.90 +                range = PythonLexerUtils.getLexerOffsets(info, range);
  115.91 +                if (range != OffsetRange.NONE) {
  115.92 +                    List<HintFix> fixList = Collections.emptyList();
  115.93 +                    String message = NbBundle.getMessage(NameRule.class,
  115.94 +                            ATTRIBUTE_DEFINED_OUTSITE_INIT_VAR,
  115.95 +                            cur.getInternalAttr());
  115.96 +                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
  115.97 +                    result.add(desc);
  115.98 +                }
  115.99 +            }
 115.100 +        }
 115.101 +
 115.102 +    }
 115.103 +
 115.104 +    @Override
 115.105 +    public String getId() {
 115.106 +        return ATTRIBUTE_DEFINED_OUTSIDE_INIT;
 115.107 +    }
 115.108 +
 115.109 +    @Override
 115.110 +    public String getDescription() {
 115.111 +        return NbBundle.getMessage(RelativeImports.class, ATTRIBUTE_DEFINED_OUTSIDE_INIT_DESC);
 115.112 +    }
 115.113 +
 115.114 +    @Override
 115.115 +    public boolean getDefaultEnabled() {
 115.116 +        return false;
 115.117 +    }
 115.118 +
 115.119 +    @Override
 115.120 +    public JComponent getCustomizer(Preferences node) {
 115.121 +        return null;
 115.122 +    }
 115.123 +
 115.124 +    @Override
 115.125 +    public boolean appliesTo(RuleContext context) {
 115.126 +        return true;
 115.127 +    }
 115.128 +
 115.129 +    @Override
 115.130 +    public String getDisplayName() {
 115.131 +        return NbBundle.getMessage(AccessToProtected.class, ATTRIBUTE_DEFINED_OUTSIDE_INIT);
 115.132 +    }
 115.133 +
 115.134 +    @Override
 115.135 +    public boolean showInTasklist() {
 115.136 +        return true;
 115.137 +    }
 115.138 +
 115.139 +    @Override
 115.140 +    public HintSeverity getDefaultSeverity() {
 115.141 +        return HintSeverity.WARNING;
 115.142 +    }
 115.143 +}
   116.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   116.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/Bundle.properties	Sun Sep 13 11:47:42 2015 +0200
   116.3 @@ -0,0 +1,147 @@
   116.4 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   116.5 +#
   116.6 +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   116.7 +#
   116.8 +# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   116.9 +# Other names may be trademarks of their respective owners.
  116.10 +#
  116.11 +# The contents of this file are subject to the terms of either the GNU
  116.12 +# General Public License Version 2 only ("GPL") or the Common
  116.13 +# Development and Distribution License("CDDL") (collectively, the
  116.14 +# "License"). You may not use this file except in compliance with the
  116.15 +# License. You can obtain a copy of the License at
  116.16 +# http://www.netbeans.org/cddl-gplv2.html
  116.17 +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  116.18 +# specific language governing permissions and limitations under the
  116.19 +# License.  When distributing the software, include this License Header
  116.20 +# Notice in each file and include the License file at
  116.21 +# nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  116.22 +# particular file as subject to the "Classpath" exception as provided
  116.23 +# by Oracle in the GPL Version 2 section of the License file that
  116.24 +# accompanied this code. If applicable, add the following below the
  116.25 +# License Header, with the fields enclosed by brackets [] replaced by
  116.26 +# your own identifying information:
  116.27 +# "Portions Copyrighted [year] [name of copyright owner]"
  116.28 +#
  116.29 +# Contributor(s):
  116.30 +#
  116.31 +# The Original Software is NetBeans. The Initial Developer of the Original
  116.32 +# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  116.33 +# Microsystems, Inc. All Rights Reserved.
  116.34 +#
  116.35 +# If you wish your version of this file to be governed by only the CDDL
  116.36 +# or only the GPL Version 2, indicate your decision by adding
  116.37 +# "[Contributor] elects to include this software in this distribution
  116.38 +# under the [CDDL or GPL Version 2] license." If you do not indicate a
  116.39 +# single choice of license, a recipient has the option to distribute
  116.40 +# your version of this file under either the CDDL, the GPL Version 2 or
  116.41 +# to extend the choice of license to its licensees as provided above.
  116.42 +# However, if you add GPL Version 2 code and therefore, elected the GPL
  116.43 +# Version 2 license, then the option applies only if the new code is
  116.44 +# made subject to such option by the copyright holder.
  116.45 +
  116.46 +# Category descriptions in the Options Panel
  116.47 +gsf-hints/text/x-python/hints/general=General
  116.48 +
  116.49 +# NameRule
  116.50 +NameRule=Naming Conventions
  116.51 +NameRuleDesc=Check class, function and variable names for style guide compliance (see http://www.python.org/dev/peps/pep-0008/ for rules)
  116.52 +NameRuleWrongNoArg=First argument should be 'self' or 'cls'
  116.53 +NameRuleWrongArg=First argument ({0}) should be 'self' or 'cls'
  116.54 +WrongStyle=Name "{0}" is not a valid {1} name according to your code style ({2})
  116.55 +Module=module
  116.56 +Function=function
  116.57 +Class=class
  116.58 +Variable=variable
  116.59 +ChangeStyle=Change preferred {0} name style to {1}
  116.60 +ChangeNoStyle=Turn off {0} name style checks
  116.61 +IgnoreWord=Ignore name violations for "{0}"
  116.62 +NameRulePrefs.selfCb.text=First method params should be "self" or "cls"
  116.63 +NameRulePrefs.moduleLabel.text=Modules:
  116.64 +NameRulePrefs.classLabel.text=Classes:
  116.65 +NameRulePrefs.functionLabel.text=Functions:
  116.66 +NameRulePrefs.parameterLabel.text=Parameters:
  116.67 +NameRulePrefs.variableLabel.text=Variables:
  116.68 +NameRulePrefs.ignoreLabel.text=Ignored:
  116.69 +
  116.70 +CreateDocString=Create document comment
  116.71 +CreateDocStringDesc=Offer to create a documentation comment for the current function, class or module
  116.72 +CreateDocStringFix=Add a one-liner docstring
  116.73 +CreateDocStringFixMulti=Add a multi-line docstring
  116.74 +
  116.75 +AssignToVariable=Assign expression to a variable
  116.76 +AssignToVariableDesc=Assign expression under the caret to a variable
  116.77 +AssignToVariableFix=Assign expression to a variable
  116.78 +VarName=name
  116.79 +
  116.80 +SplitImports=Multiple imports per import statement is discouraged
  116.81 +SplitImportsDesc=Split an import which imports multiple modules into individual import statements as recommended by the Python styleguide
  116.82 +SplitImportsFix=Split import into individual import statements
  116.83 +
  116.84 +RelativeImports=Relative imports for intra-package imports are actively discouraged (as per PEP-008)
  116.85 +RelativeImportsDesc=Relative imports for intra-package imports are actively discouraged (as per PEP-008) and this rule warns about usages of relative imports
  116.86 +RelativeImportsFix=Replace with absolute import
  116.87 +
  116.88 +Deprecations=Deprecated
  116.89 +DeprecationsMsg={0} is deprecated
  116.90 +DeprecationsMsgDetail={0} is deprecated. {1}
  116.91 +DeprecationsDesc=Check for deprecated modules
  116.92 +
  116.93 +SurroundWith=Surround With...
  116.94 +#SurroundWithDesc=Offer to surround selected code with try/catch, etc
  116.95 +SurroundWithTE=Surround With Try/Except
  116.96 +SurroundWithTEF=Surround With Try/Except/Finally
  116.97 +SurroundWithTF=Surround With Try/Finally
  116.98 +InsertSelf=Insert a new first parameter "self"
  116.99 +RenameSelf=Rename first parameter "{0}" to self
 116.100 +
 116.101 +ExtractCode=Extract Code
 116.102 +IntroduceMethod=Extract Method
 116.103 +IntroduceVariable=Introduce Variable
 116.104 +IntroduceConstant=Introduce Constant
 116.105 +IntroduceField=Introduce Field
 116.106 +
 116.107 +UnusedImport=Unused Import
 116.108 +UnusedImportSymbols=Some symbols are unused ({0})
 116.109 +UnusedImports=Find Unused Imports
 116.110 +UnusedImportsDesc=Find imports that aren't used in this module and can be removed
 116.111 +UnusedFix=Remove Unused Import
 116.112 +UnusedFixSymbols=Remove {0} from import
 116.113 +OrganizeImports=Clean up and Organize Imports
 116.114 +DeleteAllUnused=Remove All Unused Imports
 116.115 +
 116.116 +Unused=Find Unused Variables
 116.117 +UnusedDesc=Find variables that are defined but never used
 116.118 +UnusedVariable=Unused Variable {0}
 116.119 +
 116.120 +Unresolved=Find Undefined Names
 116.121 +UnresolvedDesc=Find names that are used but have not been bound
 116.122 +UnresolvedVariable=Undefined name "{0}"
 116.123 +UnresolvedVariableMaybe=Undefined name "{0}" - did you mean "{1}" ?
 116.124 +FixImport=Import {0}
 116.125 +
 116.126 +UnresolvedAttributes=Find Unresolved classes attributes and parentages
 116.127 +UnresolvedAttributesDesc=Find class attributes that are used but have not been bound and undefined inherited classes
 116.128 +UnresolvedAttributesVariable=Undefined attribute "{0}"
 116.129 +UnresolvedInheritanceVariable=Inheriting from undefined parent class "{0}"
 116.130 +
 116.131 +AccessProtected=Access Protected Attributes
 116.132 +AccessProtectedDesc=Find access to protected variables/methods of non parent classes
 116.133 +AccessProtectedVariable=Access to protected variable "{0}"
 116.134 +
 116.135 +AttributeDefinedOutsideInit=Attribute Defined Outside __init__
 116.136 +AttributeDefinedOutsideInitDesc=Class Attribute defined outside __init__ constructor
 116.137 +AttributeDefinedOutsideInitVariable=Attribute Defined Outside __init__ "{0}"
 116.138 +
 116.139 +ClassCircularRedundancy=Parent Child circular redundancy
 116.140 +ClassCircularRedundancyDesc=Parent Child circular redundancy = A inherits B and B inherits A
 116.141 +ClassCircularRedundancyVariable=Parent/child {0} inheritance circular redundancy
 116.142 +
 116.143 +AllAssignExists=Symbol defined in __all__ does not exist
 116.144 +AllAssignExistsDesc=Checks that all symbols listed in __all__ actually exist
 116.145 +AllAssignExistsMsg="{0}" defined in __all__ does not exist!
 116.146 +UnusedDetectorPrefs.skipParams.text=Ignore unused function parameters
 116.147 +UnusedDetectorPrefs.ignoredLabel.text=Ignored names:
 116.148 +UnusedDetectorPrefs.skipTupleAssignments.text=Ignore unused variables in tuple-assignments
 116.149 +
 116.150 +OpenIDE-Module-Name=Python Hints
   117.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   117.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/ClassCircularRedundancy.java	Sun Sep 13 11:47:42 2015 +0200
   117.3 @@ -0,0 +1,140 @@
   117.4 +/*
   117.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   117.6 + *
   117.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   117.8 + *
   117.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  117.10 + * Other names may be trademarks of their respective owners.
  117.11 + *
  117.12 + * The contents of this file are subject to the terms of either the GNU
  117.13 + * General Public License Version 2 only ("GPL") or the Common
  117.14 + * Development and Distribution License("CDDL") (collectively, the
  117.15 + * "License"). You may not use this file except in compliance with the
  117.16 + * License. You can obtain a copy of the License at
  117.17 + * http://www.netbeans.org/cddl-gplv2.html
  117.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  117.19 + * specific language governing permissions and limitations under the
  117.20 + * License.  When distributing the software, include this License Header
  117.21 + * Notice in each file and include the License file at
  117.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  117.23 + * particular file as subject to the "Classpath" exception as provided
  117.24 + * by Oracle in the GPL Version 2 section of the License file that
  117.25 + * accompanied this code. If applicable, add the following below the
  117.26 + * License Header, with the fields enclosed by brackets [] replaced by
  117.27 + * your own identifying information:
  117.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  117.29 + *
  117.30 + * If you wish your version of this file to be governed by only the CDDL
  117.31 + * or only the GPL Version 2, indicate your decision by adding
  117.32 + * "[Contributor] elects to include this software in this distribution
  117.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  117.34 + * single choice of license, a recipient has the option to distribute
  117.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  117.36 + * to extend the choice of license to its licensees as provided above.
  117.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  117.38 + * Version 2 license, then the option applies only if the new code is
  117.39 + * made subject to such option by the copyright holder.
  117.40 + *
  117.41 + * Contributor(s):
  117.42 + *
  117.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  117.44 + */
  117.45 +package org.netbeans.modules.python.hints;
  117.46 +
  117.47 +import java.util.Collections;
  117.48 +import java.util.HashMap;
  117.49 +import java.util.List;
  117.50 +import java.util.Map.Entry;
  117.51 +import java.util.Set;
  117.52 +import java.util.prefs.Preferences;
  117.53 +import javax.swing.JComponent;
  117.54 +import org.netbeans.modules.csl.api.Hint;
  117.55 +import org.netbeans.modules.csl.api.HintFix;
  117.56 +import org.netbeans.modules.csl.api.HintSeverity;
  117.57 +import org.netbeans.modules.csl.api.OffsetRange;
  117.58 +import org.netbeans.modules.csl.api.RuleContext;
  117.59 +import org.netbeans.modules.python.source.PythonAstUtils;
  117.60 +import org.netbeans.modules.python.source.PythonParserResult;
  117.61 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  117.62 +import org.openide.util.NbBundle;
  117.63 +import org.python.antlr.ast.ClassDef;
  117.64 +import org.python.antlr.ast.Module;
  117.65 +
  117.66 +/**
  117.67 + * check for redundancy cycling in parent child
  117.68 + * @author Jean-Yves Mengant
  117.69 + */
  117.70 +public class ClassCircularRedundancy extends PythonAstRule {
  117.71 +    private final static String CLASS_CIRCULAR_REDUNDANCY = "ClassCircularRedundancy";
  117.72 +    private final static String CLASS_CIRCULAR_REDUNDANCY_VAR = "ClassCircularRedundancyVariable";
  117.73 +    private final static String CLASS_CIRCULAR_REDUNDANCY_DESC = "ClassCircularRedundancyDesc";
  117.74 +
  117.75 +    @Override
  117.76 +    public Set<Class> getKinds() {
  117.77 +        return Collections.<Class>singleton(Module.class);
  117.78 +    }
  117.79 +
  117.80 +    @Override
  117.81 +    public void run(PythonRuleContext context, List<Hint> result) {
  117.82 +        PythonParserResult info = (PythonParserResult) context.parserResult;
  117.83 +        SymbolTable symbolTable = info.getSymbolTable();
  117.84 +
  117.85 +
  117.86 +        HashMap<ClassDef, String> cyclingRedundancies = symbolTable.getClassesCyclingRedundancies(info);
  117.87 +        if (cyclingRedundancies.size() > 0) {
  117.88 +            Set<Entry<ClassDef, String>> wk = cyclingRedundancies.entrySet();
  117.89 +            for (Entry<ClassDef, String> cur : wk) {
  117.90 +                ClassDef curClass = cur.getKey();
  117.91 +                String curCyclingMsg = curClass.getInternalName() + "/" + cur.getValue(); // NOI18N
  117.92 +                OffsetRange range = PythonAstUtils.getNameRange(info, curClass);
  117.93 +                // range = PythonLexerUtils.getLexerOffsets(info, range);
  117.94 +                if (range != OffsetRange.NONE) {
  117.95 +                    List<HintFix> fixList = Collections.emptyList();
  117.96 +                    String message = NbBundle.getMessage(NameRule.class, CLASS_CIRCULAR_REDUNDANCY_VAR, curCyclingMsg);
  117.97 +                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
  117.98 +                    result.add(desc);
  117.99 +                }
 117.100 +            }
 117.101 +        }
 117.102 +    }
 117.103 +
 117.104 +    @Override
 117.105 +    public String getId() {
 117.106 +        return CLASS_CIRCULAR_REDUNDANCY;
 117.107 +    }
 117.108 +
 117.109 +    @Override
 117.110 +    public String getDescription() {
 117.111 +        return NbBundle.getMessage(RelativeImports.class, CLASS_CIRCULAR_REDUNDANCY_DESC);
 117.112 +    }
 117.113 +
 117.114 +    @Override
 117.115 +    public boolean getDefaultEnabled() {
 117.116 +        return false;
 117.117 +    }
 117.118 +
 117.119 +    @Override
 117.120 +    public JComponent getCustomizer(Preferences node) {
 117.121 +        return null;
 117.122 +    }
 117.123 +
 117.124 +    @Override
 117.125 +    public boolean appliesTo(RuleContext context) {
 117.126 +        return true;
 117.127 +    }
 117.128 +
 117.129 +    @Override
 117.130 +    public String getDisplayName() {
 117.131 +        return NbBundle.getMessage(AccessToProtected.class, CLASS_CIRCULAR_REDUNDANCY);
 117.132 +    }
 117.133 +
 117.134 +    @Override
 117.135 +    public boolean showInTasklist() {
 117.136 +        return true;
 117.137 +    }
 117.138 +
 117.139 +    @Override
 117.140 +    public HintSeverity getDefaultSeverity() {
 117.141 +        return HintSeverity.ERROR;
 117.142 +    }
 117.143 +}
   118.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   118.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/CreateDocString.java	Sun Sep 13 11:47:42 2015 +0200
   118.3 @@ -0,0 +1,241 @@
   118.4 +/*
   118.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   118.6 + *
   118.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   118.8 + *
   118.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  118.10 + * Other names may be trademarks of their respective owners.
  118.11 + *
  118.12 + * The contents of this file are subject to the terms of either the GNU
  118.13 + * General Public License Version 2 only ("GPL") or the Common
  118.14 + * Development and Distribution License("CDDL") (collectively, the
  118.15 + * "License"). You may not use this file except in compliance with the
  118.16 + * License. You can obtain a copy of the License at
  118.17 + * http://www.netbeans.org/cddl-gplv2.html
  118.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  118.19 + * specific language governing permissions and limitations under the
  118.20 + * License.  When distributing the software, include this License Header
  118.21 + * Notice in each file and include the License file at
  118.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  118.23 + * particular file as subject to the "Classpath" exception as provided
  118.24 + * by Oracle in the GPL Version 2 section of the License file that
  118.25 + * accompanied this code. If applicable, add the following below the
  118.26 + * License Header, with the fields enclosed by brackets [] replaced by
  118.27 + * your own identifying information:
  118.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  118.29 + *
  118.30 + * Contributor(s):
  118.31 + *
  118.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  118.33 + */
  118.34 +package org.netbeans.modules.python.hints;
  118.35 +
  118.36 +import java.util.ArrayList;
  118.37 +import java.util.Collections;
  118.38 +import java.util.HashSet;
  118.39 +import java.util.List;
  118.40 +import java.util.Set;
  118.41 +import java.util.prefs.Preferences;
  118.42 +import javax.swing.JComponent;
  118.43 +import javax.swing.text.BadLocationException;
  118.44 +import javax.swing.text.JTextComponent;
  118.45 +import javax.swing.text.Position;
  118.46 +import org.netbeans.modules.python.source.PythonAstUtils;
  118.47 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  118.48 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
  118.49 +import org.netbeans.api.lexer.Token;
  118.50 +import org.netbeans.api.lexer.TokenSequence;
  118.51 +import org.netbeans.editor.BaseDocument;
  118.52 +import org.netbeans.editor.Utilities;
  118.53 +import org.netbeans.modules.csl.api.EditList;
  118.54 +import org.netbeans.modules.csl.api.Hint;
  118.55 +import org.netbeans.modules.csl.api.HintFix;
  118.56 +import org.netbeans.modules.csl.api.HintSeverity;
  118.57 +import org.netbeans.modules.csl.api.OffsetRange;
  118.58 +import org.netbeans.modules.csl.api.PreviewableFix;
  118.59 +import org.netbeans.modules.csl.api.RuleContext;
  118.60 +import org.netbeans.modules.csl.spi.GsfUtilities;
  118.61 +import org.netbeans.modules.editor.indent.api.IndentUtils;
  118.62 +import org.netbeans.modules.python.source.PythonParserResult;
  118.63 +import org.openide.util.Exceptions;
  118.64 +import org.openide.util.NbBundle;
  118.65 +import org.python.antlr.PythonTree;
  118.66 +import org.python.antlr.ast.ClassDef;
  118.67 +import org.python.antlr.ast.FunctionDef;
  118.68 +
  118.69 +/**
  118.70 + * Offer to create docstrings.
  118.71 + * @todo Handle modules?
  118.72 + * @todo Handle parameter tags (for epydoc etc)
  118.73 + *
  118.74 + * @author Tor Norbye
  118.75 + */
  118.76 +public class CreateDocString extends PythonAstRule {
  118.77 +    @Override
  118.78 +    public Set<Class> getKinds() {
  118.79 +        Set<Class> classes = new HashSet<>();
  118.80 +        classes.add(FunctionDef.class);
  118.81 +        classes.add(ClassDef.class);
  118.82 +
  118.83 +        return classes;
  118.84 +    }
  118.85 +
  118.86 +    @Override
  118.87 +    public void run(PythonRuleContext context, List<Hint> result) {
  118.88 +
  118.89 +        PythonTree node = context.node;
  118.90 +        if (PythonAstUtils.getDocumentationNode(node) != null) {
  118.91 +            return;
  118.92 +        }
  118.93 +
  118.94 +        // Create new fix
  118.95 +        PythonParserResult info = (PythonParserResult) context.parserResult;
  118.96 +        OffsetRange astOffsets = PythonAstUtils.getNameRange(info, node);
  118.97 +        OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
  118.98 +        BaseDocument doc = context.doc;
  118.99 +        try {
 118.100 +            if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
 118.101 +                    (context.caretOffset == -1 ||
 118.102 +                    Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
 118.103 +                List<HintFix> fixList = new ArrayList<>();
 118.104 +                boolean singleIsDefault = node.getClass() == FunctionDef.class;
 118.105 +                fixList.add(new CreateDocStringFix(context, node, !singleIsDefault));
 118.106 +                fixList.add(new CreateDocStringFix(context, node, singleIsDefault));
 118.107 +                String displayName = getDisplayName();
 118.108 +                Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
 118.109 +                result.add(desc);
 118.110 +            }
 118.111 +        } catch (BadLocationException ex) {
 118.112 +            Exceptions.printStackTrace(ex);
 118.113 +        }
 118.114 +    }
 118.115 +
 118.116 +    @Override
 118.117 +    public String getId() {
 118.118 +        return "CreateDocString"; // NOI18N
 118.119 +    }
 118.120 +
 118.121 +    @Override
 118.122 +    public String getDisplayName() {
 118.123 +        return NbBundle.getMessage(CreateDocString.class, "CreateDocString");
 118.124 +    }
 118.125 +
 118.126 +    @Override
 118.127 +    public String getDescription() {
 118.128 +        return NbBundle.getMessage(CreateDocString.class, "CreateDocStringDesc");
 118.129 +    }
 118.130 +
 118.131 +    @Override
 118.132 +    public boolean getDefaultEnabled() {
 118.133 +        return true;
 118.134 +    }
 118.135 +
 118.136 +    @Override
 118.137 +    public JComponent getCustomizer(Preferences node) {
 118.138 +        return null;
 118.139 +    }
 118.140 +
 118.141 +    @Override
 118.142 +    public boolean appliesTo(RuleContext context) {
 118.143 +        return true;
 118.144 +    }
 118.145 +
 118.146 +    @Override
 118.147 +    public boolean showInTasklist() {
 118.148 +        return false;
 118.149 +    }
 118.150 +
 118.151 +    @Override
 118.152 +    public HintSeverity getDefaultSeverity() {
 118.153 +        return HintSeverity.CURRENT_LINE_WARNING;
 118.154 +    }
 118.155 +
 118.156 +    private static class CreateDocStringFix implements PreviewableFix {
 118.157 +        private final PythonRuleContext context;
 118.158 +        private final PythonTree node;
 118.159 +        private final boolean multiLine;
 118.160 +        private int editListPosition;
 118.161 +
 118.162 +        private CreateDocStringFix(PythonRuleContext context, PythonTree node, boolean multiLine) {
 118.163 +            this.context = context;
 118.164 +            this.node = node;
 118.165 +            this.multiLine = multiLine;
 118.166 +        }
 118.167 +
 118.168 +        @Override
 118.169 +        public String getDescription() {
 118.170 +            return multiLine ? NbBundle.getMessage(CreateDocString.class, "CreateDocStringFixMulti") : NbBundle.getMessage(CreateDocString.class, "CreateDocStringFix");
 118.171 +        }
 118.172 +
 118.173 +        @Override
 118.174 +        public boolean canPreview() {
 118.175 +            return true;
 118.176 +        }
 118.177 +
 118.178 +        @Override
 118.179 +        public EditList getEditList() throws Exception {
 118.180 +            BaseDocument doc = context.doc;
 118.181 +            EditList edits = new EditList(doc);
 118.182 +
 118.183 +            OffsetRange astRange = PythonAstUtils.getRange(node);
 118.184 +            if (astRange != OffsetRange.NONE) {
 118.185 +                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets((PythonParserResult) context.parserResult, astRange);
 118.186 +                if (lexRange != OffsetRange.NONE) {
 118.187 +                    // Find the colon
 118.188 +                    TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPositionedSequence(doc, lexRange.getStart());
 118.189 +                    if (ts != null) {
 118.190 +                        Token<? extends PythonTokenId> token = PythonLexerUtils.findNextIncluding(ts, Collections.singletonList(PythonTokenId.COLON));
 118.191 +                        if (token != null) {
 118.192 +                            int offset = ts.offset();
 118.193 +                            if (offset < lexRange.getEnd()) {
 118.194 +                                int indent = GsfUtilities.getLineIndent(doc, lexRange.getStart()) +
 118.195 +                                        IndentUtils.indentLevelSize(doc);
 118.196 +                                StringBuilder sb = new StringBuilder();
 118.197 +                                sb.append(IndentUtils.createIndentString(doc, indent));
 118.198 +                                int rowEnd = Utilities.getRowEnd(doc, offset) + 1;
 118.199 +                                sb.append("\"\"\""); // NOI18N
 118.200 +                                if (multiLine) {
 118.201 +                                    sb.append("\n"); // NOI18N
 118.202 +                                    sb.append(IndentUtils.createIndentString(doc, indent));
 118.203 +                                }
 118.204 +                                editListPosition = rowEnd + sb.length();
 118.205 +                                if (multiLine) {
 118.206 +                                    sb.append("\n"); // NOI18N
 118.207 +                                    sb.append(IndentUtils.createIndentString(doc, indent));
 118.208 +                                }
 118.209 +                                sb.append("\"\"\"\n"); // NOI18N
 118.210 +                                edits.replace(rowEnd, 0, sb.toString(), false, 0);
 118.211 +                            }
 118.212 +                        }
 118.213 +                    }
 118.214 +                }
 118.215 +            }
 118.216 +
 118.217 +            return edits;
 118.218 +        }
 118.219 +
 118.220 +        @Override
 118.221 +        public void implement() throws Exception {
 118.222 +            EditList edits = getEditList();
 118.223 +
 118.224 +            Position pos = edits.createPosition(editListPosition);
 118.225 +            edits.apply();
 118.226 +            if (pos != null && pos.getOffset() != -1) {
 118.227 +                JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
 118.228 +                if (target != null) {
 118.229 +                    target.setCaretPosition(pos.getOffset());
 118.230 +                }
 118.231 +            }
 118.232 +        }
 118.233 +
 118.234 +        @Override
 118.235 +        public boolean isSafe() {
 118.236 +            return true;
 118.237 +        }
 118.238 +
 118.239 +        @Override
 118.240 +        public boolean isInteractive() {
 118.241 +            return false;
 118.242 +        }
 118.243 +    }
 118.244 +}
   119.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   119.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/Deprecations.java	Sun Sep 13 11:47:42 2015 +0200
   119.3 @@ -0,0 +1,184 @@
   119.4 +/*
   119.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   119.6 + *
   119.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   119.8 + *
   119.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  119.10 + * Other names may be trademarks of their respective owners.
  119.11 + *
  119.12 + * The contents of this file are subject to the terms of either the GNU
  119.13 + * General Public License Version 2 only ("GPL") or the Common
  119.14 + * Development and Distribution License("CDDL") (collectively, the
  119.15 + * "License"). You may not use this file except in compliance with the
  119.16 + * License. You can obtain a copy of the License at
  119.17 + * http://www.netbeans.org/cddl-gplv2.html
  119.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  119.19 + * specific language governing permissions and limitations under the
  119.20 + * License.  When distributing the software, include this License Header
  119.21 + * Notice in each file and include the License file at
  119.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  119.23 + * particular file as subject to the "Classpath" exception as provided
  119.24 + * by Oracle in the GPL Version 2 section of the License file that
  119.25 + * accompanied this code. If applicable, add the following below the
  119.26 + * License Header, with the fields enclosed by brackets [] replaced by
  119.27 + * your own identifying information:
  119.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  119.29 + *
  119.30 + * If you wish your version of this file to be governed by only the CDDL
  119.31 + * or only the GPL Version 2, indicate your decision by adding
  119.32 + * "[Contributor] elects to include this software in this distribution
  119.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  119.34 + * single choice of license, a recipient has the option to distribute
  119.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  119.36 + * to extend the choice of license to its licensees as provided above.
  119.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  119.38 + * Version 2 license, then the option applies only if the new code is
  119.39 + * made subject to such option by the copyright holder.
  119.40 + *
  119.41 + * Contributor(s):
  119.42 + *
  119.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  119.44 + */
  119.45 +package org.netbeans.modules.python.hints;
  119.46 +
  119.47 +import java.util.Collections;
  119.48 +import java.util.HashMap;
  119.49 +import java.util.HashSet;
  119.50 +import java.util.List;
  119.51 +import java.util.Map;
  119.52 +import java.util.Set;
  119.53 +import java.util.prefs.Preferences;
  119.54 +import javax.swing.JComponent;
  119.55 +import javax.swing.text.BadLocationException;
  119.56 +import org.netbeans.modules.python.source.PythonAstUtils;
  119.57 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  119.58 +import org.netbeans.editor.BaseDocument;
  119.59 +import org.netbeans.editor.Utilities;
  119.60 +import org.netbeans.modules.csl.api.Hint;
  119.61 +import org.netbeans.modules.csl.api.HintFix;
  119.62 +import org.netbeans.modules.csl.api.HintSeverity;
  119.63 +import org.netbeans.modules.csl.api.OffsetRange;
  119.64 +import org.netbeans.modules.csl.api.RuleContext;
  119.65 +import org.netbeans.modules.python.source.PythonParserResult;
  119.66 +import org.netbeans.modules.python.source.queries.DeprecationQuery;
  119.67 +import org.openide.util.Exceptions;
  119.68 +import org.openide.util.NbBundle;
  119.69 +import org.python.antlr.PythonTree;
  119.70 +import org.python.antlr.ast.Import;
  119.71 +import org.python.antlr.ast.ImportFrom;
  119.72 +import org.python.antlr.ast.alias;
  119.73 +
  119.74 +/**
  119.75 + * Handle deprecaton warnings, for modules listed as obsolete or
  119.76 + * deprecated in PEP4:
  119.77 + *   http://www.python.org/dev/peps/pep-0004/
  119.78 + *
  119.79 + * Todo: Add a hint to enforce this from PEP8:
  119.80 +- Comparisons to singletons like None should always be done with
  119.81 +'is' or 'is not', never the equality operators.
  119.82 + *  In general, see the "Programming Recommendations" list from
  119.83 + *    http://www.python.org/dev/peps/pep-0008/ - there are lots
  119.84 + *    of thins to check from there.  Check the PyLint list as well.
  119.85 + *
  119.86 + *
  119.87 + * @author Tor Norbye
  119.88 + */
  119.89 +public class Deprecations extends PythonAstRule {
  119.90 +
  119.91 +    @Override
  119.92 +    public Set<Class> getKinds() {
  119.93 +        HashSet<Class> kinds = new HashSet<>();
  119.94 +        kinds.add(Import.class);
  119.95 +        kinds.add(ImportFrom.class);
  119.96 +
  119.97 +        return kinds;
  119.98 +    }
  119.99 +
 119.100 +    @Override
 119.101 +    public void run(PythonRuleContext context, List<Hint> result) {
 119.102 +        PythonTree node = context.node;
 119.103 +        if (node instanceof Import) {
 119.104 +            Import imp = (Import)node;
 119.105 +            List<alias> names = imp.getInternalNames();
 119.106 +            if (names != null) {
 119.107 +                for (alias alias : names) {
 119.108 +                    String name = alias.getInternalName();
 119.109 +                    if (DeprecationQuery.isDeprecatedModule(name)) {
 119.110 +                        addDeprecation(name, DeprecationQuery.getDeprecatedModuleDescription(name), context, result);
 119.111 +                    }
 119.112 +                }
 119.113 +            }
 119.114 +        } else {
 119.115 +            assert node instanceof ImportFrom;
 119.116 +            ImportFrom imp = (ImportFrom)node;
 119.117 +            String name = imp.getInternalModule();
 119.118 +            if (DeprecationQuery.isDeprecatedModule(name)) {
 119.119 +                addDeprecation(name, DeprecationQuery.getDeprecatedModuleDescription(name), context, result);
 119.120 +            }
 119.121 +        }
 119.122 +    }
 119.123 +
 119.124 +    private void addDeprecation(String module, String rationale, PythonRuleContext context, List<Hint> result) {
 119.125 +        PythonParserResult info = (PythonParserResult) context.parserResult;
 119.126 +        OffsetRange astOffsets = PythonAstUtils.getNameRange(info, context.node);
 119.127 +        OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
 119.128 +        BaseDocument doc = context.doc;
 119.129 +        try {
 119.130 +            if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
 119.131 +                    (context.caretOffset == -1 ||
 119.132 +                    Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
 119.133 +                List<HintFix> fixList = Collections.emptyList();
 119.134 +                String displayName;
 119.135 +                if (rationale.length() > 0) {
 119.136 +                    displayName = NbBundle.getMessage(Deprecations.class, "DeprecationsMsgDetail", module, rationale);
 119.137 +                } else {
 119.138 +                    displayName = NbBundle.getMessage(Deprecations.class, "DeprecationsMsg", module);
 119.139 +                }
 119.140 +                Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
 119.141 +                result.add(desc);
 119.142 +            }
 119.143 +        } catch (BadLocationException ex) {
 119.144 +            Exceptions.printStackTrace(ex);
 119.145 +        }
 119.146 +    }
 119.147 +
 119.148 +    @Override
 119.149 +    public String getId() {
 119.150 +        return "Deprecations"; // NOI18N
 119.151 +    }
 119.152 +
 119.153 +    @Override
 119.154 +    public String getDisplayName() {
 119.155 +        return NbBundle.getMessage(Deprecations.class, "Deprecations");
 119.156 +    }
 119.157 +
 119.158 +    @Override
 119.159 +    public String getDescription() {
 119.160 +        return NbBundle.getMessage(Deprecations.class, "DeprecationsDesc");
 119.161 +    }
 119.162 +
 119.163 +    @Override
 119.164 +    public boolean getDefaultEnabled() {
 119.165 +        return true;
 119.166 +    }
 119.167 +
 119.168 +    @Override
 119.169 +    public JComponent getCustomizer(Preferences node) {
 119.170 +        return null;
 119.171 +    }
 119.172 +
 119.173 +    @Override
 119.174 +    public boolean appliesTo(RuleContext context) {
 119.175 +        return true;
 119.176 +    }
 119.177 +
 119.178 +    @Override
 119.179 +    public boolean showInTasklist() {
 119.180 +        return true;
 119.181 +    }
 119.182 +
 119.183 +    @Override
 119.184 +    public HintSeverity getDefaultSeverity() {
 119.185 +        return HintSeverity.WARNING;
 119.186 +    }
 119.187 +}
   120.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   120.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/ExtractCode.java	Sun Sep 13 11:47:42 2015 +0200
   120.3 @@ -0,0 +1,759 @@
   120.4 +/*
   120.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   120.6 + *
   120.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   120.8 + *
   120.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  120.10 + * Other names may be trademarks of their respective owners.
  120.11 + *
  120.12 + * The contents of this file are subject to the terms of either the GNU
  120.13 + * General Public License Version 2 only ("GPL") or the Common
  120.14 + * Development and Distribution License("CDDL") (collectively, the
  120.15 + * "License"). You may not use this file except in compliance with the
  120.16 + * License. You can obtain a copy of the License at
  120.17 + * http://www.netbeans.org/cddl-gplv2.html
  120.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  120.19 + * specific language governing permissions and limitations under the
  120.20 + * License.  When distributing the software, include this License Header
  120.21 + * Notice in each file and include the License file at
  120.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  120.23 + * particular file as subject to the "Classpath" exception as provided
  120.24 + * by Oracle in the GPL Version 2 section of the License file that
  120.25 + * accompanied this code. If applicable, add the following below the
  120.26 + * License Header, with the fields enclosed by brackets [] replaced by
  120.27 + * your own identifying information:
  120.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  120.29 + *
  120.30 + * Contributor(s):
  120.31 + *
  120.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  120.33 + */
  120.34 +package org.netbeans.modules.python.hints;
  120.35 +
  120.36 +import java.util.ArrayList;
  120.37 +import java.util.Collections;
  120.38 +import java.util.HashSet;
  120.39 +import java.util.List;
  120.40 +import java.util.Set;
  120.41 +import java.util.prefs.Preferences;
  120.42 +import javax.swing.JComponent;
  120.43 +import javax.swing.text.JTextComponent;
  120.44 +import org.netbeans.editor.BaseDocument;
  120.45 +import org.netbeans.editor.Utilities;
  120.46 +import org.netbeans.modules.csl.api.EditList;
  120.47 +import org.netbeans.modules.csl.api.EditRegions;
  120.48 +import org.netbeans.modules.csl.api.Hint;
  120.49 +import org.netbeans.modules.csl.api.HintFix;
  120.50 +import org.netbeans.modules.csl.api.HintSeverity;
  120.51 +import org.netbeans.modules.csl.api.OffsetRange;
  120.52 +import org.netbeans.modules.csl.api.PreviewableFix;
  120.53 +import org.netbeans.modules.csl.api.RuleContext;
  120.54 +import org.netbeans.modules.csl.spi.GsfUtilities;
  120.55 +import org.netbeans.modules.editor.indent.api.IndentUtils;
  120.56 +import org.netbeans.modules.python.source.AstPath;
  120.57 +import org.netbeans.modules.python.source.PythonAstUtils;
  120.58 +import org.netbeans.modules.python.source.PythonParserResult;
  120.59 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  120.60 +import org.openide.util.Exceptions;
  120.61 +import org.openide.util.NbBundle;
  120.62 +import org.python.antlr.PythonTree;
  120.63 +import org.python.antlr.Visitor;
  120.64 +import org.python.antlr.ast.Assert;
  120.65 +import org.python.antlr.ast.Assign;
  120.66 +import org.python.antlr.ast.AugAssign;
  120.67 +import org.python.antlr.ast.Break;
  120.68 +import org.python.antlr.ast.Call;
  120.69 +import org.python.antlr.ast.ClassDef;
  120.70 +import org.python.antlr.ast.Continue;
  120.71 +import org.python.antlr.ast.Delete;
  120.72 +import org.python.antlr.ast.For;
  120.73 +import org.python.antlr.ast.FunctionDef;
  120.74 +import org.python.antlr.ast.Global;
  120.75 +import org.python.antlr.ast.If;
  120.76 +import org.python.antlr.ast.IfExp;
  120.77 +import org.python.antlr.ast.Import;
  120.78 +import org.python.antlr.ast.ImportFrom;
  120.79 +import org.python.antlr.ast.Module;
  120.80 +import org.python.antlr.ast.Name;
  120.81 +import org.python.antlr.ast.Num;
  120.82 +import org.python.antlr.ast.Pass;
  120.83 +import org.python.antlr.ast.Print;
  120.84 +import org.python.antlr.ast.Raise;
  120.85 +import org.python.antlr.ast.Return;
  120.86 +import org.python.antlr.ast.Str;
  120.87 +import org.python.antlr.ast.Suite;
  120.88 +import org.python.antlr.ast.TryExcept;
  120.89 +import org.python.antlr.ast.TryFinally;
  120.90 +import org.python.antlr.ast.Tuple;
  120.91 +import org.python.antlr.ast.While;
  120.92 +import org.python.antlr.ast.With;
  120.93 +import org.python.antlr.ast.Yield;
  120.94 +
  120.95 +/**
  120.96 + * Offer to introduce method/variable/constant
  120.97 + * @todo There is no need to pass in class or top level constants to code fragments
  120.98 + * @todo Handle flow control: If a code fragment contains an early return, figure out
  120.99 + *   how to pass that information back to the method callsite and do something clever,
 120.100 + *   for example pass back a to-return flag which returns the same value
 120.101 + * @todo Unit tests must check instant rename as well!
 120.102 + *
 120.103 + * @author Tor Norbye
 120.104 + */
 120.105 +public class ExtractCode extends PythonSelectionRule {
 120.106 +    //private static final int NOT_APPLICABLE = 0;
 120.107 +    private static final int INTRODUCE_METHOD = 1;
 120.108 +    private static final int INTRODUCE_VARIABLE = 2;
 120.109 +    private static final int INTRODUCE_CONSTANT = 4;
 120.110 +    private static final int INTRODUCE_FIELD = 8;
 120.111 +    private static final int NON_EXPRESSIONS = INTRODUCE_VARIABLE | INTRODUCE_FIELD | INTRODUCE_CONSTANT;
 120.112 +    private static final int ALL = ~0;
 120.113 +
 120.114 +    @Override
 120.115 +    protected int getApplicability(PythonRuleContext context, PythonTree root, OffsetRange astRange) {
 120.116 +        return ApplicabilityVisitor.getType(root, astRange);
 120.117 +    }
 120.118 +
 120.119 +    @Override
 120.120 +    public void run(PythonRuleContext context, List<Hint> result, OffsetRange range, int applicability) {
 120.121 +        int start = range.getStart();
 120.122 +        int end = range.getEnd();
 120.123 +
 120.124 +// HACK: Only extract method works at this point
 120.125 +        applicability = applicability & INTRODUCE_METHOD;
 120.126 +
 120.127 +
 120.128 +        // Adjust the fix range to be right around the dot so that the light bulb ends up
 120.129 +        // on the same line as the caret and alt-enter works
 120.130 +        JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
 120.131 +        if (target != null) {
 120.132 +            int dot = target.getCaret().getDot();
 120.133 +            range = new OffsetRange(dot, dot);
 120.134 +        }
 120.135 +
 120.136 +        List<HintFix> fixList = new ArrayList<>(3);
 120.137 +        if ((applicability & INTRODUCE_METHOD) != 0) {
 120.138 +            fixList.add(new ExtractCodeFix(context, start, end, INTRODUCE_METHOD));
 120.139 +        }
 120.140 +        if ((applicability & INTRODUCE_VARIABLE) != 0) {
 120.141 +            fixList.add(new ExtractCodeFix(context, start, end, INTRODUCE_VARIABLE));
 120.142 +        }
 120.143 +        if ((applicability & INTRODUCE_CONSTANT) != 0) {
 120.144 +            fixList.add(new ExtractCodeFix(context, start, end, INTRODUCE_CONSTANT));
 120.145 +        }
 120.146 +        if ((applicability & INTRODUCE_FIELD) != 0) {
 120.147 +            fixList.add(new ExtractCodeFix(context, start, end, INTRODUCE_FIELD));
 120.148 +        }
 120.149 +        if (fixList.size() > 0) {
 120.150 +            String displayName = getDisplayName();
 120.151 +            Hint desc = new Hint(this, displayName, context.parserResult.getSnapshot().getSource().getFileObject(),
 120.152 +                    range, fixList, 490);
 120.153 +            result.add(desc);
 120.154 +        }
 120.155 +    }
 120.156 +
 120.157 +    @Override
 120.158 +    public boolean appliesTo(RuleContext context) {
 120.159 +        return true;
 120.160 +    }
 120.161 +
 120.162 +    @Override
 120.163 +    public String getDisplayName() {
 120.164 +        return NbBundle.getMessage(ExtractCode.class, "ExtractCode");
 120.165 +    }
 120.166 +
 120.167 +    @Override
 120.168 +    public String getId() {
 120.169 +        return "ExtractCode"; // NOI18N
 120.170 +    }
 120.171 +
 120.172 +    @Override
 120.173 +    public String getDescription() {
 120.174 +        return "";
 120.175 +    }
 120.176 +
 120.177 +    @Override
 120.178 +    public boolean getDefaultEnabled() {
 120.179 +        return true;
 120.180 +    }
 120.181 +
 120.182 +    @Override
 120.183 +    public JComponent getCustomizer(Preferences node) {
 120.184 +        return null;
 120.185 +    }
 120.186 +
 120.187 +    @Override
 120.188 +    public boolean showInTasklist() {
 120.189 +        return false;
 120.190 +    }
 120.191 +
 120.192 +    @Override
 120.193 +    public HintSeverity getDefaultSeverity() {
 120.194 +        return HintSeverity.CURRENT_LINE_WARNING;
 120.195 +    }
 120.196 +
 120.197 +    private static class ExtractCodeFix implements PreviewableFix {
 120.198 +        private final PythonRuleContext context;
 120.199 +        //private Position callSitePos;
 120.200 +        //private Position extractedPos;
 120.201 +        private int finalCallSiteOffset;
 120.202 +        private int finalExtractedSiteOffset;
 120.203 +        ;
 120.204 +        private final int type;
 120.205 +        private final int start;
 120.206 +        private final int end;
 120.207 +        private String newName;
 120.208 +
 120.209 +        private ExtractCodeFix(PythonRuleContext context,
 120.210 +                int start, int end, int type) {
 120.211 +            this.context = context;
 120.212 +
 120.213 +            OffsetRange range = PythonLexerUtils.narrow(context.doc, new OffsetRange(start, end), false);
 120.214 +            this.start = range.getStart();
 120.215 +            this.end = range.getEnd();
 120.216 +
 120.217 +            this.type = type;
 120.218 +        }
 120.219 +
 120.220 +        @Override
 120.221 +        public String getDescription() {
 120.222 +            switch (type) {
 120.223 +            case INTRODUCE_VARIABLE:
 120.224 +                return NbBundle.getMessage(CreateDocString.class, "IntroduceVariable");
 120.225 +            case INTRODUCE_CONSTANT:
 120.226 +                return NbBundle.getMessage(CreateDocString.class, "IntroduceConstant");
 120.227 +            case INTRODUCE_METHOD:
 120.228 +                return NbBundle.getMessage(CreateDocString.class, "IntroduceMethod");
 120.229 +            case INTRODUCE_FIELD:
 120.230 +                return NbBundle.getMessage(CreateDocString.class, "IntroduceField");
 120.231 +            default:
 120.232 +                throw new IllegalArgumentException();
 120.233 +            }
 120.234 +        }
 120.235 +
 120.236 +        @Override
 120.237 +        public boolean canPreview() {
 120.238 +            return true;
 120.239 +        }
 120.240 +
 120.241 +        @Override
 120.242 +        public EditList getEditList() throws Exception {
 120.243 +            BaseDocument doc = context.doc;
 120.244 +            PythonParserResult info = (PythonParserResult) context.parserResult;
 120.245 +            EditList edits = new EditList(doc);
 120.246 +
 120.247 +            int extractedOffset = doc.getLength();
 120.248 +            int prevFunctionOffset = 0;
 120.249 +            PythonTree root = PythonAstUtils.getRoot(info);
 120.250 +
 120.251 +            OffsetRange narrowed = PythonLexerUtils.narrow(doc, new OffsetRange(start, end), true);
 120.252 +
 120.253 +            int astStart = PythonAstUtils.getAstOffset(info, narrowed != OffsetRange.NONE ? narrowed.getStart() : start);
 120.254 +            int astEnd = PythonAstUtils.getAstOffset(info, narrowed != OffsetRange.NONE ? narrowed.getEnd() : end);
 120.255 +            if (astStart == -1 || astEnd == -1) {
 120.256 +                return edits;
 120.257 +            }
 120.258 +            AstPath startPath = AstPath.get(root, astStart);
 120.259 +            AstPath endPath = AstPath.get(root, astEnd);
 120.260 +            PythonTree localScope = PythonAstUtils.getLocalScope(startPath);
 120.261 +            if (localScope != null) {
 120.262 +                OffsetRange astRange = PythonAstUtils.getRange(localScope);
 120.263 +                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 120.264 +                if (lexRange != OffsetRange.NONE) {
 120.265 +                    extractedOffset = lexRange.getEnd();
 120.266 +
 120.267 +                    // Function end offsets are a bit sloppy so try to deal with that
 120.268 +                    int firstNonWhite = Utilities.getRowFirstNonWhite(doc, Math.min(extractedOffset, doc.getLength()));
 120.269 +                    if (firstNonWhite == -1 || extractedOffset <= firstNonWhite) {
 120.270 +                        extractedOffset = Utilities.getRowStart(doc, extractedOffset);
 120.271 +                    }
 120.272 +
 120.273 +                    prevFunctionOffset = lexRange.getStart();
 120.274 +                    if (extractedOffset > doc.getLength()) {
 120.275 +                        extractedOffset = doc.getLength();
 120.276 +                    }
 120.277 +                }
 120.278 +            }
 120.279 +            int callSiteOffset = start;
 120.280 +            int callSiteReplaceLength = end - start;
 120.281 +
 120.282 +            int indentSize = IndentUtils.indentLevelSize(doc);
 120.283 +            int lineStart = Utilities.getRowStart(doc, prevFunctionOffset);
 120.284 +            int initialIndent = IndentUtils.lineIndent(doc, lineStart);
 120.285 +            String initialIndentStr = IndentUtils.createIndentString(doc, initialIndent);
 120.286 +
 120.287 +            newName = "new_name"; // TODO - localize!
 120.288 +
 120.289 +            // Compute input/output arguments
 120.290 +            PythonTree startNode = startPath.leaf();
 120.291 +            PythonTree endNode = endPath.leaf();
 120.292 +
 120.293 +            InputOutputFinder finder = new InputOutputFinder(startNode, endNode, Collections.<PythonTree>emptyList());
 120.294 +            finder.traverse(localScope);
 120.295 +            List<String> inParams = new ArrayList<>(finder.getInputVars());
 120.296 +            List<String> outParams = new ArrayList<>(finder.getOutputVars());
 120.297 +            Collections.sort(inParams);
 120.298 +            Collections.sort(outParams);
 120.299 +
 120.300 +            ClassDef cls = PythonAstUtils.getClassDef(startPath);
 120.301 +
 120.302 +            // Adjust the insert location in case we are at the top level
 120.303 +            if (cls == null && PythonAstUtils.getFuncDef(startPath) == null) {
 120.304 +                extractedOffset = -1;
 120.305 +                PythonTree top = startPath.topModuleLevel();
 120.306 +                if (top != null) {
 120.307 +                    OffsetRange astRange = PythonAstUtils.getRange(top);
 120.308 +                    extractedOffset = PythonLexerUtils.getLexerOffset(info, astRange.getStart());
 120.309 +                }
 120.310 +
 120.311 +                // We're at the top level - I can't insert the function -after- the current function
 120.312 +                // because that will result in a runtime error
 120.313 +                if (extractedOffset == -1) {
 120.314 +                    extractedOffset = Utilities.getRowStart(doc, Math.min(doc.getLength(), start));
 120.315 +                }
 120.316 +            }
 120.317 +
 120.318 +            String extractedCode = null;
 120.319 +            int extractedSiteDelta = 0;
 120.320 +            if (type == INTRODUCE_METHOD) {
 120.321 +                StringBuilder sb = new StringBuilder();
 120.322 +                if (Utilities.getRowStart(doc, Math.min(extractedOffset, doc.getLength())) < extractedOffset) {
 120.323 +                    sb.append("\n"); // NOI18N
 120.324 +                }
 120.325 +                sb.append("\n"); // NOI18N
 120.326 +                sb.append(initialIndentStr);
 120.327 +                sb.append("def "); // NOI18N
 120.328 +                extractedSiteDelta = sb.length();
 120.329 +                sb.append(newName);
 120.330 +                sb.append("("); // NOI18N
 120.331 +                if (cls != null) {
 120.332 +                    sb.append("self"); // NOI18N
 120.333 +                    if (inParams.size() > 0) {
 120.334 +                        sb.append(", "); // NOI18N
 120.335 +                    }
 120.336 +                }
 120.337 +                boolean first = true;
 120.338 +                for (String param : inParams) {
 120.339 +                    if (first) {
 120.340 +                        first = false;
 120.341 +                    } else {
 120.342 +                        sb.append(", "); // NOI18N
 120.343 +                    }
 120.344 +                    sb.append(param);
 120.345 +                }
 120.346 +                sb.append("):\n"); // NOI18N
 120.347 +
 120.348 +                // Copy in the extracted code
 120.349 +                int firstIndent = IndentUtils.lineIndent(doc, Utilities.getRowStart(doc, start));
 120.350 +                for (int offset = start; offset < end; offset = Utilities.getRowEnd(doc, offset) + 1) {
 120.351 +                    // TODO - handle multiline literal strings correctly!!!
 120.352 +                    if (!(Utilities.isRowEmpty(doc, offset) || Utilities.isRowWhite(doc, offset))) {
 120.353 +                        int lineIndent = IndentUtils.lineIndent(doc, Utilities.getRowStart(doc, offset));
 120.354 +                        int newIndent = (lineIndent - firstIndent) + initialIndent + indentSize;
 120.355 +                        if (newIndent > 0) {
 120.356 +                            sb.append(IndentUtils.createIndentString(doc, newIndent));
 120.357 +                        }
 120.358 +                        int rowFirstNonWhite = Utilities.getRowFirstNonWhite(doc, offset);
 120.359 +                        int rowLastNonWhite = Utilities.getRowLastNonWhite(doc, offset) + 1; // +1: doesn't include last char
 120.360 +                        sb.append(doc.getText(rowFirstNonWhite, rowLastNonWhite - rowFirstNonWhite));
 120.361 +                    }
 120.362 +                    sb.append("\n"); // NOI18N
 120.363 +                }
 120.364 +                sb.append("\n");
 120.365 +
 120.366 +                if (outParams.size() > 0) {
 120.367 +                    sb.append(IndentUtils.createIndentString(doc, initialIndent + indentSize));
 120.368 +                    sb.append("return "); // NOI18N
 120.369 +                    first = true;
 120.370 +                    for (String param : outParams) {
 120.371 +                        if (first) {
 120.372 +                            first = false;
 120.373 +                        } else {
 120.374 +                            // No spaces in the comma list for return tuples
 120.375 +                            sb.append(","); // NOI18N
 120.376 +                        }
 120.377 +                        sb.append(param);
 120.378 +                    }
 120.379 +                    sb.append("\n\n"); // NOI18N
 120.380 +                }
 120.381 +
 120.382 +                // Insert the extracted code at the end
 120.383 +                extractedCode = sb.toString();
 120.384 +            } else {
 120.385 +                assert (type == INTRODUCE_FIELD || type == INTRODUCE_CONSTANT || type == INTRODUCE_VARIABLE);
 120.386 +                throw new RuntimeException("Not yet implemented");
 120.387 +            }
 120.388 +
 120.389 +            // Replace the code at the extract site with just the call
 120.390 +            StringBuilder sb = new StringBuilder();
 120.391 +            if (type == INTRODUCE_METHOD) {
 120.392 +                // Assign to the output variables if any
 120.393 +                if (outParams.size() > 0) {
 120.394 +                    boolean first = true;
 120.395 +                    for (String param : outParams) {
 120.396 +                        if (first) {
 120.397 +                            first = false;
 120.398 +                        } else {
 120.399 +                            // No spaces in the comma list for return tuples
 120.400 +                            sb.append(","); // NOI18N
 120.401 +                        }
 120.402 +                        sb.append(param);
 120.403 +                    }
 120.404 +
 120.405 +                    sb.append(" = ");
 120.406 +                }
 120.407 +            } else {
 120.408 +                assert (type == INTRODUCE_FIELD || type == INTRODUCE_CONSTANT || type == INTRODUCE_VARIABLE);
 120.409 +            }
 120.410 +
 120.411 +            int callSiteDelta = sb.length();
 120.412 +            sb.append(newName);
 120.413 +            if (type == INTRODUCE_METHOD) {
 120.414 +                sb.append('(');
 120.415 +                if (cls != null) {
 120.416 +                    sb.append("self"); // NOI18N
 120.417 +                    if (inParams.size() > 0) {
 120.418 +                        sb.append(", "); // NOI18N
 120.419 +                    }
 120.420 +                }
 120.421 +                boolean first = true;
 120.422 +                for (String param : inParams) {
 120.423 +                    if (first) {
 120.424 +                        first = false;
 120.425 +                    } else {
 120.426 +                        sb.append(", "); // NOI18N
 120.427 +                    }
 120.428 +                    sb.append(param);
 120.429 +                }
 120.430 +                sb.append(')');
 120.431 +            }
 120.432 +            String callSiteCode = sb.toString();
 120.433 +
 120.434 +
 120.435 +            // Apply changes
 120.436 +            if (extractedOffset >= callSiteOffset && extractedOffset <= callSiteOffset + callSiteReplaceLength) {
 120.437 +                if (extractedOffset > callSiteOffset) {
 120.438 +                    // We're trying to insert the extracted code segment after the call - that must mean we're
 120.439 +                    // in something like a function
 120.440 +                    edits.replace(callSiteOffset, callSiteReplaceLength, callSiteCode + extractedCode, false, 0);
 120.441 +
 120.442 +                    // Work around bug in Document.Position
 120.443 +                    //extractedPos = edits.createPosition(callSiteOffset+callSiteCode.length()+extractedSiteDelta, Bias.Forward);
 120.444 +                    //callSitePos = edits.createPosition(callSiteOffset+callSiteDelta, Bias.Forward);
 120.445 +                    finalCallSiteOffset = callSiteOffset + callSiteDelta;
 120.446 +                    finalExtractedSiteOffset = callSiteOffset + callSiteCode.length() + extractedSiteDelta;
 120.447 +                } else {
 120.448 +                    edits.replace(callSiteOffset, callSiteReplaceLength, extractedCode + callSiteCode, false, 0);
 120.449 +
 120.450 +                    // Work around bug in Document.Position
 120.451 +                    //extractedPos = edits.createPosition(callSiteOffset+extractedSiteDelta, Bias.Forward);
 120.452 +                    //callSitePos = edits.createPosition(callSiteOffset+extractedCode.length()+callSiteDelta, Bias.Forward);
 120.453 +                    finalCallSiteOffset = callSiteOffset + extractedCode.length() + callSiteDelta;
 120.454 +                    finalExtractedSiteOffset = callSiteOffset + extractedSiteDelta;
 120.455 +                }
 120.456 +            } else {
 120.457 +                edits.replace(extractedOffset, 0, extractedCode, false, 1);
 120.458 +                edits.replace(callSiteOffset, callSiteReplaceLength, callSiteCode, false, 0);
 120.459 +
 120.460 +                // There's a bug document/editlist position code - the offsets aren't updated on my
 120.461 +                // edits! For now just compute the offsets directly since we know the exact edits applied
 120.462 +                //extractedPos = edits.createPosition(extractedOffset+extractedSiteDelta, Bias.Backward);
 120.463 +                //callSitePos = edits.createPosition(callSiteOffset+callSiteDelta, Bias.Backward);
 120.464 +                if (extractedOffset < callSiteOffset) {
 120.465 +                    finalCallSiteOffset = callSiteOffset + callSiteDelta + extractedCode.length();
 120.466 +                    finalExtractedSiteOffset = extractedOffset + extractedSiteDelta;
 120.467 +                } else {
 120.468 +                    finalCallSiteOffset = callSiteOffset + callSiteDelta;
 120.469 +                    finalExtractedSiteOffset = extractedOffset + extractedSiteDelta + callSiteCode.length() - callSiteReplaceLength;
 120.470 +                }
 120.471 +            }
 120.472 +
 120.473 +            return edits;
 120.474 +        }
 120.475 +
 120.476 +        @Override
 120.477 +        public void implement() throws Exception {
 120.478 +            EditList edits = getEditList();
 120.479 +
 120.480 +            edits.apply();
 120.481 +
 120.482 +            // Refactoring isn't necessary here since local variables and block
 120.483 +            // variables are limited to the local scope, so we can accurately just
 120.484 +            // find their positions using the AST and let the user edit them synchronously.
 120.485 +            Set<OffsetRange> ranges = new HashSet<>();
 120.486 +            int length = newName.length();
 120.487 +            ranges.add(new OffsetRange(finalCallSiteOffset, finalCallSiteOffset + length));
 120.488 +            ranges.add(new OffsetRange(finalExtractedSiteOffset, finalExtractedSiteOffset + length));
 120.489 +
 120.490 +            // Initiate synchronous editing:
 120.491 +            EditRegions.getInstance().edit(context.parserResult.getSnapshot().getSource().getFileObject(), ranges, finalExtractedSiteOffset);
 120.492 +        }
 120.493 +
 120.494 +        @Override
 120.495 +        public boolean isSafe() {
 120.496 +            return true;
 120.497 +        }
 120.498 +
 120.499 +        @Override
 120.500 +        public boolean isInteractive() {
 120.501 +            return false;
 120.502 +        }
 120.503 +    }
 120.504 +
 120.505 +    /** @todo Prune search in traverse, ala AstPath.
 120.506 +     *  @todo Build up start and end AstPaths.
 120.507 +     */
 120.508 +    private static class ApplicabilityVisitor extends Visitor {
 120.509 +        private boolean applies = true;
 120.510 +        private int disabled;
 120.511 +        private int enabled;
 120.512 +        private final int start;
 120.513 +        private final int end;
 120.514 +
 120.515 +        static int getType(PythonTree root, OffsetRange astRange) {
 120.516 +            ApplicabilityVisitor visitor = new ApplicabilityVisitor(astRange);
 120.517 +            try {
 120.518 +                visitor.visit(root);
 120.519 +            } catch (Exception ex) {
 120.520 +                Exceptions.printStackTrace(ex);
 120.521 +                return 0;
 120.522 +            }
 120.523 +            return visitor.getType();
 120.524 +        }
 120.525 +
 120.526 +        ApplicabilityVisitor(OffsetRange astRange) {
 120.527 +            this.start = astRange.getStart();
 120.528 +            this.end = astRange.getEnd();
 120.529 +        }
 120.530 +
 120.531 +        private void enable(PythonTree node, int mask) {
 120.532 +            if (node.getCharStartIndex() >= start && node.getCharStopIndex() <= end) {
 120.533 +                enabled |= mask;
 120.534 +            }
 120.535 +        }
 120.536 +
 120.537 +        private void disable(PythonTree node, int mask) {
 120.538 +            if (node.getCharStartIndex() >= start && node.getCharStopIndex() <= end) {
 120.539 +                disabled |= mask;
 120.540 +            }
 120.541 +        }
 120.542 +
 120.543 +        public int getType() {
 120.544 +            return enabled & ~disabled;
 120.545 +        }
 120.546 +
 120.547 +        private void maybeBail(PythonTree node) {
 120.548 +            int nodeStart = node.getCharStartIndex();
 120.549 +            int nodeEnd = node.getCharStopIndex();
 120.550 +            if (nodeStart >= start && nodeStart < end) {
 120.551 +                applies = false;
 120.552 +                disable(node, ALL);
 120.553 +            }
 120.554 +            if (nodeEnd > start && nodeEnd < end) {
 120.555 +                applies = false;
 120.556 +                disable(node, ALL);
 120.557 +            }
 120.558 +        }
 120.559 +
 120.560 +        @Override
 120.561 +        public void traverse(PythonTree node) throws Exception {
 120.562 +            if (!applies) {
 120.563 +                return;
 120.564 +            }
 120.565 +
 120.566 +            int nodeStart = node.getCharStartIndex();
 120.567 +            int nodeStop = node.getCharStopIndex();
 120.568 +            //if (!(nodeStop < start || nodeStart > end)) {
 120.569 +            if (nodeStop >= start && nodeStart <= end) {
 120.570 +                super.traverse(node);
 120.571 +            }
 120.572 +        }
 120.573 +
 120.574 +        @Override
 120.575 +        public Object visitClassDef(ClassDef node) throws Exception {
 120.576 +            maybeBail(node);
 120.577 +            return super.visitClassDef(node);
 120.578 +        }
 120.579 +
 120.580 +        @Override
 120.581 +        public Object visitFunctionDef(FunctionDef node) throws Exception {
 120.582 +            maybeBail(node);
 120.583 +            return super.visitFunctionDef(node);
 120.584 +        }
 120.585 +
 120.586 +        @Override
 120.587 +        public Object visitImport(Import node) throws Exception {
 120.588 +            disable(node, ALL);
 120.589 +            return super.visitImport(node);
 120.590 +        }
 120.591 +
 120.592 +        @Override
 120.593 +        public Object visitImportFrom(ImportFrom node) throws Exception {
 120.594 +            disable(node, ALL);
 120.595 +            return super.visitImportFrom(node);
 120.596 +        }
 120.597 +
 120.598 +        @Override
 120.599 +        public Object visitAssign(Assign node) throws Exception {
 120.600 +            disable(node, NON_EXPRESSIONS);
 120.601 +            disable(node, NON_EXPRESSIONS);
 120.602 +            return super.visitAssign(node);
 120.603 +        }
 120.604 +
 120.605 +        @Override
 120.606 +        public Object visitCall(Call node) throws Exception {
 120.607 +            enable(node, ALL);
 120.608 +            disable(node, INTRODUCE_CONSTANT);
 120.609 +            return super.visitCall(node);
 120.610 +        }
 120.611 +
 120.612 +        @Override
 120.613 +        public Object visitAugAssign(AugAssign node) throws Exception {
 120.614 +            disable(node, NON_EXPRESSIONS);
 120.615 +            return super.visitAugAssign(node);
 120.616 +        }
 120.617 +
 120.618 +        @Override
 120.619 +        public Object visitBreak(Break node) throws Exception {
 120.620 +            disable(node, NON_EXPRESSIONS);
 120.621 +            return super.visitBreak(node);
 120.622 +        }
 120.623 +
 120.624 +        @Override
 120.625 +        public Object visitContinue(Continue node) throws Exception {
 120.626 +            disable(node, NON_EXPRESSIONS);
 120.627 +            return super.visitContinue(node);
 120.628 +        }
 120.629 +
 120.630 +        @Override
 120.631 +        public Object visitDelete(Delete node) throws Exception {
 120.632 +            disable(node, NON_EXPRESSIONS);
 120.633 +            return super.visitDelete(node);
 120.634 +        }
 120.635 +
 120.636 +        @Override
 120.637 +        public Object visitFor(For node) throws Exception {
 120.638 +            disable(node, NON_EXPRESSIONS);
 120.639 +            return super.visitFor(node);
 120.640 +        }
 120.641 +
 120.642 +        @Override
 120.643 +        public Object visitIf(If node) throws Exception {
 120.644 +            disable(node, NON_EXPRESSIONS);
 120.645 +            return super.visitIf(node);
 120.646 +        }
 120.647 +
 120.648 +        @Override
 120.649 +        public Object visitIfExp(IfExp node) throws Exception {
 120.650 +            disable(node, NON_EXPRESSIONS);
 120.651 +            return super.visitIfExp(node);
 120.652 +        }
 120.653 +
 120.654 +        @Override
 120.655 +        public Object visitPrint(Print node) throws Exception {
 120.656 +            disable(node, NON_EXPRESSIONS);
 120.657 +            return super.visitPrint(node);
 120.658 +        }
 120.659 +
 120.660 +        @Override
 120.661 +        public Object visitYield(Yield node) throws Exception {
 120.662 +            disable(node, NON_EXPRESSIONS);
 120.663 +            return super.visitYield(node);
 120.664 +        }
 120.665 +
 120.666 +        @Override
 120.667 +        public Object visitWith(With node) throws Exception {
 120.668 +            disable(node, NON_EXPRESSIONS);
 120.669 +            return super.visitWith(node);
 120.670 +        }
 120.671 +
 120.672 +        @Override
 120.673 +        public Object visitWhile(While node) throws Exception {
 120.674 +            disable(node, NON_EXPRESSIONS);
 120.675 +            return super.visitWhile(node);
 120.676 +        }
 120.677 +
 120.678 +        @Override
 120.679 +        public Object visitTryFinally(TryFinally node) throws Exception {
 120.680 +            disable(node, NON_EXPRESSIONS);
 120.681 +            return super.visitTryFinally(node);
 120.682 +        }
 120.683 +
 120.684 +        @Override
 120.685 +        public Object visitTryExcept(TryExcept node) throws Exception {
 120.686 +            disable(node, NON_EXPRESSIONS);
 120.687 +            return super.visitTryExcept(node);
 120.688 +        }
 120.689 +
 120.690 +        @Override
 120.691 +        public Object visitSuite(Suite node) throws Exception {
 120.692 +            disable(node, NON_EXPRESSIONS);
 120.693 +            return super.visitSuite(node);
 120.694 +        }
 120.695 +
 120.696 +        @Override
 120.697 +        public Object visitReturn(Return node) throws Exception {
 120.698 +//            disable(node, NON_EXPRESSIONS);
 120.699 +            // TODO - handle flow control!!
 120.700 +            disable(node, ALL);
 120.701 +            return super.visitReturn(node);
 120.702 +        }
 120.703 +
 120.704 +        @Override
 120.705 +        public Object visitModule(Module node) throws Exception {
 120.706 +            if (node.getCharStartIndex() > start && node.getCharStopIndex() < end) {
 120.707 +//                disable(node, NON_EXPRESSIONS);
 120.708 +                disable(node, ALL);
 120.709 +            }
 120.710 +            return super.visitModule(node);
 120.711 +        }
 120.712 +
 120.713 +        @Override
 120.714 +        public Object visitPass(Pass node) throws Exception {
 120.715 +            disable(node, NON_EXPRESSIONS);
 120.716 +            return super.visitPass(node);
 120.717 +        }
 120.718 +
 120.719 +        @Override
 120.720 +        public Object visitRaise(Raise node) throws Exception {
 120.721 +            disable(node, NON_EXPRESSIONS);
 120.722 +            return super.visitRaise(node);
 120.723 +        }
 120.724 +
 120.725 +        @Override
 120.726 +        public Object visitAssert(Assert node) throws Exception {
 120.727 +            disable(node, NON_EXPRESSIONS);
 120.728 +            return super.visitAssert(node);
 120.729 +        }
 120.730 +
 120.731 +        @Override
 120.732 +        public Object visitNum(Num node) throws Exception {
 120.733 +            enable(node, ALL);
 120.734 +            return super.visitNum(node);
 120.735 +        }
 120.736 +
 120.737 +        @Override
 120.738 +        public Object visitName(Name node) throws Exception {
 120.739 +            enable(node, ALL);
 120.740 +            return super.visitName(node);
 120.741 +        }
 120.742 +
 120.743 +        @Override
 120.744 +        public Object visitGlobal(Global node) throws Exception {
 120.745 +            enable(node, ALL);
 120.746 +            disable(node, INTRODUCE_CONSTANT);
 120.747 +            return super.visitGlobal(node);
 120.748 +        }
 120.749 +
 120.750 +        @Override
 120.751 +        public Object visitTuple(Tuple node) throws Exception {
 120.752 +            enable(node, ALL);
 120.753 +            return super.visitTuple(node);
 120.754 +        }
 120.755 +
 120.756 +        @Override
 120.757 +        public Object visitStr(Str node) throws Exception {
 120.758 +            enable(node, ALL);
 120.759 +            return super.visitStr(node);
 120.760 +        }
 120.761 +    }
 120.762 +}
   121.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   121.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/InputOutputFinder.java	Sun Sep 13 11:47:42 2015 +0200
   121.3 @@ -0,0 +1,304 @@
   121.4 +/*
   121.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   121.6 + *
   121.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   121.8 + *
   121.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  121.10 + * Other names may be trademarks of their respective owners.
  121.11 + *
  121.12 + * The contents of this file are subject to the terms of either the GNU
  121.13 + * General Public License Version 2 only ("GPL") or the Common
  121.14 + * Development and Distribution License("CDDL") (collectively, the
  121.15 + * "License"). You may not use this file except in compliance with the
  121.16 + * License. You can obtain a copy of the License at
  121.17 + * http://www.netbeans.org/cddl-gplv2.html
  121.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  121.19 + * specific language governing permissions and limitations under the
  121.20 + * License.  When distributing the software, include this License Header
  121.21 + * Notice in each file and include the License file at
  121.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  121.23 + * particular file as subject to the "Classpath" exception as provided
  121.24 + * by Oracle in the GPL Version 2 section of the License file that
  121.25 + * accompanied this code. If applicable, add the following below the
  121.26 + * License Header, with the fields enclosed by brackets [] replaced by
  121.27 + * your own identifying information:
  121.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  121.29 + * 
  121.30 + * If you wish your version of this file to be governed by only the CDDL
  121.31 + * or only the GPL Version 2, indicate your decision by adding
  121.32 + * "[Contributor] elects to include this software in this distribution
  121.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  121.34 + * single choice of license, a recipient has the option to distribute
  121.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  121.36 + * to extend the choice of license to its licensees as provided above.
  121.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  121.38 + * Version 2 license, then the option applies only if the new code is
  121.39 + * made subject to such option by the copyright holder.
  121.40 + * 
  121.41 + * Contributor(s):
  121.42 + * 
  121.43 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  121.44 + */
  121.45 +package org.netbeans.modules.python.hints;
  121.46 +
  121.47 +import java.util.HashMap;
  121.48 +import java.util.HashSet;
  121.49 +import java.util.List;
  121.50 +import java.util.Map;
  121.51 +import java.util.Set;
  121.52 +import org.netbeans.modules.python.source.PythonAstUtils;
  121.53 +import org.python.antlr.PythonTree;
  121.54 +import org.python.antlr.Visitor;
  121.55 +import org.python.antlr.ast.Assign;
  121.56 +import org.python.antlr.ast.Call;
  121.57 +import org.python.antlr.ast.FunctionDef;
  121.58 +import org.python.antlr.ast.Name;
  121.59 +import org.python.antlr.base.expr;
  121.60 +
  121.61 +/** 
  121.62 + * This visitor computes the set of input and output variables required by
  121.63 + * a code block for extract method.
  121.64 + * In particular, it tracks the local variable assignments inside the method,
  121.65 + * and checks which are used outside of the method (which would make it an
  121.66 + * output variable) and similarly, which variables are used inside the method
  121.67 + * before getting assigned (which would make it an input variable).
  121.68 + * 
  121.69 + * @author Tor Norbye
  121.70 + */
  121.71 +class InputOutputFinder extends Visitor {
  121.72 +    //private enum When { BEFORE, DURING, AFTER };
  121.73 +    private static final int WHEN_BEFORE = 0;
  121.74 +    private static final int WHEN_DURING = 1;
  121.75 +    private static final int WHEN_AFTER = 2;
  121.76 +    private final PythonTree startNode;
  121.77 +    private final PythonTree endNode;
  121.78 +    private final int startPos;
  121.79 +    private final int endPos;
  121.80 +    private final List<PythonTree> applicableBlocks;
  121.81 +    private int when = WHEN_BEFORE;
  121.82 +    private int ifs;
  121.83 +    //private PythonTree currentBlock;
  121.84 +    //private final List<PythonTree> blockStack = new ArrayList<PythonTree>(); // JDK16: Use Deque
  121.85 +    private Map<PythonTree, UsageScope> blockScopes = new HashMap<>();
  121.86 +    private UsageScope methodScope = new UsageScope(null);
  121.87 +    //private UsageScope blockScope;
  121.88 +    private PythonTree parent;
  121.89 +    private boolean isWriting;
  121.90 +
  121.91 +    /** The node ranges are inclusive */
  121.92 +    InputOutputFinder(PythonTree startNode, PythonTree endNode, List<PythonTree> applicableBlocks) {
  121.93 +        this.startNode = startNode;
  121.94 +        this.endNode = endNode;
  121.95 +        this.applicableBlocks = applicableBlocks;
  121.96 +
  121.97 +        startPos = startNode.getCharStartIndex();
  121.98 +        endPos = endNode.getCharStopIndex();
  121.99 +    }
 121.100 +
 121.101 +    public Set<String> getInputVars() {
 121.102 +        UsageScope scope = methodScope;
 121.103 +        for (UsageScope s : blockScopes.values()) {
 121.104 +            if (s.block != null && !applicableBlocks.contains(s.block)) {
 121.105 +                continue;
 121.106 +            }
 121.107 +            scope.merge(s);
 121.108 +        }
 121.109 +
 121.110 +        Set<String> inputs = new HashSet<>(scope.readDuring);
 121.111 +        // But not read before
 121.112 +        inputs.removeAll(scope.writtenBeforeReadDuring);
 121.113 +
 121.114 +        // Also need to pass in any variables I'm modifying that are read after
 121.115 +        Set<String> outputs = new HashSet<>(scope.writtenDuring);
 121.116 +        outputs.retainAll(scope.readAfter);
 121.117 +        Set<String> extraOutputs = new HashSet<>(scope.writtenBefore);
 121.118 +        extraOutputs.retainAll(outputs);
 121.119 +        // unless they are written before read
 121.120 +        extraOutputs.removeAll(scope.writtenBeforeReadDuring);
 121.121 +        inputs.addAll(extraOutputs);
 121.122 +
 121.123 +        return inputs;
 121.124 +    }
 121.125 +
 121.126 +    public Set<String> getOutputVars() {
 121.127 +        UsageScope scope = methodScope;
 121.128 +        for (UsageScope s : blockScopes.values()) {
 121.129 +            if (s.block != null && !applicableBlocks.contains(s.block)) {
 121.130 +                continue;
 121.131 +            }
 121.132 +            scope.merge(s);
 121.133 +        }
 121.134 +
 121.135 +        Set<String> outputs = new HashSet<>(scope.writtenDuring);
 121.136 +        outputs.retainAll(scope.readAfter);
 121.137 +
 121.138 +        return outputs;
 121.139 +    }
 121.140 +
 121.141 +    @Override
 121.142 +    public Object visitFunctionDef(FunctionDef node) throws Exception {
 121.143 +        // Record the parameters
 121.144 +//        assert when == WHEN_BEFORE; // Is this true when I extract a whole method? I can't do that, right?
 121.145 +        boolean x = true;
 121.146 +        assert x;
 121.147 +
 121.148 +        for (String param : PythonAstUtils.getParameters(node)) {
 121.149 +            methodScope.write(param);
 121.150 +        }
 121.151 +
 121.152 +        return super.visitFunctionDef(node);
 121.153 +    }
 121.154 +
 121.155 +    @SuppressWarnings("unchecked")
 121.156 +    @Override
 121.157 +    public Object visitAssign(Assign node) throws Exception {
 121.158 +        // Visit the right hand side of the assignment first, such
 121.159 +        // that with for example
 121.160 +        //    x = x + 1
 121.161 +        // we treat this as a read of x, before a write of x.
 121.162 +        // The Assign.traverse() implementation will do the targets first,
 121.163 +        // so we explicitly do it here in the opposite order instead...
 121.164 +
 121.165 +        if (when == WHEN_BEFORE && node.getCharStartIndex() >= startPos) {
 121.166 +            when = WHEN_DURING;
 121.167 +        }
 121.168 +        int oldWhen = when;
 121.169 +        
 121.170 +        expr nodeValue = node.getInternalValue();
 121.171 +        if (nodeValue != null) {
 121.172 +            nodeValue.accept(this);
 121.173 +        }
 121.174 +        int newWhen = when;
 121.175 +        when = oldWhen;
 121.176 +
 121.177 +        boolean oldWriting = isWriting;
 121.178 +        try {
 121.179 +            isWriting = true;
 121.180 +            List<expr> targets = node.getInternalTargets();
 121.181 +            if (targets != null) {
 121.182 +                for (expr expr : targets) {
 121.183 +                    if (expr != null) {
 121.184 +                        expr.accept(this);
 121.185 +                    }
 121.186 +                }
 121.187 +            }
 121.188 +        } finally {
 121.189 +            isWriting = oldWriting;
 121.190 +        }
 121.191 +
 121.192 +        when = newWhen;
 121.193 +
 121.194 +        return node;
 121.195 +    }
 121.196 +
 121.197 +    @Override
 121.198 +    public Object visitName(Name node) throws Exception {
 121.199 +        if (parent instanceof Call && ((Call)parent).getInternalFunc() == node) { // Name in a call is the call name, not a variable
 121.200 +            return super.visitName(node);
 121.201 +        }
 121.202 +
 121.203 +        methodScope.read(node.getInternalId());
 121.204 +
 121.205 +        return super.visitName(node);
 121.206 +    }
 121.207 +
 121.208 +    @Override
 121.209 +    public void traverse(PythonTree node) throws Exception {
 121.210 +        if (node == startNode) {
 121.211 +            when = WHEN_DURING;
 121.212 +        }
 121.213 +
 121.214 +        PythonTree oldParent = parent;
 121.215 +        parent = node;
 121.216 +        super.traverse(node);
 121.217 +        parent = oldParent;
 121.218 +
 121.219 +        if (node == endNode) {
 121.220 +            when = WHEN_AFTER;
 121.221 +        }
 121.222 +
 121.223 +    }
 121.224 +
 121.225 +    private class UsageScope {
 121.226 +        UsageScope(PythonTree block) {
 121.227 +            this.block = block;
 121.228 +        }
 121.229 +
 121.230 +        private void read(String name) {
 121.231 +            // No need to pass class references or constants in/out
 121.232 +            // TODO: Make this smarter such that what it really does
 121.233 +            // is ignore any variables that aren't defined locally - so
 121.234 +            // global variables for example aren't passed in since they
 121.235 +            // can -also- be accessed from the extracted method.
 121.236 +            if (Character.isUpperCase(name.charAt(0))) {
 121.237 +                return;
 121.238 +            }
 121.239 +
 121.240 +            if (isWriting) {
 121.241 +                // A read in the AST for example on the left hand side of an
 121.242 +                // assignment is really a write
 121.243 +                write(name);
 121.244 +                return;
 121.245 +            }
 121.246 +
 121.247 +            if (when == WHEN_DURING) {
 121.248 +                if (!writtenBeforeReadDuring.contains(name)) {
 121.249 +                    readDuring.add(name);
 121.250 +                }
 121.251 +            } else if (when == WHEN_AFTER) {
 121.252 +                // I don't want a reassignment of the variable before it's been
 121.253 +                // read to count as a usage of the result from the fragment
 121.254 +                if (!writtenAfter.contains(name)) {
 121.255 +                    readAfter.add(name);
 121.256 +                }
 121.257 +            }
 121.258 +        }
 121.259 +
 121.260 +        private void write(String name) {
 121.261 +            // No need to pass class references or constants in/out
 121.262 +            // TODO: Make this smarter such that what it really does
 121.263 +            // is ignore any variables that aren't defined locally - so
 121.264 +            // global variables for example aren't passed in since they
 121.265 +            // can -also- be accessed from the extracted method.
 121.266 +            if (Character.isUpperCase(name.charAt(0))) {
 121.267 +                return;
 121.268 +            }
 121.269 +
 121.270 +            if (when == WHEN_BEFORE) {
 121.271 +                writtenBefore.add(name);
 121.272 +            } else if (when == WHEN_DURING) {
 121.273 +                writtenDuring.add(name);
 121.274 +                if (ifs == 0 && !readDuring.contains(name)) {
 121.275 +                    writtenBeforeReadDuring.add(name);
 121.276 +                }
 121.277 +            } else if (when == WHEN_AFTER) {
 121.278 +                if (ifs == 0 && !readAfter.contains(name)) {
 121.279 +                    writtenAfter.add(name);
 121.280 +                }
 121.281 +            }
 121.282 +        }
 121.283 +
 121.284 +        private void merge(UsageScope other) {
 121.285 +            writtenBefore.addAll(other.writtenBefore);
 121.286 +            readDuring.addAll(other.readDuring);
 121.287 +            writtenDuring.addAll(other.writtenDuring);
 121.288 +            writtenBeforeReadDuring.addAll(other.writtenBeforeReadDuring);
 121.289 +            writtenAfter.addAll(other.writtenAfter);
 121.290 +            readAfter.addAll(other.readAfter);
 121.291 +        }
 121.292 +        /** Block, or null if it's the local method */
 121.293 +        private PythonTree block;
 121.294 +        /** Variables that exist in scope before the code fragment */
 121.295 +        private final Set<String> writtenBefore = new HashSet<>();
 121.296 +        /** Variables that are read during the code fragment */
 121.297 +        private final Set<String> readDuring = new HashSet<>(); // rename readBeforeWrittenDuring
 121.298 +        /** Variables that are written to during the code fragment */
 121.299 +        private final Set<String> writtenDuring = new HashSet<>();
 121.300 +        /** Variables that are written to during the code fragment */
 121.301 +        private final Set<String> writtenBeforeReadDuring = new HashSet<>();
 121.302 +        /** Variables that are written PRIOR TO A READ OF THE SAME VAR after the code fragment */
 121.303 +        private final Set<String> writtenAfter = new HashSet<>(); // rename writtenBeforeReadAfter
 121.304 +        /** Variables that are read (prior to a write) after the code fragment */
 121.305 +        private final Set<String> readAfter = new HashSet<>(); // rename readBeforeWrittenAfter
 121.306 +    }
 121.307 +}
   122.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   122.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/NameRule.java	Sun Sep 13 11:47:42 2015 +0200
   122.3 @@ -0,0 +1,524 @@
   122.4 +/*
   122.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   122.6 + *
   122.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   122.8 + *
   122.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  122.10 + * Other names may be trademarks of their respective owners.
  122.11 + *
  122.12 + * The contents of this file are subject to the terms of either the GNU
  122.13 + * General Public License Version 2 only ("GPL") or the Common
  122.14 + * Development and Distribution License("CDDL") (collectively, the
  122.15 + * "License"). You may not use this file except in compliance with the
  122.16 + * License. You can obtain a copy of the License at
  122.17 + * http://www.netbeans.org/cddl-gplv2.html
  122.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  122.19 + * specific language governing permissions and limitations under the
  122.20 + * License.  When distributing the software, include this License Header
  122.21 + * Notice in each file and include the License file at
  122.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  122.23 + * particular file as subject to the "Classpath" exception as provided
  122.24 + * by Oracle in the GPL Version 2 section of the License file that
  122.25 + * accompanied this code. If applicable, add the following below the
  122.26 + * License Header, with the fields enclosed by brackets [] replaced by
  122.27 + * your own identifying information:
  122.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  122.29 + *
  122.30 + * Contributor(s):
  122.31 + *
  122.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  122.33 + */
  122.34 +package org.netbeans.modules.python.hints;
  122.35 +
  122.36 +import org.netbeans.modules.python.source.NameStyle;
  122.37 +import java.util.ArrayList;
  122.38 +import java.util.Collections;
  122.39 +import java.util.HashSet;
  122.40 +import java.util.List;
  122.41 +import java.util.Set;
  122.42 +import java.util.prefs.Preferences;
  122.43 +import javax.swing.JComponent;
  122.44 +import org.netbeans.editor.BaseDocument;
  122.45 +import org.netbeans.editor.Utilities;
  122.46 +import org.netbeans.modules.csl.api.EditList;
  122.47 +import org.netbeans.modules.csl.api.Hint;
  122.48 +import org.netbeans.modules.csl.api.HintFix;
  122.49 +import org.netbeans.modules.csl.api.HintSeverity;
  122.50 +import org.netbeans.modules.csl.api.OffsetRange;
  122.51 +import org.netbeans.modules.csl.api.PreviewableFix;
  122.52 +import org.netbeans.modules.csl.api.RuleContext;
  122.53 +import org.netbeans.modules.python.source.PythonAstUtils;
  122.54 +import org.netbeans.modules.python.source.PythonParserResult;
  122.55 +import org.netbeans.modules.python.source.PythonUtils;
  122.56 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  122.57 +import org.openide.util.NbBundle;
  122.58 +import org.python.antlr.PythonTree;
  122.59 +import org.python.antlr.ast.ClassDef;
  122.60 +import org.python.antlr.ast.FunctionDef;
  122.61 +import org.python.antlr.ast.Module;
  122.62 +import org.python.antlr.ast.arguments;
  122.63 +
  122.64 +import static org.netbeans.modules.python.source.NameStyle.*;
  122.65 +
  122.66 +/**
  122.67 + * Check names to see if they conform to standard Python conventions.
  122.68 + * These are documented here:
  122.69 + *   http://www.python.org/dev/peps/pep-0008/
  122.70 + * 
  122.71 + * @todo Add fix to rename!
  122.72 + * @todo Implement variable name checking!
  122.73 + * 
  122.74 + * 
  122.75 + * @author Tor Norbye
  122.76 + */
  122.77 +public class NameRule extends PythonAstRule {
  122.78 +    private static final String CLASS_STYLE_NAME = "classStyle"; // NOI18N
  122.79 +    private static final String IGNORED_NAMES = "ignoredNames"; // NOI18N
  122.80 +    private static final String MODULE_STYLE_NAME = "moduleStyle"; // NOI18N
  122.81 +    private static final String FUNCTION_STYLE_NAME = "functionStyle"; // NOI18N
  122.82 +    private static final String SELF_REQUIRED_NAME = "selfRequired"; // NOI18N
  122.83 +    private static final String VARIABLE_STYLE_NAME = "variableStyle"; // NOI18N
  122.84 +    private static NameStyle moduleStyle;
  122.85 +    private static NameStyle functionStyle;
  122.86 +    private static NameStyle classStyle;
  122.87 +    private static NameStyle variableStyle;
  122.88 +    private static String ignoredNames;
  122.89 +    private static boolean selfRequired;
  122.90 +
  122.91 +    public NameRule() {
  122.92 +    }
  122.93 +
  122.94 +    @Override
  122.95 +    public boolean appliesTo(RuleContext context) {
  122.96 +        moduleStyle = null; // Ensure lazy init
  122.97 +
  122.98 +        return true;
  122.99 +    }
 122.100 +
 122.101 +    private static void initializeFromPrefs(PythonRuleContext context, NameRule rule) {
 122.102 +        Preferences pref = context.manager.getPreferences(rule);
 122.103 +        moduleStyle = getModuleNameStyle(pref);
 122.104 +        classStyle = getClassNameStyle(pref);
 122.105 +        functionStyle = getFunctionNameStyle(pref);
 122.106 +        variableStyle = getVariableNameStyle(pref);
 122.107 +        ignoredNames = getIgnoredNames(pref);
 122.108 +        selfRequired = isSelfRequired(pref);
 122.109 +    }
 122.110 +
 122.111 +    @Override
 122.112 +    public Set<Class> getKinds() {
 122.113 +        Set<Class> classes = new HashSet<>();
 122.114 +        classes.add(Module.class);
 122.115 +        classes.add(FunctionDef.class);
 122.116 +        classes.add(ClassDef.class);
 122.117 +
 122.118 +        return classes;
 122.119 +    }
 122.120 +
 122.121 +    @Override
 122.122 +    public void run(PythonRuleContext context, List<Hint> result) {
 122.123 +        if (moduleStyle == null) {
 122.124 +            initializeFromPrefs(context, this);
 122.125 +        }
 122.126 +
 122.127 +        // TODO - check module name!!
 122.128 +
 122.129 +        PythonTree node = context.node;
 122.130 +        if (node instanceof Module) {
 122.131 +            if (moduleStyle != NO_PREFERENCE) {
 122.132 +                String moduleName = PythonUtils.getModuleName(context.parserResult.getSnapshot().getSource().getFileObject());
 122.133 +                if (!moduleStyle.complies(moduleName) && !moduleStyle.complies(moduleName.substring(moduleName.lastIndexOf('.') + 1))) {
 122.134 +                    String typeKey = "Module"; // NOI18N
 122.135 +                    String message = NbBundle.getMessage(NameRule.class, "WrongStyle", moduleName,
 122.136 +                            NbBundle.getMessage(NameRule.class, typeKey),
 122.137 +                            moduleStyle.getDisplayName());
 122.138 +                    List<HintFix> hintFixes = getNameStyleFixes(moduleName, context, moduleStyle, MODULE_STYLE_NAME, typeKey);
 122.139 +                    addError(moduleName, context, message, node, result, hintFixes);
 122.140 +                }
 122.141 +            }
 122.142 +        } else if (node instanceof FunctionDef) {
 122.143 +            FunctionDef def = (FunctionDef)node;
 122.144 +            if (functionStyle != NO_PREFERENCE) {
 122.145 +                if (!functionStyle.complies(def.getInternalName())) {
 122.146 +                    String typeKey = "Function"; // NOI18N
 122.147 +                    String message = NbBundle.getMessage(NameRule.class, "WrongStyle", def.getInternalName(),
 122.148 +                            NbBundle.getMessage(NameRule.class, typeKey),
 122.149 +                            functionStyle.getDisplayName());
 122.150 +                    List<HintFix> hintFixes = getNameStyleFixes(def.getInternalName(), context, functionStyle, FUNCTION_STYLE_NAME, typeKey);
 122.151 +                    addError(def.getInternalName(), context, message, def, result, hintFixes);
 122.152 +                }
 122.153 +            }
 122.154 +
 122.155 +            // Functions should have a first argument of name "self"
 122.156 +            if (selfRequired && !PythonAstUtils.isStaticMethod(def)) {
 122.157 +                arguments args = def.getInternalArgs();
 122.158 +                if (args.getInternalArgs().size() > 0) {
 122.159 +                    String name = PythonAstUtils.getName(args.getInternalArgs().get(0));
 122.160 +                    if (!("self".equals(name) || "cls".equals(name))) { // NOI18N
 122.161 +                        // Make sure it's a class; other methods don't have to
 122.162 +                        if (PythonAstUtils.isClassMethod(context.path, def)) {
 122.163 +                            String message = NbBundle.getMessage(NameRule.class,
 122.164 +                                    // TODO - determine if it should be cls or def
 122.165 +                                    "NameRuleWrongArg", // NOI18N
 122.166 +                                    name);
 122.167 +                            List<HintFix> fixList = new ArrayList<>(2);
 122.168 +                            fixList.add(new SelfParamFix(context, true, def, null));
 122.169 +                            List<String> parameters = PythonAstUtils.getParameters(def);
 122.170 +                            if (parameters.size() > 0) {
 122.171 +                                fixList.add(new SelfParamFix(context, false, def, parameters.get(0)));
 122.172 +                            }
 122.173 +                            addError(null, context, message, args, result, fixList);
 122.174 +                        }
 122.175 +                    }
 122.176 +                } else if (PythonAstUtils.isClassMethod(context.path, def)) {
 122.177 +                    String message = NbBundle.getMessage(NameRule.class,
 122.178 +                            // TODO - determine if it should be cls or def
 122.179 +                            "NameRuleWrongNoArg"); // NOI18N
 122.180 +                    List<HintFix> fixList = Collections.<HintFix>singletonList(new SelfParamFix(context, true, def, null));
 122.181 +                    addError(null, context, message, args, result, fixList);
 122.182 +                }
 122.183 +            }
 122.184 +        } else if (node instanceof ClassDef) {
 122.185 +            if (functionStyle != NO_PREFERENCE) {
 122.186 +                ClassDef def = (ClassDef)node;
 122.187 +                if (!classStyle.complies(def.getInternalName())) {
 122.188 +                    String typeKey = "Class"; // NOI18N
 122.189 +                    String message = NbBundle.getMessage(NameRule.class, "WrongStyle", def.getInternalName(),
 122.190 +                            NbBundle.getMessage(NameRule.class, typeKey),
 122.191 +                            classStyle.getDisplayName());
 122.192 +                    List<HintFix> hintFixes = getNameStyleFixes(def.getInternalName(), context, classStyle, CLASS_STYLE_NAME, typeKey);
 122.193 +                    addError(def.getInternalName(), context, message, def, result, hintFixes);
 122.194 +                }
 122.195 +            }
 122.196 +        }
 122.197 +    }
 122.198 +
 122.199 +    private List<HintFix> getNameStyleFixes(String name, PythonRuleContext context, NameStyle currentStyle, String key, String type) {
 122.200 +        List<HintFix> fixes = new ArrayList<>(5);
 122.201 +
 122.202 +        fixes.add(new IgnoreWordFix(name, this, context));
 122.203 +
 122.204 +        for (NameStyle style : NameStyle.values()) {
 122.205 +            if (style == currentStyle || style == NO_PREFERENCE) {
 122.206 +                continue;
 122.207 +            }
 122.208 +
 122.209 +            if (style.complies(name)) {
 122.210 +                ChangeStyleFix cs = new ChangeStyleFix(this, context, style, key, type);
 122.211 +                fixes.add(cs);
 122.212 +            }
 122.213 +        }
 122.214 +
 122.215 +        // No preference always last
 122.216 +        fixes.add(new ChangeStyleFix(this, context, NO_PREFERENCE, key, type));
 122.217 +
 122.218 +        return fixes;
 122.219 +    }
 122.220 +
 122.221 +    private void addError(String name, PythonRuleContext context, String message, PythonTree node, List<Hint> result, List<HintFix> fixList) {
 122.222 +        if (name != null && ignoredNames.length() > 0) {
 122.223 +            for (String ignoredName : ignoredNames.split(",")) { // NOI18N
 122.224 +                ignoredName = ignoredName.trim();
 122.225 +                if (name.equals(ignoredName)) {
 122.226 +                    return;
 122.227 +                }
 122.228 +            }
 122.229 +        }
 122.230 +        
 122.231 +        PythonParserResult info = (PythonParserResult)context.parserResult;
 122.232 +        OffsetRange range;
 122.233 +        if (node instanceof Module) {
 122.234 +            range = new OffsetRange(0, 0);
 122.235 +        } else {
 122.236 +            
 122.237 +            range = PythonAstUtils.getNameRange(info, node);
 122.238 +        }
 122.239 +        range = PythonLexerUtils.getLexerOffsets(info, range);
 122.240 +        if (range != OffsetRange.NONE) {
 122.241 +            if (fixList == null) {
 122.242 +                fixList = Collections.emptyList();
 122.243 +            }
 122.244 +            Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 1500);
 122.245 +            result.add(desc);
 122.246 +        }
 122.247 +    }
 122.248 +
 122.249 +    @Override
 122.250 +    public String getId() {
 122.251 +        return "NameRule"; // NOI18N
 122.252 +    }
 122.253 +
 122.254 +    @Override
 122.255 +    public String getDisplayName() {
 122.256 +        return NbBundle.getMessage(NameRule.class, "NameRule");
 122.257 +    }
 122.258 +
 122.259 +    @Override
 122.260 +    public String getDescription() {
 122.261 +        return NbBundle.getMessage(NameRule.class, "NameRuleDesc");
 122.262 +    }
 122.263 +
 122.264 +    @Override
 122.265 +    public boolean getDefaultEnabled() {
 122.266 +        return true;
 122.267 +    }
 122.268 +
 122.269 +    @Override
 122.270 +    public boolean showInTasklist() {
 122.271 +        return true;
 122.272 +    }
 122.273 +
 122.274 +    @Override
 122.275 +    public HintSeverity getDefaultSeverity() {
 122.276 +        return HintSeverity.WARNING;
 122.277 +    }
 122.278 +
 122.279 +    @Override
 122.280 +    public JComponent getCustomizer(Preferences node) {
 122.281 +        moduleStyle = null; // Ensure lazy init after this
 122.282 +        return new NameRulePrefs(this, node);
 122.283 +    }
 122.284 +
 122.285 +    static NameStyle getNameStyle(String key, NameStyle deflt, Preferences pref) {
 122.286 +        String value = pref.get(key, deflt.name());
 122.287 +
 122.288 +        return NameStyle.valueOf(value);
 122.289 +    }
 122.290 +
 122.291 +    static NameStyle getModuleNameStyle(Preferences pref) {
 122.292 +        return getNameStyle(MODULE_STYLE_NAME, NameStyle.NO_PREFERENCE, pref);
 122.293 +    }
 122.294 +
 122.295 +    static NameStyle getClassNameStyle(Preferences pref) {
 122.296 +        return getNameStyle(CLASS_STYLE_NAME, NameStyle.CAPITALIZED_WORDS, pref);
 122.297 +    }
 122.298 +
 122.299 +    static NameStyle getVariableNameStyle(Preferences pref) {
 122.300 +        return getNameStyle(VARIABLE_STYLE_NAME, NameStyle.LOWERCASE_WITH_UNDERSCORES, pref);
 122.301 +    }
 122.302 +
 122.303 +    static NameStyle getFunctionNameStyle(Preferences pref) {
 122.304 +        return getNameStyle(FUNCTION_STYLE_NAME, NameStyle.LOWERCASE_WITH_UNDERSCORES, pref);
 122.305 +    }
 122.306 +
 122.307 +    static boolean isSelfRequired(Preferences pref) {
 122.308 +        return pref.getBoolean(SELF_REQUIRED_NAME, true);
 122.309 +    }
 122.310 +
 122.311 +    static String getIgnoredNames(Preferences pref) {
 122.312 +        return pref.get(IGNORED_NAMES, "");
 122.313 +    }
 122.314 +
 122.315 +    void setModuleNameStyle(Preferences pref, NameStyle style) {
 122.316 +        pref.put(MODULE_STYLE_NAME, style.name());
 122.317 +    }
 122.318 +
 122.319 +    void setClassNameStyle(Preferences pref, NameStyle style) {
 122.320 +        pref.put(CLASS_STYLE_NAME, style.name());
 122.321 +    }
 122.322 +
 122.323 +    void setFunctionNameStyle(Preferences pref, NameStyle style) {
 122.324 +        pref.put(FUNCTION_STYLE_NAME, style.name());
 122.325 +    }
 122.326 +
 122.327 +    void setVariableNameStyle(Preferences pref, NameStyle style) {
 122.328 +        pref.put(VARIABLE_STYLE_NAME, style.name());
 122.329 +    }
 122.330 +
 122.331 +    void setIgnoredNames(Preferences pref, String ignoredNames) {
 122.332 +        pref.put(IGNORED_NAMES, ignoredNames);
 122.333 +    }
 122.334 +
 122.335 +    void setSelfRequired(Preferences pref, boolean requireSelf) {
 122.336 +        pref.putBoolean(SELF_REQUIRED_NAME, requireSelf);
 122.337 +    }
 122.338 +
 122.339 +    private static class IgnoreWordFix implements HintFix {
 122.340 +        private String name;
 122.341 +        private NameRule rule;
 122.342 +        private PythonRuleContext context;
 122.343 +
 122.344 +        public IgnoreWordFix(String name, NameRule rule, PythonRuleContext context) {
 122.345 +            this.name = name;
 122.346 +            this.rule = rule;
 122.347 +            this.context = context;
 122.348 +        }
 122.349 +
 122.350 +        @Override
 122.351 +        public String getDescription() {
 122.352 +            return NbBundle.getMessage(NameRule.class, "IgnoreWord", name);
 122.353 +        }
 122.354 +
 122.355 +        @Override
 122.356 +        public void implement() throws Exception {
 122.357 +            Preferences pref = context.manager.getPreferences(rule);
 122.358 +            String ignored = getIgnoredNames(pref);
 122.359 +            if (ignored.length() > 0) {
 122.360 +                ignored = ignored + "," + name; // NOI18N
 122.361 +            } else {
 122.362 +                ignored = name;
 122.363 +            }
 122.364 +            pref.put(IGNORED_NAMES, ignored);
 122.365 +
 122.366 +            context.manager.refreshHints(context);
 122.367 +        }
 122.368 +
 122.369 +        @Override
 122.370 +        public boolean isSafe() {
 122.371 +            return true;
 122.372 +        }
 122.373 +
 122.374 +        @Override
 122.375 +        public boolean isInteractive() {
 122.376 +            return true;
 122.377 +        }
 122.378 +    }
 122.379 +
 122.380 +    private static class ChangeStyleFix implements HintFix {
 122.381 +        private NameRule rule;
 122.382 +        private PythonRuleContext context;
 122.383 +        private NameStyle style;
 122.384 +        private String key;
 122.385 +        private String typeKey;
 122.386 +
 122.387 +        public ChangeStyleFix(NameRule rule, PythonRuleContext context, NameStyle style, String key, String type) {
 122.388 +            this.rule = rule;
 122.389 +            this.context = context;
 122.390 +            this.style = style;
 122.391 +            this.key = key;
 122.392 +            this.typeKey = type;
 122.393 +        }
 122.394 +
 122.395 +        @Override
 122.396 +        public String getDescription() {
 122.397 +            if (style == NO_PREFERENCE) {
 122.398 +                return NbBundle.getMessage(NameRule.class, "ChangeNoStyle", NbBundle.getMessage(NameRule.class, typeKey));
 122.399 +            } else {
 122.400 +                return NbBundle.getMessage(NameRule.class, "ChangeStyle", NbBundle.getMessage(NameRule.class, typeKey), style.getDisplayName());
 122.401 +            }
 122.402 +        }
 122.403 +
 122.404 +        @Override
 122.405 +        public void implement() throws Exception {
 122.406 +            Preferences pref = context.manager.getPreferences(rule);
 122.407 +            pref.put(key, style.name());
 122.408 +
 122.409 +            context.manager.refreshHints(context);
 122.410 +        }
 122.411 +
 122.412 +        @Override
 122.413 +        public boolean isSafe() {
 122.414 +            return true;
 122.415 +        }
 122.416 +
 122.417 +        @Override
 122.418 +        public boolean isInteractive() {
 122.419 +            return true;
 122.420 +        }
 122.421 +    }
 122.422 +
 122.423 +    /**
 122.424 +     * Fix to insert self argument or rename first argument to self
 122.425 +     */
 122.426 +    private static class SelfParamFix implements PreviewableFix {
 122.427 +        private final PythonRuleContext context;
 122.428 +        private final FunctionDef func;
 122.429 +        private final boolean insert;
 122.430 +        private final String first;
 122.431 +
 122.432 +        private SelfParamFix(PythonRuleContext context, boolean insert, FunctionDef func, String first) {
 122.433 +            this.context = context;
 122.434 +            this.insert = insert;
 122.435 +            this.func = func;
 122.436 +            this.first = first;
 122.437 +
 122.438 +            assert insert || first != null;
 122.439 +        }
 122.440 +
 122.441 +        @Override
 122.442 +        public String getDescription() {
 122.443 +            if (insert) {
 122.444 +                return NbBundle.getMessage(CreateDocString.class, "InsertSelf");
 122.445 +            } else {
 122.446 +                return NbBundle.getMessage(CreateDocString.class, "RenameSelf", first);
 122.447 +            }
 122.448 +        }
 122.449 +
 122.450 +        @Override
 122.451 +        public boolean canPreview() {
 122.452 +            return true;
 122.453 +        }
 122.454 +
 122.455 +        @Override
 122.456 +        public EditList getEditList() throws Exception {
 122.457 +            return getEditList(true);
 122.458 +        }
 122.459 +
 122.460 +        private EditList getEditList(boolean previewOnly) throws Exception {
 122.461 +            BaseDocument doc = context.doc;
 122.462 +            EditList edits = new EditList(doc);
 122.463 +
 122.464 +            OffsetRange astRange = PythonAstUtils.getNameRange((PythonParserResult) context.parserResult, func);
 122.465 +            OffsetRange lexRange = PythonLexerUtils.getLexerOffsets((PythonParserResult) context.parserResult, astRange);
 122.466 +            if (lexRange == OffsetRange.NONE) {
 122.467 +                return edits;
 122.468 +            }
 122.469 +            int paramStart = lexRange.getEnd();
 122.470 +            if (insert) {
 122.471 +                String missing;
 122.472 +                int lineEnd = Utilities.getRowEnd(doc, paramStart);
 122.473 +                int offset = paramStart;
 122.474 +                if (lineEnd > paramStart) {
 122.475 +                    String line = doc.getText(paramStart, lineEnd - paramStart);
 122.476 +                    int paren = line.indexOf('(');
 122.477 +                    int colon = line.indexOf(':');
 122.478 +                    if (paren != -1) {
 122.479 +                        offset = paramStart + paren + 1;
 122.480 +                        missing = "self"; // NOI18N
 122.481 +                        List<String> parameters = PythonAstUtils.getParameters(func);
 122.482 +                        if (parameters.size() > 0) {
 122.483 +                            missing = "self, "; // NOI18N
 122.484 +                        } else {
 122.485 +                            missing = "self"; // NOI18N
 122.486 +                        }
 122.487 +                    } else if (colon != -1) {
 122.488 +                        offset = paramStart + colon;
 122.489 +                        missing = "(self)"; // NOI18N
 122.490 +                    } else {
 122.491 +                        return edits;
 122.492 +                    }
 122.493 +                } else {
 122.494 +                    missing = "(self)"; // NOI18N
 122.495 +                }
 122.496 +                edits.replace(offset, 0, missing, false, 0);
 122.497 +            } else {
 122.498 +                String text = doc.getText(paramStart, doc.getLength() - paramStart);
 122.499 +                int offset = text.indexOf(first);
 122.500 +                if (offset != -1) {
 122.501 +                    offset += paramStart;
 122.502 +                    edits.replace(offset, first.length(), "self", false, 0); // NOI18N
 122.503 +                }
 122.504 +            }
 122.505 +
 122.506 +
 122.507 +            return edits;
 122.508 +        }
 122.509 +
 122.510 +        @Override
 122.511 +        public void implement() throws Exception {
 122.512 +            EditList edits = getEditList(true);
 122.513 +
 122.514 +            edits.apply();
 122.515 +        }
 122.516 +
 122.517 +        @Override
 122.518 +        public boolean isSafe() {
 122.519 +            return true;
 122.520 +        }
 122.521 +
 122.522 +        @Override
 122.523 +        public boolean isInteractive() {
 122.524 +            return false;
 122.525 +        }
 122.526 +    }
 122.527 +}
   123.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   123.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/NameRulePrefs.form	Sun Sep 13 11:47:42 2015 +0200
   123.3 @@ -0,0 +1,182 @@
   123.4 +<?xml version="1.0" encoding="UTF-8" ?>
   123.5 +
   123.6 +<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   123.7 +  <AuxValues>
   123.8 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   123.9 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  123.10 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  123.11 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
  123.12 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  123.13 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
  123.14 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
  123.15 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  123.16 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  123.17 +  </AuxValues>
  123.18 +
  123.19 +  <Layout>
  123.20 +    <DimensionLayout dim="0">
  123.21 +      <Group type="103" groupAlignment="0" attributes="0">
  123.22 +          <Group type="102" attributes="0">
  123.23 +              <Group type="103" groupAlignment="0" attributes="0">
  123.24 +                  <Group type="102" alignment="0" attributes="0">
  123.25 +                      <Group type="103" groupAlignment="0" attributes="0">
  123.26 +                          <Component id="moduleLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  123.27 +                          <Component id="classLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  123.28 +                          <Component id="functionLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  123.29 +                          <Component id="variableLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  123.30 +                      </Group>
  123.31 +                      <EmptySpace max="-2" attributes="0"/>
  123.32 +                      <Group type="103" groupAlignment="1" max="-2" attributes="0">
  123.33 +                          <Component id="variableCombo" alignment="0" max="32767" attributes="1"/>
  123.34 +                          <Component id="classCombo" alignment="0" max="32767" attributes="1"/>
  123.35 +                          <Component id="moduleCombo" alignment="0" pref="234" max="32767" attributes="1"/>
  123.36 +                          <Component id="functionCombo" alignment="1" max="32767" attributes="1"/>
  123.37 +                      </Group>
  123.38 +                  </Group>
  123.39 +                  <Component id="parameterLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  123.40 +                  <Component id="selfCb" alignment="0" min="-2" max="-2" attributes="0"/>
  123.41 +                  <Group type="102" alignment="0" attributes="0">
  123.42 +                      <Component id="ignoreLabel" min="-2" max="-2" attributes="0"/>
  123.43 +                      <EmptySpace max="-2" attributes="0"/>
  123.44 +                      <Component id="ignoredText" max="32767" attributes="0"/>
  123.45 +                  </Group>
  123.46 +              </Group>
  123.47 +              <EmptySpace max="-2" attributes="0"/>
  123.48 +          </Group>
  123.49 +      </Group>
  123.50 +    </DimensionLayout>
  123.51 +    <DimensionLayout dim="1">
  123.52 +      <Group type="103" groupAlignment="0" attributes="0">
  123.53 +          <Group type="102" alignment="0" attributes="0">
  123.54 +              <Group type="103" groupAlignment="3" attributes="0">
  123.55 +                  <Component id="moduleLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  123.56 +                  <Component id="moduleCombo" alignment="3" min="-2" max="-2" attributes="0"/>
  123.57 +              </Group>
  123.58 +              <EmptySpace max="-2" attributes="0"/>
  123.59 +              <Group type="103" groupAlignment="3" attributes="0">
  123.60 +                  <Component id="classLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  123.61 +                  <Component id="classCombo" alignment="3" min="-2" max="-2" attributes="0"/>
  123.62 +              </Group>
  123.63 +              <EmptySpace max="-2" attributes="0"/>
  123.64 +              <Group type="103" groupAlignment="3" attributes="0">
  123.65 +                  <Component id="functionLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  123.66 +                  <Component id="functionCombo" alignment="3" min="-2" max="-2" attributes="0"/>
  123.67 +              </Group>
  123.68 +              <EmptySpace max="-2" attributes="0"/>
  123.69 +              <Group type="103" groupAlignment="3" attributes="0">
  123.70 +                  <Component id="variableLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  123.71 +                  <Component id="variableCombo" alignment="3" min="-2" max="-2" attributes="0"/>
  123.72 +              </Group>
  123.73 +              <EmptySpace type="separate" max="-2" attributes="0"/>
  123.74 +              <Component id="parameterLabel" min="-2" max="-2" attributes="0"/>
  123.75 +              <EmptySpace max="-2" attributes="0"/>
  123.76 +              <Component id="selfCb" min="-2" max="-2" attributes="0"/>
  123.77 +              <EmptySpace type="separate" max="-2" attributes="0"/>
  123.78 +              <Group type="103" groupAlignment="3" attributes="0">
  123.79 +                  <Component id="ignoreLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  123.80 +                  <Component id="ignoredText" alignment="3" min="-2" max="-2" attributes="0"/>
  123.81 +              </Group>
  123.82 +              <EmptySpace max="32767" attributes="0"/>
  123.83 +          </Group>
  123.84 +      </Group>
  123.85 +    </DimensionLayout>
  123.86 +  </Layout>
  123.87 +  <SubComponents>
  123.88 +    <Component class="javax.swing.JLabel" name="classLabel">
  123.89 +      <Properties>
  123.90 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  123.91 +          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="NameRulePrefs.classLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  123.92 +        </Property>
  123.93 +      </Properties>
  123.94 +    </Component>
  123.95 +    <Component class="javax.swing.JLabel" name="functionLabel">
  123.96 +      <Properties>
  123.97 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  123.98 +          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="NameRulePrefs.functionLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  123.99 +        </Property>
 123.100 +      </Properties>
 123.101 +    </Component>
 123.102 +    <Component class="javax.swing.JLabel" name="moduleLabel">
 123.103 +      <Properties>
 123.104 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 123.105 +          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="NameRulePrefs.moduleLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 123.106 +        </Property>
 123.107 +      </Properties>
 123.108 +    </Component>
 123.109 +    <Component class="javax.swing.JLabel" name="parameterLabel">
 123.110 +      <Properties>
 123.111 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 123.112 +          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="NameRulePrefs.parameterLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 123.113 +        </Property>
 123.114 +      </Properties>
 123.115 +    </Component>
 123.116 +    <Component class="javax.swing.JCheckBox" name="selfCb">
 123.117 +      <Properties>
 123.118 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 123.119 +          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="NameRulePrefs.selfCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 123.120 +        </Property>
 123.121 +      </Properties>
 123.122 +      <Events>
 123.123 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
 123.124 +      </Events>
 123.125 +    </Component>
 123.126 +    <Component class="javax.swing.JComboBox" name="moduleCombo">
 123.127 +      <Properties>
 123.128 +        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
 123.129 +          <Connection code="getNameStyleModel()" type="code"/>
 123.130 +        </Property>
 123.131 +      </Properties>
 123.132 +      <Events>
 123.133 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
 123.134 +      </Events>
 123.135 +    </Component>
 123.136 +    <Component class="javax.swing.JComboBox" name="classCombo">
 123.137 +      <Properties>
 123.138 +        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
 123.139 +          <Connection code="getNameStyleModel()" type="code"/>
 123.140 +        </Property>
 123.141 +      </Properties>
 123.142 +      <Events>
 123.143 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
 123.144 +      </Events>
 123.145 +    </Component>
 123.146 +    <Component class="javax.swing.JComboBox" name="functionCombo">
 123.147 +      <Properties>
 123.148 +        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
 123.149 +          <Connection code="getNameStyleModel()" type="code"/>
 123.150 +        </Property>
 123.151 +      </Properties>
 123.152 +      <Events>
 123.153 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
 123.154 +      </Events>
 123.155 +    </Component>
 123.156 +    <Component class="javax.swing.JLabel" name="variableLabel">
 123.157 +      <Properties>
 123.158 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 123.159 +          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="NameRulePrefs.variableLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 123.160 +        </Property>
 123.161 +        <Property name="enabled" type="boolean" value="false"/>
 123.162 +      </Properties>
 123.163 +    </Component>
 123.164 +    <Component class="javax.swing.JComboBox" name="variableCombo">
 123.165 +      <Properties>
 123.166 +        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
 123.167 +          <Connection code="getNameStyleModel()" type="code"/>
 123.168 +        </Property>
 123.169 +        <Property name="enabled" type="boolean" value="false"/>
 123.170 +      </Properties>
 123.171 +      <Events>
 123.172 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
 123.173 +      </Events>
 123.174 +    </Component>
 123.175 +    <Component class="javax.swing.JLabel" name="ignoreLabel">
 123.176 +      <Properties>
 123.177 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 123.178 +          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="NameRulePrefs.ignoreLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 123.179 +        </Property>
 123.180 +      </Properties>
 123.181 +    </Component>
 123.182 +    <Component class="javax.swing.JTextField" name="ignoredText">
 123.183 +    </Component>
 123.184 +  </SubComponents>
 123.185 +</Form>
   124.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   124.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/NameRulePrefs.java	Sun Sep 13 11:47:42 2015 +0200
   124.3 @@ -0,0 +1,292 @@
   124.4 +/*
   124.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   124.6 + *
   124.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   124.8 + *
   124.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  124.10 + * Other names may be trademarks of their respective owners.
  124.11 + *
  124.12 + * The contents of this file are subject to the terms of either the GNU
  124.13 + * General Public License Version 2 only ("GPL") or the Common
  124.14 + * Development and Distribution License("CDDL") (collectively, the
  124.15 + * "License"). You may not use this file except in compliance with the
  124.16 + * License. You can obtain a copy of the License at
  124.17 + * http://www.netbeans.org/cddl-gplv2.html
  124.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  124.19 + * specific language governing permissions and limitations under the
  124.20 + * License.  When distributing the software, include this License Header
  124.21 + * Notice in each file and include the License file at
  124.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  124.23 + * particular file as subject to the "Classpath" exception as provided
  124.24 + * by Oracle in the GPL Version 2 section of the License file that
  124.25 + * accompanied this code. If applicable, add the following below the
  124.26 + * License Header, with the fields enclosed by brackets [] replaced by
  124.27 + * your own identifying information:
  124.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  124.29 + *
  124.30 + * If you wish your version of this file to be governed by only the CDDL
  124.31 + * or only the GPL Version 2, indicate your decision by adding
  124.32 + * "[Contributor] elects to include this software in this distribution
  124.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  124.34 + * single choice of license, a recipient has the option to distribute
  124.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  124.36 + * to extend the choice of license to its licensees as provided above.
  124.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  124.38 + * Version 2 license, then the option applies only if the new code is
  124.39 + * made subject to such option by the copyright holder.
  124.40 + *
  124.41 + * Contributor(s):
  124.42 + *
  124.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  124.44 + */
  124.45 +package org.netbeans.modules.python.hints;
  124.46 +
  124.47 +import org.netbeans.modules.python.source.NameStyle;
  124.48 +import java.awt.Component;
  124.49 +import java.util.prefs.Preferences;
  124.50 +import javax.swing.ComboBoxModel;
  124.51 +import javax.swing.DefaultComboBoxModel;
  124.52 +import javax.swing.JLabel;
  124.53 +import javax.swing.JList;
  124.54 +import javax.swing.ListCellRenderer;
  124.55 +
  124.56 +/**
  124.57 + *
  124.58 + * @author Tor Norbye
  124.59 + */
  124.60 +public class NameRulePrefs extends javax.swing.JPanel {
  124.61 +    private NameRule rule;
  124.62 +    private Preferences prefs;
  124.63 +
  124.64 +    /** Creates new form NameRulePrefs */
  124.65 +    public NameRulePrefs(NameRule rule, Preferences prefs) {
  124.66 +        this.rule = rule;
  124.67 +        this.prefs = prefs;
  124.68 +
  124.69 +        initComponents();
  124.70 +
  124.71 +        ListCellRenderer renderer = new NameStyleRenderer();
  124.72 +        moduleCombo.setRenderer(renderer);
  124.73 +        functionCombo.setRenderer(renderer);
  124.74 +        classCombo.setRenderer(renderer);
  124.75 +        variableCombo.setRenderer(renderer);
  124.76 +
  124.77 +        moduleCombo.setSelectedItem(NameRule.getModuleNameStyle(prefs));
  124.78 +        functionCombo.setSelectedItem(NameRule.getFunctionNameStyle(prefs));
  124.79 +        classCombo.setSelectedItem(NameRule.getClassNameStyle(prefs));
  124.80 +        variableCombo.setSelectedItem(NameRule.getVariableNameStyle(prefs));
  124.81 +
  124.82 +        selfCb.setSelected(NameRule.isSelfRequired(prefs));
  124.83 +        ignoredText.setText(NameRule.getIgnoredNames(prefs));
  124.84 +    }
  124.85 +
  124.86 +    private ComboBoxModel getNameStyleModel() {
  124.87 +        return new DefaultComboBoxModel(NameStyle.values());
  124.88 +    }
  124.89 +
  124.90 +    private static class NameStyleRenderer extends JLabel implements ListCellRenderer/*, UIResource*/ {
  124.91 +        public NameStyleRenderer() {
  124.92 +            setOpaque(true);
  124.93 +        }
  124.94 +
  124.95 +        @Override
  124.96 +        public Component getListCellRendererComponent(JList list, Object value,
  124.97 +                int index, boolean isSelected, boolean cellHasFocus) {
  124.98 +            // #93658: GTK needs name to render cell renderer "natively"
  124.99 +            setName("ComboBox.listRenderer"); // NOI18N
 124.100 +
 124.101 +            if (isSelected) {
 124.102 +                setBackground(list.getSelectionBackground());
 124.103 +                setForeground(list.getSelectionForeground());
 124.104 +            } else {
 124.105 +                setBackground(list.getBackground());
 124.106 +                setForeground(list.getForeground());
 124.107 +            }
 124.108 +
 124.109 +            if (value instanceof NameStyle) {
 124.110 +                setText(((NameStyle)value).getDisplayName());
 124.111 +            }
 124.112 +
 124.113 +            return this;
 124.114 +        }
 124.115 +
 124.116 +        // #93658: GTK needs name to render cell renderer "natively"
 124.117 +        public 
 124.118 +        @Override
 124.119 +        String getName() {
 124.120 +            String name = super.getName();
 124.121 +            return name == null ? "ComboBox.renderer" : name;  // NOI18N
 124.122 +        }
 124.123 +    }
 124.124 +
 124.125 +    /** This method is called from within the constructor to
 124.126 +     * initialize the form.
 124.127 +     * WARNING: Do NOT modify this code. The content of this method is
 124.128 +     * always regenerated by the Form Editor.
 124.129 +     */
 124.130 +    @SuppressWarnings("unchecked")
 124.131 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
 124.132 +    private void initComponents() {
 124.133 +
 124.134 +        classLabel = new javax.swing.JLabel();
 124.135 +        functionLabel = new javax.swing.JLabel();
 124.136 +        moduleLabel = new javax.swing.JLabel();
 124.137 +        parameterLabel = new javax.swing.JLabel();
 124.138 +        selfCb = new javax.swing.JCheckBox();
 124.139 +        moduleCombo = new javax.swing.JComboBox();
 124.140 +        classCombo = new javax.swing.JComboBox();
 124.141 +        functionCombo = new javax.swing.JComboBox();
 124.142 +        variableLabel = new javax.swing.JLabel();
 124.143 +        variableCombo = new javax.swing.JComboBox();
 124.144 +        ignoreLabel = new javax.swing.JLabel();
 124.145 +        ignoredText = new javax.swing.JTextField();
 124.146 +
 124.147 +        classLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.classLabel.text")); // NOI18N
 124.148 +
 124.149 +        functionLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.functionLabel.text")); // NOI18N
 124.150 +
 124.151 +        moduleLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.moduleLabel.text")); // NOI18N
 124.152 +
 124.153 +        parameterLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.parameterLabel.text")); // NOI18N
 124.154 +
 124.155 +        selfCb.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.selfCb.text")); // NOI18N
 124.156 +        selfCb.addActionListener(new java.awt.event.ActionListener() {
 124.157 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
 124.158 +                changed(evt);
 124.159 +            }
 124.160 +        });
 124.161 +
 124.162 +        moduleCombo.setModel(getNameStyleModel());
 124.163 +        moduleCombo.addActionListener(new java.awt.event.ActionListener() {
 124.164 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
 124.165 +                changed(evt);
 124.166 +            }
 124.167 +        });
 124.168 +
 124.169 +        classCombo.setModel(getNameStyleModel());
 124.170 +        classCombo.addActionListener(new java.awt.event.ActionListener() {
 124.171 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
 124.172 +                changed(evt);
 124.173 +            }
 124.174 +        });
 124.175 +
 124.176 +        functionCombo.setModel(getNameStyleModel());
 124.177 +        functionCombo.addActionListener(new java.awt.event.ActionListener() {
 124.178 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
 124.179 +                changed(evt);
 124.180 +            }
 124.181 +        });
 124.182 +
 124.183 +        variableLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.variableLabel.text")); // NOI18N
 124.184 +        variableLabel.setEnabled(false);
 124.185 +
 124.186 +        variableCombo.setModel(getNameStyleModel());
 124.187 +        variableCombo.setEnabled(false);
 124.188 +        variableCombo.addActionListener(new java.awt.event.ActionListener() {
 124.189 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
 124.190 +                changed(evt);
 124.191 +            }
 124.192 +        });
 124.193 +
 124.194 +        ignoreLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.ignoreLabel.text")); // NOI18N
 124.195 +
 124.196 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
 124.197 +        this.setLayout(layout);
 124.198 +        layout.setHorizontalGroup(
 124.199 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 124.200 +            .addGroup(layout.createSequentialGroup()
 124.201 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 124.202 +                    .addGroup(layout.createSequentialGroup()
 124.203 +                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 124.204 +                            .addComponent(moduleLabel)
 124.205 +                            .addComponent(classLabel)
 124.206 +                            .addComponent(functionLabel)
 124.207 +                            .addComponent(variableLabel))
 124.208 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 124.209 +                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
 124.210 +                            .addComponent(variableCombo, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 124.211 +                            .addComponent(classCombo, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 124.212 +                            .addComponent(moduleCombo, javax.swing.GroupLayout.Alignment.LEADING, 0, 234, Short.MAX_VALUE)
 124.213 +                            .addComponent(functionCombo, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
 124.214 +                    .addComponent(parameterLabel)
 124.215 +                    .addComponent(selfCb)
 124.216 +                    .addGroup(layout.createSequentialGroup()
 124.217 +                        .addComponent(ignoreLabel)
 124.218 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 124.219 +                        .addComponent(ignoredText)))
 124.220 +                .addContainerGap())
 124.221 +        );
 124.222 +        layout.setVerticalGroup(
 124.223 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 124.224 +            .addGroup(layout.createSequentialGroup()
 124.225 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 124.226 +                    .addComponent(moduleLabel)
 124.227 +                    .addComponent(moduleCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 124.228 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 124.229 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 124.230 +                    .addComponent(classLabel)
 124.231 +                    .addComponent(classCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 124.232 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 124.233 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 124.234 +                    .addComponent(functionLabel)
 124.235 +                    .addComponent(functionCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 124.236 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 124.237 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 124.238 +                    .addComponent(variableLabel)
 124.239 +                    .addComponent(variableCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 124.240 +                .addGap(18, 18, 18)
 124.241 +                .addComponent(parameterLabel)
 124.242 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 124.243 +                .addComponent(selfCb)
 124.244 +                .addGap(18, 18, 18)
 124.245 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 124.246 +                    .addComponent(ignoreLabel)
 124.247 +                    .addComponent(ignoredText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 124.248 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 124.249 +        );
 124.250 +    }// </editor-fold>//GEN-END:initComponents
 124.251 +
 124.252 +    private void changed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_changed
 124.253 +        Object source = evt.getSource();
 124.254 +
 124.255 +        if (source == moduleCombo) {
 124.256 +            NameStyle style = (NameStyle)moduleCombo.getSelectedItem();
 124.257 +            if (style != null) {
 124.258 +                rule.setModuleNameStyle(prefs, style);
 124.259 +            }
 124.260 +        } else if (source == functionCombo) {
 124.261 +            NameStyle style = (NameStyle)functionCombo.getSelectedItem();
 124.262 +            if (style != null) {
 124.263 +                rule.setFunctionNameStyle(prefs, style);
 124.264 +            }
 124.265 +        } else if (source == classCombo) {
 124.266 +            NameStyle style = (NameStyle)classCombo.getSelectedItem();
 124.267 +            if (style != null) {
 124.268 +                rule.setClassNameStyle(prefs, style);
 124.269 +            }
 124.270 +        } else if (source == variableCombo) {
 124.271 +            NameStyle style = (NameStyle)variableCombo.getSelectedItem();
 124.272 +            if (style != null) {
 124.273 +                rule.setVariableNameStyle(prefs, style);
 124.274 +            }
 124.275 +        } else if (source == ignoredText) {
 124.276 +            rule.setIgnoredNames(prefs, ignoredText.getText().trim());
 124.277 +        } else if (source == selfCb) {
 124.278 +            rule.setSelfRequired(prefs, selfCb.isSelected());
 124.279 +        }
 124.280 +    }//GEN-LAST:event_changed
 124.281 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 124.282 +    private javax.swing.JComboBox classCombo;
 124.283 +    private javax.swing.JLabel classLabel;
 124.284 +    private javax.swing.JComboBox functionCombo;
 124.285 +    private javax.swing.JLabel functionLabel;
 124.286 +    private javax.swing.JLabel ignoreLabel;
 124.287 +    private javax.swing.JTextField ignoredText;
 124.288 +    private javax.swing.JComboBox moduleCombo;
 124.289 +    private javax.swing.JLabel moduleLabel;
 124.290 +    private javax.swing.JLabel parameterLabel;
 124.291 +    private javax.swing.JCheckBox selfCb;
 124.292 +    private javax.swing.JComboBox variableCombo;
 124.293 +    private javax.swing.JLabel variableLabel;
 124.294 +    // End of variables declaration//GEN-END:variables
 124.295 +}
   125.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   125.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/PythonAstRule.java	Sun Sep 13 11:47:42 2015 +0200
   125.3 @@ -0,0 +1,51 @@
   125.4 +/*
   125.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   125.6 + *
   125.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   125.8 + *
   125.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  125.10 + * Other names may be trademarks of their respective owners.
  125.11 + *
  125.12 + * The contents of this file are subject to the terms of either the GNU
  125.13 + * General Public License Version 2 only ("GPL") or the Common
  125.14 + * Development and Distribution License("CDDL") (collectively, the
  125.15 + * "License"). You may not use this file except in compliance with the
  125.16 + * License. You can obtain a copy of the License at
  125.17 + * http://www.netbeans.org/cddl-gplv2.html
  125.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  125.19 + * specific language governing permissions and limitations under the
  125.20 + * License.  When distributing the software, include this License Header
  125.21 + * Notice in each file and include the License file at
  125.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  125.23 + * particular file as subject to the "Classpath" exception as provided
  125.24 + * by Oracle in the GPL Version 2 section of the License file that
  125.25 + * accompanied this code. If applicable, add the following below the
  125.26 + * License Header, with the fields enclosed by brackets [] replaced by
  125.27 + * your own identifying information:
  125.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  125.29 + *
  125.30 + * Contributor(s):
  125.31 + *
  125.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  125.33 + */
  125.34 +package org.netbeans.modules.python.hints;
  125.35 +
  125.36 +import java.util.List;
  125.37 +import java.util.Set;
  125.38 +import org.netbeans.modules.csl.api.Hint;
  125.39 +import org.netbeans.modules.csl.api.Rule.AstRule;
  125.40 +
  125.41 +public abstract class PythonAstRule implements AstRule {
  125.42 +    /** 
  125.43 +     * Get the ElementKinds this rule should run on.
  125.44 +     * The integers should correspond to values in {@link org.mozilla.javascript.Token}
  125.45 +     */
  125.46 +    @Override
  125.47 +    public abstract Set<Class> getKinds();
  125.48 +
  125.49 +    /**
  125.50 +     * Run the test on given CompilationUnit and return list of Errors or
  125.51 +     * warrnings to be shown in the editor.
  125.52 +     */
  125.53 +    public abstract void run(PythonRuleContext context, List<Hint> result);
  125.54 +}
   126.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   126.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/PythonHintOptions.java	Sun Sep 13 11:47:42 2015 +0200
   126.3 @@ -0,0 +1,71 @@
   126.4 +/*
   126.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   126.6 + *
   126.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   126.8 + *
   126.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  126.10 + * Other names may be trademarks of their respective owners.
  126.11 + *
  126.12 + * The contents of this file are subject to the terms of either the GNU
  126.13 + * General Public License Version 2 only ("GPL") or the Common
  126.14 + * Development and Distribution License("CDDL") (collectively, the
  126.15 + * "License"). You may not use this file except in compliance with the
  126.16 + * License. You can obtain a copy of the License at
  126.17 + * http://www.netbeans.org/cddl-gplv2.html
  126.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  126.19 + * specific language governing permissions and limitations under the
  126.20 + * License.  When distributing the software, include this License Header
  126.21 + * Notice in each file and include the License file at
  126.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  126.23 + * particular file as subject to the "Classpath" exception as provided
  126.24 + * by Oracle in the GPL Version 2 section of the License file that
  126.25 + * accompanied this code. If applicable, add the following below the
  126.26 + * License Header, with the fields enclosed by brackets [] replaced by
  126.27 + * your own identifying information:
  126.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  126.29 + *
  126.30 + * Contributor(s):
  126.31 + *
  126.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  126.33 + */
  126.34 +package org.netbeans.modules.python.hints;
  126.35 +
  126.36 +import org.netbeans.modules.csl.api.HintsProvider;
  126.37 +import org.netbeans.modules.csl.api.HintsProvider.HintsManager;
  126.38 +import org.netbeans.modules.python.api.PythonMIMEResolver;
  126.39 +import org.netbeans.spi.options.AdvancedOption;
  126.40 +import org.netbeans.spi.options.OptionsPanelController;
  126.41 +import org.openide.util.NbBundle;
  126.42 +
  126.43 +/**
  126.44 + * Hint settings for Python
  126.45 + */
  126.46 +public class PythonHintOptions extends AdvancedOption {
  126.47 +    OptionsPanelController panelController;
  126.48 +
  126.49 +    @Override
  126.50 +    public String getDisplayName() {
  126.51 +        return NbBundle.getMessage(PythonHintOptions.class, "CTL_Hints_DisplayName"); // NOI18N
  126.52 +    }
  126.53 +
  126.54 +    @Override
  126.55 +    public String getTooltip() {
  126.56 +        return NbBundle.getMessage(PythonHintOptions.class, "CTL_Hints_ToolTip"); // NOI18N
  126.57 +    }
  126.58 +
  126.59 +    @Override
  126.60 +    public synchronized OptionsPanelController create() {
  126.61 +        if (panelController == null) {
  126.62 +            HintsManager manager = HintsProvider.HintsManager.getManagerForMimeType(PythonMIMEResolver.PYTHON_MIME_TYPE);
  126.63 +            assert manager != null;
  126.64 +            panelController = manager.getOptionsController();
  126.65 +        }
  126.66 +
  126.67 +        return panelController;
  126.68 +    }
  126.69 +
  126.70 +    //TODO: temporary solution, this should be solved on GSF level
  126.71 +    public static OptionsPanelController createStatic() {
  126.72 +        return new PythonHintOptions().create();
  126.73 +    }
  126.74 +}
   127.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   127.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/PythonHintsProvider.java	Sun Sep 13 11:47:42 2015 +0200
   127.3 @@ -0,0 +1,433 @@
   127.4 +/*
   127.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   127.6 + *
   127.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   127.8 + *
   127.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  127.10 + * Other names may be trademarks of their respective owners.
  127.11 + *
  127.12 + * The contents of this file are subject to the terms of either the GNU
  127.13 + * General Public License Version 2 only ("GPL") or the Common
  127.14 + * Development and Distribution License("CDDL") (collectively, the
  127.15 + * "License"). You may not use this file except in compliance with the
  127.16 + * License. You can obtain a copy of the License at
  127.17 + * http://www.netbeans.org/cddl-gplv2.html
  127.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  127.19 + * specific language governing permissions and limitations under the
  127.20 + * License.  When distributing the software, include this License Header
  127.21 + * Notice in each file and include the License file at
  127.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  127.23 + * particular file as subject to the "Classpath" exception as provided
  127.24 + * by Oracle in the GPL Version 2 section of the License file that
  127.25 + * accompanied this code. If applicable, add the following below the
  127.26 + * License Header, with the fields enclosed by brackets [] replaced by
  127.27 + * your own identifying information:
  127.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  127.29 + *
  127.30 + * Contributor(s):
  127.31 + *
  127.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  127.33 + */
  127.34 +package org.netbeans.modules.python.hints;
  127.35 +
  127.36 +import java.util.Collections;
  127.37 +import java.util.HashMap;
  127.38 +import java.util.Iterator;
  127.39 +import java.util.LinkedList;
  127.40 +import java.util.List;
  127.41 +import java.util.Map;
  127.42 +import java.util.Map.Entry;
  127.43 +import java.util.Set;
  127.44 +import org.netbeans.modules.csl.api.Error;
  127.45 +import org.netbeans.modules.csl.api.Hint;
  127.46 +import org.netbeans.modules.csl.api.HintFix;
  127.47 +import org.netbeans.modules.csl.api.HintSeverity;
  127.48 +import org.netbeans.modules.csl.api.HintsProvider;
  127.49 +import org.netbeans.modules.csl.api.HintsProvider.HintsManager;
  127.50 +import org.netbeans.modules.csl.api.OffsetRange;
  127.51 +import org.netbeans.modules.csl.api.Rule;
  127.52 +import org.netbeans.modules.csl.api.RuleContext;
  127.53 +import org.netbeans.modules.csl.spi.GsfUtilities;
  127.54 +import org.netbeans.modules.csl.spi.ParserResult;
  127.55 +import org.netbeans.modules.python.source.AstPath;
  127.56 +import org.netbeans.modules.python.source.PythonAstUtils;
  127.57 +import org.netbeans.modules.python.source.PythonParserResult;
  127.58 +import org.openide.util.Exceptions;
  127.59 +import org.python.antlr.PythonTree;
  127.60 +import org.python.antlr.Visitor;
  127.61 +
  127.62 +/**
  127.63 + *
  127.64 + * @todo Write rules based on the PythonChecker ideas:
  127.65 + *   http://pychecker.sourceforge.net/
  127.66 + * @todo Write rules based on the PyLint ideas:
  127.67 + *   http://www.logilab.org/projects/pylint
  127.68 + *   http://www.logilab.org/card/pylintfeatures
  127.69 + *
  127.70 + * @author Tor Norbye
  127.71 + */
  127.72 +public class PythonHintsProvider implements HintsProvider {
  127.73 +    private boolean cancelled;
  127.74 +
  127.75 +    public PythonHintsProvider() {
  127.76 +    }
  127.77 +
  127.78 +    private static class ScopeRule implements Rule {
  127.79 +        @Override
  127.80 +        public boolean appliesTo(RuleContext context) {
  127.81 +            return true;
  127.82 +        }
  127.83 +
  127.84 +        @Override
  127.85 +        public String getDisplayName() {
  127.86 +            return "";
  127.87 +        }
  127.88 +
  127.89 +        @Override
  127.90 +        public boolean showInTasklist() {
  127.91 +            return true;
  127.92 +        }
  127.93 +
  127.94 +        @Override
  127.95 +        public HintSeverity getDefaultSeverity() {
  127.96 +            return HintSeverity.ERROR;
  127.97 +        }
  127.98 +    }
  127.99 +    
 127.100 +    @Override
 127.101 +    public void computeErrors(HintsManager manager, RuleContext context, List<Hint> result, List<Error> unhandled) {
 127.102 +        ParserResult parserResult = context.parserResult;
 127.103 +        if (parserResult == null) {
 127.104 +            return;
 127.105 +        }
 127.106 +
 127.107 +        PythonParserResult pr = (PythonParserResult)parserResult;
 127.108 +        List<Error> scopeErrors = pr.getSymbolTable().getErrors();
 127.109 +        if (scopeErrors.size() > 0) {
 127.110 +            List<HintFix> fixList = Collections.emptyList();
 127.111 +            Rule rule = new ScopeRule(); // HACK! Just need a rule that will return a severity!
 127.112 +            for (Error error : scopeErrors) {
 127.113 +                Hint desc = new Hint(rule, error.getDisplayName(), error.getFile(),
 127.114 +                        new OffsetRange(error.getStartPosition(), error.getEndPosition()), fixList, 10);
 127.115 +                result.add(desc);
 127.116 +            }
 127.117 +        }
 127.118 +
 127.119 +        List<? extends Error> errors = parserResult.getDiagnostics();
 127.120 +        if (errors == null || errors.size() == 0) {
 127.121 +            return;
 127.122 +        }
 127.123 +//
 127.124 +//        cancelled = false;
 127.125 +//
 127.126 +//        @SuppressWarnings("unchecked")
 127.127 +//        Map<String,List<JsErrorRule>> hints = (Map)manager.getErrors();
 127.128 +//
 127.129 +//        if (hints.isEmpty() || isCancelled()) {
 127.130 +        unhandled.addAll(errors);
 127.131 +//            return;
 127.132 +//        }
 127.133 +//
 127.134 +//        for (Error error : errors) {
 127.135 +//            if (!applyErrorRules(manager, context, error, hints, result)) {
 127.136 +//                unhandled.add(error);
 127.137 +//            }
 127.138 +//        }
 127.139 +    }
 127.140 +
 127.141 +    @Override
 127.142 +    public void computeSelectionHints(HintsManager manager, RuleContext context, List<Hint> result, int start, int end) {
 127.143 +        cancelled = false;
 127.144 +
 127.145 +        if (GsfUtilities.isCodeTemplateEditing(context.doc)) {
 127.146 +            return;
 127.147 +        }
 127.148 +
 127.149 +        ParserResult parserResult = context.parserResult;
 127.150 +        if (parserResult == null) {
 127.151 +            return;
 127.152 +        }
 127.153 +        PythonTree root = PythonAstUtils.getRoot(context.parserResult);
 127.154 +
 127.155 +        if (root == null) {
 127.156 +            return;
 127.157 +        }
 127.158 +        @SuppressWarnings("unchecked")
 127.159 +        List<? extends Rule.SelectionRule> hints = manager.getSelectionHints();
 127.160 +
 127.161 +        if (hints.isEmpty()) {
 127.162 +            return;
 127.163 +        }
 127.164 +
 127.165 +        if (isCancelled()) {
 127.166 +            return;
 127.167 +        }
 127.168 +
 127.169 +        try {
 127.170 +            context.doc.readLock();
 127.171 +            applySelectionRules(manager, context, hints, result);
 127.172 +        } finally {
 127.173 +            context.doc.readUnlock();
 127.174 +        }
 127.175 +}
 127.176 +
 127.177 +    private void applySelectionRules(HintsManager manager, RuleContext context, List<? extends Rule.SelectionRule> rules, List<Hint> result) {
 127.178 +
 127.179 +        PythonRuleContext pythonContext = (PythonRuleContext)context;
 127.180 +
 127.181 +        for (Rule.SelectionRule rule : rules) {
 127.182 +            if (!rule.appliesTo(context)) {
 127.183 +                continue;
 127.184 +            }
 127.185 +            
 127.186 +            if(!(rule instanceof PythonSelectionRule)) {
 127.187 +                continue;
 127.188 +            }
 127.189 +
 127.190 +            if (!manager.isEnabled((PythonSelectionRule)rule)) {
 127.191 +                continue;
 127.192 +            }
 127.193 +
 127.194 +            try {
 127.195 +                context.doc.readLock();
 127.196 +                ((PythonSelectionRule)rule).run(pythonContext, result);
 127.197 +            } finally {
 127.198 +                context.doc.readUnlock();
 127.199 +            }
 127.200 +        }
 127.201 +    }
 127.202 +
 127.203 +    @Override
 127.204 +    public void computeHints(HintsManager manager, RuleContext context, List<Hint> result) {
 127.205 +        cancelled = false;
 127.206 +
 127.207 +        if (context.parserResult == null) {
 127.208 +            return;
 127.209 +        }
 127.210 +        PythonTree root = PythonAstUtils.getRoot(context.parserResult);
 127.211 +
 127.212 +        if (root == null) {
 127.213 +            return;
 127.214 +        }
 127.215 +        @SuppressWarnings("unchecked")
 127.216 +        Map<Class, List<PythonAstRule>> hints = (Map)manager.getHints(false, context);
 127.217 +
 127.218 +        if (hints.isEmpty()) {
 127.219 +            return;
 127.220 +        }
 127.221 +
 127.222 +        if (isCancelled()) {
 127.223 +            return;
 127.224 +        }
 127.225 +
 127.226 +//        AstPath path = new AstPath();
 127.227 +//        path.descend(root);
 127.228 +//
 127.229 +//        //applyRules(manager, NodeTypes.ROOTNODE, root, path, info, hints, descriptions);
 127.230 +//        applyHints(manager, context, -1, root, path, hints, result);
 127.231 +//
 127.232 +//        scan(manager, context, root, path, hints, result);
 127.233 +//        path.ascend();
 127.234 +
 127.235 +
 127.236 +        RuleApplicator finder = new RuleApplicator(manager, context, hints, result);
 127.237 +        try {
 127.238 +            context.doc.readLock();
 127.239 +            finder.visit(root);
 127.240 +        } catch (Exception ex) {
 127.241 +            Exceptions.printStackTrace(ex);
 127.242 +        } finally {
 127.243 +            context.doc.readUnlock();
 127.244 +        }
 127.245 +    }
 127.246 +
 127.247 +    @SuppressWarnings("unchecked")
 127.248 +    @Override
 127.249 +    public void computeSuggestions(HintsManager manager, RuleContext context, List<Hint> result, int caretOffset) {
 127.250 +        cancelled = false;
 127.251 +        if (context.parserResult == null) {
 127.252 +            return;
 127.253 +        }
 127.254 +
 127.255 +        PythonTree root = PythonAstUtils.getRoot(context.parserResult);
 127.256 +
 127.257 +        if (root == null) {
 127.258 +            return;
 127.259 +        }
 127.260 +
 127.261 +        Map<Class, List<PythonAstRule>> suggestions = new HashMap<>();
 127.262 +        suggestions.putAll((Map)manager.getHints(true, context));
 127.263 +
 127.264 +        Set<Entry<Class, List<PythonAstRule>>> entrySet = (Set)manager.getSuggestions().entrySet();
 127.265 +        for (Entry<Class, List<PythonAstRule>> e : entrySet) {
 127.266 +            List<PythonAstRule> rules = suggestions.get(e.getKey());
 127.267 +
 127.268 +            if (rules != null) {
 127.269 +                List<PythonAstRule> res = new LinkedList<>();
 127.270 +
 127.271 +                res.addAll(rules);
 127.272 +                res.addAll(e.getValue());
 127.273 +
 127.274 +                suggestions.put(e.getKey(), res);
 127.275 +            } else {
 127.276 +                suggestions.put(e.getKey(), e.getValue());
 127.277 +            }
 127.278 +        }
 127.279 +
 127.280 +        if (suggestions.isEmpty()) {
 127.281 +            return;
 127.282 +        }
 127.283 +
 127.284 +
 127.285 +        if (isCancelled()) {
 127.286 +            return;
 127.287 +        }
 127.288 +
 127.289 +        try {
 127.290 +            context.doc.readLock();
 127.291 +
 127.292 +            PythonParserResult info = (PythonParserResult)context.parserResult;
 127.293 +            int astOffset = PythonAstUtils.getAstOffset(info, caretOffset);
 127.294 +            AstPath path = AstPath.get(root, astOffset);
 127.295 +            Iterator<PythonTree> it = path.leafToRoot();
 127.296 +            while (it.hasNext()) {
 127.297 +                if (isCancelled()) {
 127.298 +                    return;
 127.299 +                }
 127.300 +
 127.301 +                PythonTree node = it.next();
 127.302 +
 127.303 +                applySuggestions(manager, context, node.getClass(), node, path, suggestions, result);
 127.304 +            }
 127.305 +        } finally {
 127.306 +            context.doc.readUnlock();
 127.307 +        }
 127.308 +
 127.309 +    //applyRules(NodeTypes.ROOTNODE, path, info, suggestions, caretOffset, result);
 127.310 +    }
 127.311 +
 127.312 +    private void applySuggestions(HintsManager manager, RuleContext context, Class nodeType, PythonTree node, AstPath path, Map<Class, List<PythonAstRule>> hints,
 127.313 +            List<Hint> result) {
 127.314 +        List<PythonAstRule> rules = hints.get(nodeType);
 127.315 +
 127.316 +        if (rules != null) {
 127.317 +            PythonRuleContext pyCtx = (PythonRuleContext)context;
 127.318 +            pyCtx.node = node;
 127.319 +            pyCtx.path = path;
 127.320 +
 127.321 +            try {
 127.322 +                context.doc.readLock();
 127.323 +                for (PythonAstRule rule : rules) {
 127.324 +                    if (manager.isEnabled(rule)) {
 127.325 +                        rule.run(pyCtx, result);
 127.326 +                    }
 127.327 +                }
 127.328 +            } finally {
 127.329 +                context.doc.readUnlock();
 127.330 +            }
 127.331 +        }
 127.332 +    }
 127.333 +
 127.334 +//    /** Apply error rules and return true iff somebody added an error description for it */
 127.335 +//    private boolean applyErrorRules(HintsManager manager, RuleContext context, Error error, Map<String,List<JsErrorRule>> hints,
 127.336 +//            List<Hint> result) {
 127.337 +//        String code = error.getKey();
 127.338 +//        if (code != null) {
 127.339 +//            List<JsErrorRule> rules = hints.get(code);
 127.340 +//
 127.341 +//            if (rules != null) {
 127.342 +//                int countBefore = result.size();
 127.343 +//                PythonRuleContext jsContext = (PythonRuleContext)context;
 127.344 +//
 127.345 +//                boolean disabled = false;
 127.346 +//                for (JsErrorRule rule : rules) {
 127.347 +//                    if (!manager.isEnabled(rule)) {
 127.348 +//                        disabled = true;
 127.349 +//                    } else if (rule.appliesTo(context)) {
 127.350 +//                        rule.run(jsContext, error, result);
 127.351 +//                    }
 127.352 +//                }
 127.353 +//
 127.354 +//                return disabled || countBefore < result.size() || jsContext.remove;
 127.355 +//            }
 127.356 +//        }
 127.357 +//
 127.358 +//        return false;
 127.359 +//    }
 127.360 +//
 127.361 +//    private void applySelectionRules(HintsManager manager, RuleContext context, List<JsSelectionRule> rules,
 127.362 +//            List<Hint> result) {
 127.363 +//
 127.364 +//        for (JsSelectionRule rule : rules) {
 127.365 +//            if (!rule.appliesTo(context)) {
 127.366 +//                continue;
 127.367 +//            }
 127.368 +//
 127.369 +//            //if (!manager.isEnabled(rule)) {
 127.370 +//            //    continue;
 127.371 +//            //}
 127.372 +//
 127.373 +//            rule.run(context, result);
 127.374 +//        }
 127.375 +//    }
 127.376 +//
 127.377 +    @Override
 127.378 +    public void cancel() {
 127.379 +        cancelled = true;
 127.380 +    }
 127.381 +
 127.382 +    private boolean isCancelled() {
 127.383 +        return cancelled;
 127.384 +    }
 127.385 +
 127.386 +    @Override
 127.387 +    public RuleContext createRuleContext() {
 127.388 +        return new PythonRuleContext();
 127.389 +    }
 127.390 +
 127.391 +    @Override
 127.392 +    public List<Rule> getBuiltinRules() {
 127.393 +        return Collections.emptyList();
 127.394 +    }
 127.395 +
 127.396 +    private static class RuleApplicator extends Visitor {
 127.397 +        private HintsManager manager;
 127.398 +        private RuleContext context;
 127.399 +        private AstPath path;
 127.400 +        private Map<Class, List<PythonAstRule>> hints;
 127.401 +        private List<Hint> result;
 127.402 +
 127.403 +        public RuleApplicator(HintsManager manager, RuleContext context, Map<Class, List<PythonAstRule>> hints, List<Hint> result) {
 127.404 +            this.manager = manager;
 127.405 +            this.context = context;
 127.406 +            this.hints = hints;
 127.407 +            this.result = result;
 127.408 +
 127.409 +            path = new AstPath();
 127.410 +        }
 127.411 +
 127.412 +        @Override
 127.413 +        public void traverse(PythonTree node) throws Exception {
 127.414 +            path.descend(node);
 127.415 +            applyHints(node);
 127.416 +            super.traverse(node);
 127.417 +            path.ascend();
 127.418 +        }
 127.419 +
 127.420 +        private void applyHints(PythonTree node) {
 127.421 +            List<PythonAstRule> rules = hints.get(node.getClass());
 127.422 +
 127.423 +            if (rules != null) {
 127.424 +                PythonRuleContext jsContext = (PythonRuleContext)context;
 127.425 +                jsContext.node = node;
 127.426 +                jsContext.path = path;
 127.427 +
 127.428 +                for (PythonAstRule rule : rules) {
 127.429 +                    if (manager.isEnabled(rule)) {
 127.430 +                        rule.run(jsContext, result);
 127.431 +                    }
 127.432 +                }
 127.433 +            }
 127.434 +        }
 127.435 +    }
 127.436 +}
   128.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   128.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/PythonRuleContext.java	Sun Sep 13 11:47:42 2015 +0200
   128.3 @@ -0,0 +1,45 @@
   128.4 +/*
   128.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   128.6 + *
   128.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   128.8 + *
   128.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  128.10 + * Other names may be trademarks of their respective owners.
  128.11 + *
  128.12 + * The contents of this file are subject to the terms of either the GNU
  128.13 + * General Public License Version 2 only ("GPL") or the Common
  128.14 + * Development and Distribution License("CDDL") (collectively, the
  128.15 + * "License"). You may not use this file except in compliance with the
  128.16 + * License. You can obtain a copy of the License at
  128.17 + * http://www.netbeans.org/cddl-gplv2.html
  128.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  128.19 + * specific language governing permissions and limitations under the
  128.20 + * License.  When distributing the software, include this License Header
  128.21 + * Notice in each file and include the License file at
  128.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  128.23 + * particular file as subject to the "Classpath" exception as provided
  128.24 + * by Oracle in the GPL Version 2 section of the License file that
  128.25 + * accompanied this code. If applicable, add the following below the
  128.26 + * License Header, with the fields enclosed by brackets [] replaced by
  128.27 + * your own identifying information:
  128.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  128.29 + *
  128.30 + * Contributor(s):
  128.31 + *
  128.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  128.33 + */
  128.34 +package org.netbeans.modules.python.hints;
  128.35 +
  128.36 +import org.netbeans.modules.python.source.AstPath;
  128.37 +import org.python.antlr.PythonTree;
  128.38 +
  128.39 +/**
  128.40 + * Information about the current context a rule is being asked to evaluate.
  128.41 + * 
  128.42 + * @author Tor Norbye
  128.43 + */
  128.44 +public class PythonRuleContext extends org.netbeans.modules.csl.api.RuleContext {
  128.45 +    public AstPath path;
  128.46 +    public PythonTree node;
  128.47 +    public boolean remove;
  128.48 +}
   129.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/PythonSelectionRule.java	Sun Sep 13 11:47:42 2015 +0200
   129.3 @@ -0,0 +1,128 @@
   129.4 +/*
   129.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   129.6 + *
   129.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   129.8 + *
   129.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  129.10 + * Other names may be trademarks of their respective owners.
  129.11 + *
  129.12 + * The contents of this file are subject to the terms of either the GNU
  129.13 + * General Public License Version 2 only ("GPL") or the Common
  129.14 + * Development and Distribution License("CDDL") (collectively, the
  129.15 + * "License"). You may not use this file except in compliance with the
  129.16 + * License. You can obtain a copy of the License at
  129.17 + * http://www.netbeans.org/cddl-gplv2.html
  129.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  129.19 + * specific language governing permissions and limitations under the
  129.20 + * License.  When distributing the software, include this License Header
  129.21 + * Notice in each file and include the License file at
  129.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  129.23 + * particular file as subject to the "Classpath" exception as provided
  129.24 + * by Oracle in the GPL Version 2 section of the License file that
  129.25 + * accompanied this code. If applicable, add the following below the
  129.26 + * License Header, with the fields enclosed by brackets [] replaced by
  129.27 + * your own identifying information:
  129.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  129.29 + *
  129.30 + * Contributor(s):
  129.31 + *
  129.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  129.33 + */
  129.34 +package org.netbeans.modules.python.hints;
  129.35 +
  129.36 +import javax.swing.text.BadLocationException;
  129.37 +import java.util.List;
  129.38 +import org.netbeans.modules.python.source.PythonAstUtils;
  129.39 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  129.40 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
  129.41 +import org.netbeans.api.lexer.Token;
  129.42 +import org.netbeans.api.lexer.TokenId;
  129.43 +import org.netbeans.editor.BaseDocument;
  129.44 +import org.netbeans.editor.Utilities;
  129.45 +import org.netbeans.modules.csl.api.Hint;
  129.46 +import org.netbeans.modules.csl.api.OffsetRange;
  129.47 +import org.netbeans.modules.csl.api.Rule.SelectionRule;
  129.48 +import org.netbeans.modules.csl.api.Rule.UserConfigurableRule;
  129.49 +import org.openide.util.Exceptions;
  129.50 +import org.python.antlr.PythonTree;
  129.51 +
  129.52 +/**
  129.53 + * Represents a rule to be run on text selection
  129.54 + *
  129.55 + * @author Tor Norbye
  129.56 + */
  129.57 +public abstract class PythonSelectionRule implements SelectionRule, UserConfigurableRule {
  129.58 +    protected abstract int getApplicability(PythonRuleContext context, PythonTree root, OffsetRange astRange);
  129.59 +
  129.60 +    //public abstract void run(PythonRuleContext context, List<Hint> result);
  129.61 +    public void run(PythonRuleContext context, List<Hint> result) {
  129.62 +        // TODO - decide if this code represents a complete statement...
  129.63 +        // For now - that's true iff there's no code to the left on the
  129.64 +        // start line and code to the right on the end line
  129.65 +        BaseDocument doc = context.doc;
  129.66 +        int originalStart = context.selectionStart;
  129.67 +        int originalEnd = context.selectionEnd;
  129.68 +        int docLength = doc.getLength();
  129.69 +
  129.70 +        if (originalEnd > docLength) {
  129.71 +            return;
  129.72 +        }
  129.73 +        OffsetRange narrowed = PythonLexerUtils.narrow(doc, new OffsetRange(originalStart, originalEnd), false);
  129.74 +        if (narrowed == OffsetRange.NONE) {
  129.75 +            return;
  129.76 +        }
  129.77 +
  129.78 +        int start = narrowed.getStart();
  129.79 +        int end = narrowed.getEnd();
  129.80 +        try {
  129.81 +            if (start > Utilities.getRowFirstNonWhite(doc, Math.min(docLength, start))) {
  129.82 +                return;
  129.83 +            }
  129.84 +            if (end < Utilities.getRowLastNonWhite(doc, Math.min(docLength, end)) + 1) {
  129.85 +                return;
  129.86 +            }
  129.87 +        } catch (BadLocationException ex) {
  129.88 +            Exceptions.printStackTrace(ex);
  129.89 +        }
  129.90 +
  129.91 +        PythonTree root = PythonAstUtils.getRoot(context.parserResult);
  129.92 +        if (root == null) {
  129.93 +            return;
  129.94 +        }
  129.95 +
  129.96 +        OffsetRange astRange = PythonAstUtils.getAstOffsets(context.parserResult, new OffsetRange(start, end));
  129.97 +        if (astRange == OffsetRange.NONE) {
  129.98 +            return;
  129.99 +        }
 129.100 +
 129.101 +        int applicability = getApplicability(context, root, astRange);
 129.102 +        if (applicability == 0) {
 129.103 +            return;
 129.104 +        }
 129.105 +        // Don't allow extract with if you're inside strings or comments
 129.106 +        Token<? extends PythonTokenId> startToken = PythonLexerUtils.getToken(doc, start);
 129.107 +        Token<? extends PythonTokenId> endToken = PythonLexerUtils.getToken(doc, end);
 129.108 +        if (startToken == null || endToken == null) {
 129.109 +            return;
 129.110 +        }
 129.111 +        TokenId startId = startToken.id();
 129.112 +        if (startId == PythonTokenId.STRING_LITERAL ||
 129.113 +                (startId == PythonTokenId.COMMENT && start > 0 && startToken == PythonLexerUtils.getToken(doc, start - 1))) {
 129.114 +            return;
 129.115 +        }
 129.116 +        TokenId endId = endToken.id();
 129.117 +        if (endId == PythonTokenId.STRING_LITERAL) {
 129.118 +            return;
 129.119 +        }
 129.120 +
 129.121 +        // TODO - don't enable inside comments or strings!!
 129.122 +        // TODO - if you are including functions or classes it should probably
 129.123 +        // be disabled!
 129.124 +
 129.125 +        OffsetRange range = new OffsetRange(originalStart, originalEnd);
 129.126 +
 129.127 +        run(context, result, range, applicability);
 129.128 +    }
 129.129 +
 129.130 +    public abstract void run(PythonRuleContext context, List<Hint> result, OffsetRange range, int applicability);
 129.131 +}
   130.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/RelativeImports.java	Sun Sep 13 11:47:42 2015 +0200
   130.3 @@ -0,0 +1,246 @@
   130.4 +/*
   130.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   130.6 + *
   130.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   130.8 + *
   130.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  130.10 + * Other names may be trademarks of their respective owners.
  130.11 + *
  130.12 + * The contents of this file are subject to the terms of either the GNU
  130.13 + * General Public License Version 2 only ("GPL") or the Common
  130.14 + * Development and Distribution License("CDDL") (collectively, the
  130.15 + * "License"). You may not use this file except in compliance with the
  130.16 + * License. You can obtain a copy of the License at
  130.17 + * http://www.netbeans.org/cddl-gplv2.html
  130.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  130.19 + * specific language governing permissions and limitations under the
  130.20 + * License.  When distributing the software, include this License Header
  130.21 + * Notice in each file and include the License file at
  130.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  130.23 + * particular file as subject to the "Classpath" exception as provided
  130.24 + * by Oracle in the GPL Version 2 section of the License file that
  130.25 + * accompanied this code. If applicable, add the following below the
  130.26 + * License Header, with the fields enclosed by brackets [] replaced by
  130.27 + * your own identifying information:
  130.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  130.29 + *
  130.30 + * If you wish your version of this file to be governed by only the CDDL
  130.31 + * or only the GPL Version 2, indicate your decision by adding
  130.32 + * "[Contributor] elects to include this software in this distribution
  130.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  130.34 + * single choice of license, a recipient has the option to distribute
  130.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  130.36 + * to extend the choice of license to its licensees as provided above.
  130.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  130.38 + * Version 2 license, then the option applies only if the new code is
  130.39 + * made subject to such option by the copyright holder.
  130.40 + *
  130.41 + * Contributor(s):
  130.42 + *
  130.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  130.44 + */
  130.45 +package org.netbeans.modules.python.hints;
  130.46 +
  130.47 +import java.util.ArrayList;
  130.48 +import java.util.Collections;
  130.49 +import java.util.List;
  130.50 +import java.util.Set;
  130.51 +import java.util.prefs.Preferences;
  130.52 +import javax.swing.JComponent;
  130.53 +import javax.swing.text.BadLocationException;
  130.54 +import org.netbeans.modules.python.source.PythonAstUtils;
  130.55 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  130.56 +import org.netbeans.editor.BaseDocument;
  130.57 +import org.netbeans.editor.Utilities;
  130.58 +import org.netbeans.modules.csl.api.EditList;
  130.59 +import org.netbeans.modules.csl.api.Hint;
  130.60 +import org.netbeans.modules.csl.api.HintFix;
  130.61 +import org.netbeans.modules.csl.api.HintSeverity;
  130.62 +import org.netbeans.modules.csl.api.OffsetRange;
  130.63 +import org.netbeans.modules.csl.api.PreviewableFix;
  130.64 +import org.netbeans.modules.csl.api.RuleContext;
  130.65 +import org.netbeans.modules.csl.spi.ParserResult;
  130.66 +import org.netbeans.modules.python.source.PythonParserResult;
  130.67 +import org.openide.filesystems.FileObject;
  130.68 +import org.openide.util.Exceptions;
  130.69 +import org.openide.util.NbBundle;
  130.70 +import org.python.antlr.PythonTree;
  130.71 +import org.python.antlr.ast.ImportFrom;
  130.72 +
  130.73 +/**
  130.74 + * Import statements should be one per line. This quickfix
  130.75 + * offers to make it so.
  130.76 + *
  130.77 + * @todo Ensure that
  130.78 + *  {@code from __future__ import absolute_import}
  130.79 + *   is present, at least until Python 2.7
  130.80 + *
  130.81 + * @author Tor Norbye
  130.82 + */
  130.83 +public class RelativeImports extends PythonAstRule {
  130.84 +    @Override
  130.85 +    public Set<Class> getKinds() {
  130.86 +        return Collections.singleton((Class)ImportFrom.class);
  130.87 +    }
  130.88 +
  130.89 +    @Override
  130.90 +    public void run(PythonRuleContext context, List<Hint> result) {
  130.91 +        ImportFrom imp = (ImportFrom)context.node;
  130.92 +        if (imp.getInternalModule() != null && imp.getInternalModule().startsWith(".")) {
  130.93 +            PythonTree node = context.node;
  130.94 +            PythonParserResult info = (PythonParserResult) context.parserResult;
  130.95 +            OffsetRange astOffsets = PythonAstUtils.getNameRange(info, node);
  130.96 +            OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
  130.97 +            BaseDocument doc = context.doc;
  130.98 +            try {
  130.99 +                if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
 130.100 +                        (context.caretOffset == -1 ||
 130.101 +                        Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
 130.102 +                    List<HintFix> fixList = new ArrayList<>();
 130.103 +                    fixList.add(new RelativeImportsFix(context, imp));
 130.104 +                    String displayName = getDisplayName();
 130.105 +                    Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
 130.106 +                    result.add(desc);
 130.107 +                }
 130.108 +            } catch (BadLocationException ex) {
 130.109 +                Exceptions.printStackTrace(ex);
 130.110 +            }
 130.111 +        }
 130.112 +    }
 130.113 +
 130.114 +    @Override
 130.115 +    public String getId() {
 130.116 +        return "RelativeImports"; // NOI18N
 130.117 +    }
 130.118 +
 130.119 +    @Override
 130.120 +    public String getDisplayName() {
 130.121 +        return NbBundle.getMessage(RelativeImports.class, "RelativeImports");
 130.122 +    }
 130.123 +
 130.124 +    @Override
 130.125 +    public String getDescription() {
 130.126 +        return NbBundle.getMessage(RelativeImports.class, "RelativeImportsDesc");
 130.127 +    }
 130.128 +
 130.129 +    @Override
 130.130 +    public boolean getDefaultEnabled() {
 130.131 +        return true;
 130.132 +    }
 130.133 +
 130.134 +    @Override
 130.135 +    public JComponent getCustomizer(Preferences node) {
 130.136 +        return null;
 130.137 +    }
 130.138 +
 130.139 +    @Override
 130.140 +    public boolean appliesTo(RuleContext context) {
 130.141 +        return true;
 130.142 +    }
 130.143 +
 130.144 +    @Override
 130.145 +    public boolean showInTasklist() {
 130.146 +        return true;
 130.147 +    }
 130.148 +
 130.149 +    @Override
 130.150 +    public HintSeverity getDefaultSeverity() {
 130.151 +        return HintSeverity.WARNING;
 130.152 +    }
 130.153 +
 130.154 +    private static class RelativeImportsFix implements PreviewableFix {
 130.155 +        private final PythonRuleContext context;
 130.156 +        private final ImportFrom imp;
 130.157 +
 130.158 +        private RelativeImportsFix(PythonRuleContext context, ImportFrom imp) {
 130.159 +            this.context = context;
 130.160 +            this.imp = imp;
 130.161 +        }
 130.162 +
 130.163 +        @Override
 130.164 +        public String getDescription() {
 130.165 +            return NbBundle.getMessage(RelativeImports.class, "RelativeImportsFix");
 130.166 +        }
 130.167 +
 130.168 +        @Override
 130.169 +        public boolean canPreview() {
 130.170 +            return true;
 130.171 +        }
 130.172 +
 130.173 +        @Override
 130.174 +        public EditList getEditList() throws Exception {
 130.175 +            BaseDocument doc = context.doc;
 130.176 +            EditList edits = new EditList(doc);
 130.177 +
 130.178 +            // Algorithm:
 130.179 +            //  (1) Figure out which package we are in
 130.180 +            //  (2) Subtrack package elements per dot
 130.181 +            //  (3) Replace relative reference
 130.182 +
 130.183 +            OffsetRange astRange = PythonAstUtils.getRange(imp);
 130.184 +            if (astRange != OffsetRange.NONE) {
 130.185 +                PythonParserResult info = (PythonParserResult)context.parserResult;
 130.186 +                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 130.187 +                if (lexRange != OffsetRange.NONE) {
 130.188 +                    FileObject fo = info.getSnapshot().getSource().getFileObject();
 130.189 +                    if (fo != null) {
 130.190 +                        String path = imp.getInternalModule();
 130.191 +                        int i = 0;
 130.192 +                        for (; i < path.length(); i++) {
 130.193 +                            if (path.charAt(i) != '.') {
 130.194 +                                break;
 130.195 +                            }
 130.196 +                        }
 130.197 +                        int levels = i;
 130.198 +                        path = path.substring(levels);
 130.199 +
 130.200 +                        for (int j = 0; j < levels; j++) {
 130.201 +                            if (fo != null) {
 130.202 +                                fo = fo.getParent();
 130.203 +                            }
 130.204 +                        }
 130.205 +
 130.206 +                        // Finally, find out the absolute path we are in
 130.207 +                        // Hopefully, I will have access to the python load path
 130.208 +                        // here. But in the mean time, I can just see which 
 130.209 +                        // packages I am in...
 130.210 +                        while (fo != null) {
 130.211 +                            if (fo.getFileObject("__init__.py") != null) { // NOI18N
 130.212 +                                // Yep, we're still in a package
 130.213 +                                if (path.length() > 0) {
 130.214 +                                    path = fo.getName() + "." + path; // NOI18N
 130.215 +                                } else {
 130.216 +                                    path = fo.getName();
 130.217 +                                }
 130.218 +                            }
 130.219 +                            fo = fo.getParent();
 130.220 +                        }
 130.221 +                        String text = doc.getText(lexRange.getStart(), lexRange.getLength());
 130.222 +                        int relativePos = text.indexOf(imp.getInternalModule());
 130.223 +                        if (relativePos != -1) {
 130.224 +                            edits.replace(lexRange.getStart() + relativePos, imp.getInternalModule().length(), path, false, 0);
 130.225 +                        }
 130.226 +                    }
 130.227 +                }
 130.228 +            }
 130.229 +
 130.230 +            return edits;
 130.231 +        }
 130.232 +
 130.233 +        @Override
 130.234 +        public void implement() throws Exception {
 130.235 +            EditList edits = getEditList();
 130.236 +            edits.apply();
 130.237 +        }
 130.238 +
 130.239 +        @Override
 130.240 +        public boolean isSafe() {
 130.241 +            return true;
 130.242 +        }
 130.243 +
 130.244 +        @Override
 130.245 +        public boolean isInteractive() {
 130.246 +            return false;
 130.247 +        }
 130.248 +    }
 130.249 +}
   131.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   131.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/SplitImports.java	Sun Sep 13 11:47:42 2015 +0200
   131.3 @@ -0,0 +1,222 @@
   131.4 +/*
   131.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   131.6 + *
   131.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   131.8 + *
   131.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  131.10 + * Other names may be trademarks of their respective owners.
  131.11 + *
  131.12 + * The contents of this file are subject to the terms of either the GNU
  131.13 + * General Public License Version 2 only ("GPL") or the Common
  131.14 + * Development and Distribution License("CDDL") (collectively, the
  131.15 + * "License"). You may not use this file except in compliance with the
  131.16 + * License. You can obtain a copy of the License at
  131.17 + * http://www.netbeans.org/cddl-gplv2.html
  131.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  131.19 + * specific language governing permissions and limitations under the
  131.20 + * License.  When distributing the software, include this License Header
  131.21 + * Notice in each file and include the License file at
  131.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  131.23 + * particular file as subject to the "Classpath" exception as provided
  131.24 + * by Oracle in the GPL Version 2 section of the License file that
  131.25 + * accompanied this code. If applicable, add the following below the
  131.26 + * License Header, with the fields enclosed by brackets [] replaced by
  131.27 + * your own identifying information:
  131.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  131.29 + *
  131.30 + * If you wish your version of this file to be governed by only the CDDL
  131.31 + * or only the GPL Version 2, indicate your decision by adding
  131.32 + * "[Contributor] elects to include this software in this distribution
  131.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  131.34 + * single choice of license, a recipient has the option to distribute
  131.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  131.36 + * to extend the choice of license to its licensees as provided above.
  131.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  131.38 + * Version 2 license, then the option applies only if the new code is
  131.39 + * made subject to such option by the copyright holder.
  131.40 + *
  131.41 + * Contributor(s):
  131.42 + *
  131.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  131.44 + */
  131.45 +package org.netbeans.modules.python.hints;
  131.46 +
  131.47 +import java.util.ArrayList;
  131.48 +import java.util.Collections;
  131.49 +import java.util.List;
  131.50 +import java.util.Set;
  131.51 +import java.util.prefs.Preferences;
  131.52 +import javax.swing.JComponent;
  131.53 +import javax.swing.text.BadLocationException;
  131.54 +import org.netbeans.modules.python.source.PythonAstUtils;
  131.55 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  131.56 +import org.netbeans.editor.BaseDocument;
  131.57 +import org.netbeans.editor.Utilities;
  131.58 +import org.netbeans.modules.csl.api.EditList;
  131.59 +import org.netbeans.modules.csl.api.Hint;
  131.60 +import org.netbeans.modules.csl.api.HintFix;
  131.61 +import org.netbeans.modules.csl.api.HintSeverity;
  131.62 +import org.netbeans.modules.csl.api.OffsetRange;
  131.63 +import org.netbeans.modules.csl.api.PreviewableFix;
  131.64 +import org.netbeans.modules.csl.api.RuleContext;
  131.65 +import org.netbeans.modules.csl.spi.GsfUtilities;
  131.66 +import org.netbeans.modules.editor.indent.api.IndentUtils;
  131.67 +import org.netbeans.modules.python.source.PythonParserResult;
  131.68 +import org.netbeans.modules.python.source.CodeStyle;
  131.69 +import org.openide.util.Exceptions;
  131.70 +import org.openide.util.NbBundle;
  131.71 +import org.python.antlr.PythonTree;
  131.72 +import org.python.antlr.ast.Import;
  131.73 +import org.python.antlr.ast.alias;
  131.74 +
  131.75 +/**
  131.76 + * Import statements should be one per line. This quickfix
  131.77 + * offers to make it so.
  131.78 + *
  131.79 + * @author Tor Norbye
  131.80 + */
  131.81 +public class SplitImports extends PythonAstRule {
  131.82 +    @Override
  131.83 +    public Set<Class> getKinds() {
  131.84 +        return Collections.singleton((Class)Import.class);
  131.85 +    }
  131.86 +
  131.87 +    @Override
  131.88 +    public void run(PythonRuleContext context, List<Hint> result) {
  131.89 +        Import imp = (Import)context.node;
  131.90 +        List<alias> names = imp.getInternalNames();
  131.91 +        if (names != null && names.size() > 1) {
  131.92 +            PythonTree node = context.node;
  131.93 +            PythonParserResult info = (PythonParserResult)context.parserResult;
  131.94 +            OffsetRange astOffsets = PythonAstUtils.getNameRange(info, node);
  131.95 +            OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
  131.96 +            BaseDocument doc = context.doc;
  131.97 +            try {
  131.98 +                if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
  131.99 +                        (context.caretOffset == -1 ||
 131.100 +                        Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
 131.101 +                    List<HintFix> fixList = new ArrayList<>();
 131.102 +                    fixList.add(new SplitImportsFix(context, imp));
 131.103 +                    String displayName = getDisplayName();
 131.104 +                    Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
 131.105 +                    result.add(desc);
 131.106 +                }
 131.107 +            } catch (BadLocationException ex) {
 131.108 +                Exceptions.printStackTrace(ex);
 131.109 +            }
 131.110 +        }
 131.111 +    }
 131.112 +
 131.113 +    @Override
 131.114 +    public String getId() {
 131.115 +        return "SplitImports"; // NOI18N
 131.116 +    }
 131.117 +
 131.118 +    @Override
 131.119 +    public String getDisplayName() {
 131.120 +        return NbBundle.getMessage(SplitImports.class, "SplitImports");
 131.121 +    }
 131.122 +
 131.123 +    @Override
 131.124 +    public String getDescription() {
 131.125 +        return NbBundle.getMessage(SplitImports.class, "SplitImportsDesc");
 131.126 +    }
 131.127 +
 131.128 +    @Override
 131.129 +    public boolean getDefaultEnabled() {
 131.130 +        return true;
 131.131 +    }
 131.132 +
 131.133 +    @Override
 131.134 +    public JComponent getCustomizer(Preferences node) {
 131.135 +        return null;
 131.136 +    }
 131.137 +
 131.138 +    @Override
 131.139 +    public boolean appliesTo(RuleContext context) {
 131.140 +        CodeStyle codeStyle = CodeStyle.getDefault(context.doc);
 131.141 +        return codeStyle == null || codeStyle.oneImportPerLine();
 131.142 +    }
 131.143 +
 131.144 +    @Override
 131.145 +    public boolean showInTasklist() {
 131.146 +        return true;
 131.147 +    }
 131.148 +
 131.149 +    @Override
 131.150 +    public HintSeverity getDefaultSeverity() {
 131.151 +        return HintSeverity.WARNING;
 131.152 +    }
 131.153 +
 131.154 +    private static class SplitImportsFix implements PreviewableFix {
 131.155 +        private final PythonRuleContext context;
 131.156 +        private final Import imp;
 131.157 +
 131.158 +        private SplitImportsFix(PythonRuleContext context, Import imp) {
 131.159 +            this.context = context;
 131.160 +            this.imp = imp;
 131.161 +        }
 131.162 +
 131.163 +        @Override
 131.164 +        public String getDescription() {
 131.165 +            return NbBundle.getMessage(SplitImports.class, "SplitImportsFix");
 131.166 +        }
 131.167 +
 131.168 +        @Override
 131.169 +        public boolean canPreview() {
 131.170 +            return true;
 131.171 +        }
 131.172 +
 131.173 +        @Override
 131.174 +        public EditList getEditList() throws Exception {
 131.175 +            BaseDocument doc = context.doc;
 131.176 +            EditList edits = new EditList(doc);
 131.177 +
 131.178 +            OffsetRange astRange = PythonAstUtils.getRange(imp);
 131.179 +            if (astRange != OffsetRange.NONE) {
 131.180 +                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets((PythonParserResult) context.parserResult, astRange);
 131.181 +                if (lexRange != OffsetRange.NONE) {
 131.182 +                    int indent = GsfUtilities.getLineIndent(doc, lexRange.getStart());
 131.183 +                    StringBuilder sb = new StringBuilder();
 131.184 +                    List<alias> names = imp.getInternalNames();
 131.185 +                    if (names != null) {
 131.186 +                        for (alias at : names) {
 131.187 +                            if (indent > 0 && sb.length() > 0) {
 131.188 +                                sb.append(IndentUtils.createIndentString(doc, indent));
 131.189 +                            }
 131.190 +                            sb.append("import "); // NOI18N
 131.191 +                            sb.append(at.getInternalName());
 131.192 +                            if (at.getInternalAsname() != null && at.getInternalAsname().length() > 0) {
 131.193 +                                sb.append(" as "); // NOI18N
 131.194 +                                sb.append(at.getInternalAsname());
 131.195 +                            }
 131.196 +                            sb.append("\n");
 131.197 +                        }
 131.198 +                    }
 131.199 +                    // Remove the final newline since Import doesn't include it
 131.200 +                    sb.setLength(sb.length() - 1);
 131.201 +
 131.202 +                    edits.replace(lexRange.getStart(), lexRange.getLength(), sb.toString(), false, 0);
 131.203 +                }
 131.204 +            }
 131.205 +
 131.206 +            return edits;
 131.207 +        }
 131.208 +
 131.209 +        @Override
 131.210 +        public void implement() throws Exception {
 131.211 +            EditList edits = getEditList();
 131.212 +            edits.apply();
 131.213 +        }
 131.214 +
 131.215 +        @Override
 131.216 +        public boolean isSafe() {
 131.217 +            return true;
 131.218 +        }
 131.219 +
 131.220 +        @Override
 131.221 +        public boolean isInteractive() {
 131.222 +            return false;
 131.223 +        }
 131.224 +    }
 131.225 +}
   132.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   132.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/SurroundWith.java	Sun Sep 13 11:47:42 2015 +0200
   132.3 @@ -0,0 +1,377 @@
   132.4 +/*
   132.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   132.6 + *
   132.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   132.8 + *
   132.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  132.10 + * Other names may be trademarks of their respective owners.
  132.11 + *
  132.12 + * The contents of this file are subject to the terms of either the GNU
  132.13 + * General Public License Version 2 only ("GPL") or the Common
  132.14 + * Development and Distribution License("CDDL") (collectively, the
  132.15 + * "License"). You may not use this file except in compliance with the
  132.16 + * License. You can obtain a copy of the License at
  132.17 + * http://www.netbeans.org/cddl-gplv2.html
  132.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  132.19 + * specific language governing permissions and limitations under the
  132.20 + * License.  When distributing the software, include this License Header
  132.21 + * Notice in each file and include the License file at
  132.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  132.23 + * particular file as subject to the "Classpath" exception as provided
  132.24 + * by Oracle in the GPL Version 2 section of the License file that
  132.25 + * accompanied this code. If applicable, add the following below the
  132.26 + * License Header, with the fields enclosed by brackets [] replaced by
  132.27 + * your own identifying information:
  132.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  132.29 + *
  132.30 + * Contributor(s):
  132.31 + *
  132.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  132.33 + */
  132.34 +package org.netbeans.modules.python.hints;
  132.35 +
  132.36 +import java.util.ArrayList;
  132.37 +import java.util.List;
  132.38 +import java.util.prefs.Preferences;
  132.39 +import javax.swing.JComponent;
  132.40 +import javax.swing.text.JTextComponent;
  132.41 +import javax.swing.text.Position;
  132.42 +import org.netbeans.editor.BaseDocument;
  132.43 +import org.netbeans.editor.Utilities;
  132.44 +import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager;
  132.45 +import org.netbeans.modules.csl.api.EditList;
  132.46 +import org.netbeans.modules.csl.api.Hint;
  132.47 +import org.netbeans.modules.csl.api.HintFix;
  132.48 +import org.netbeans.modules.csl.api.HintSeverity;
  132.49 +import org.netbeans.modules.csl.api.OffsetRange;
  132.50 +import org.netbeans.modules.csl.api.PreviewableFix;
  132.51 +import org.netbeans.modules.csl.api.RuleContext;
  132.52 +import org.netbeans.modules.csl.spi.GsfUtilities;
  132.53 +import org.netbeans.modules.editor.indent.api.IndentUtils;
  132.54 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  132.55 +import org.openide.util.Exceptions;
  132.56 +import org.openide.util.NbBundle;
  132.57 +import org.python.antlr.PythonTree;
  132.58 +import org.python.antlr.Visitor;
  132.59 +import org.python.antlr.ast.ClassDef;
  132.60 +import org.python.antlr.ast.FunctionDef;
  132.61 +import org.python.antlr.ast.Import;
  132.62 +import org.python.antlr.ast.ImportFrom;
  132.63 +
  132.64 +/**
  132.65 + * Offer to surround code with for example try/except/finally
  132.66 + *
  132.67 + * @author Tor Norbye
  132.68 + */
  132.69 +public class SurroundWith extends PythonSelectionRule {
  132.70 +    @Override
  132.71 +    protected int getApplicability(PythonRuleContext context, PythonTree root, OffsetRange astRange) {
  132.72 +        if (!ApplicabilityVisitor.applies(root, astRange)) {
  132.73 +            return 0;
  132.74 +        }
  132.75 +
  132.76 +        return 1;
  132.77 +    }
  132.78 +
  132.79 +    @Override
  132.80 +    public void run(PythonRuleContext context, List<Hint> result, OffsetRange range, int applicability) {
  132.81 +        int start = range.getStart();
  132.82 +        int end = range.getEnd();
  132.83 +
  132.84 +        // Adjust the fix range to be right around the dot so that the light bulb ends up
  132.85 +        // on the same line as the caret and alt-enter works
  132.86 +        JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
  132.87 +        if (target != null) {
  132.88 +            int dot = target.getCaret().getDot();
  132.89 +            range = new OffsetRange(dot, dot);
  132.90 +        }
  132.91 +
  132.92 +        List<HintFix> fixList = new ArrayList<>(3);
  132.93 +        fixList.add(new SurroundWithFix(context, start, end, false, true));
  132.94 +        fixList.add(new SurroundWithFix(context, start, end, true, true));
  132.95 +        fixList.add(new SurroundWithFix(context, start, end, true, false));
  132.96 +        String displayName = getDisplayName();
  132.97 +        Hint desc = new Hint(this, displayName, context.parserResult.getSnapshot().getSource().getFileObject(),
  132.98 +                range, fixList, 1500);
  132.99 +        result.add(desc);
 132.100 +    }
 132.101 +
 132.102 +    @Override
 132.103 +    public boolean appliesTo(RuleContext context) {
 132.104 +        return true;
 132.105 +    }
 132.106 +
 132.107 +    @Override
 132.108 +    public String getDisplayName() {
 132.109 +        return NbBundle.getMessage(SurroundWith.class, "SurroundWith");
 132.110 +    }
 132.111 +
 132.112 +    @Override
 132.113 +    public boolean showInTasklist() {
 132.114 +        return false;
 132.115 +    }
 132.116 +
 132.117 +    @Override
 132.118 +    public HintSeverity getDefaultSeverity() {
 132.119 +        return HintSeverity.CURRENT_LINE_WARNING;
 132.120 +    }
 132.121 +
 132.122 +    @Override
 132.123 +    public String getId() {
 132.124 +        return "SurroundWith"; // NOI18N
 132.125 +    }
 132.126 +
 132.127 +    @Override
 132.128 +    public String getDescription() {
 132.129 +        return "";
 132.130 +    }
 132.131 +
 132.132 +    @Override
 132.133 +    public boolean getDefaultEnabled() {
 132.134 +        return true;
 132.135 +    }
 132.136 +
 132.137 +    @Override
 132.138 +    public JComponent getCustomizer(Preferences node) {
 132.139 +        return null;
 132.140 +    }
 132.141 +
 132.142 +    private static class SurroundWithFix implements PreviewableFix {
 132.143 +        private final PythonRuleContext context;
 132.144 +        private final boolean includeFinally;
 132.145 +        private final boolean includeExcept;
 132.146 +        private Position startPos;
 132.147 +        private Position endPos;
 132.148 +        private Position codeTemplatePos;
 132.149 +        private String codeTemplateText;
 132.150 +        private final int start;
 132.151 +        private final int end;
 132.152 +
 132.153 +        private SurroundWithFix(PythonRuleContext context,
 132.154 +                int start, int end,
 132.155 +                boolean includeFinally, boolean includeExcept) {
 132.156 +            assert includeExcept || includeFinally;
 132.157 +
 132.158 +            this.context = context;
 132.159 +
 132.160 +            OffsetRange range = PythonLexerUtils.narrow(context.doc, new OffsetRange(start, end), false);
 132.161 +            this.start = range.getStart();
 132.162 +            this.end = range.getEnd();
 132.163 +            this.includeFinally = includeFinally;
 132.164 +            this.includeExcept = includeExcept;
 132.165 +        }
 132.166 +
 132.167 +        @Override
 132.168 +        public String getDescription() {
 132.169 +            if (includeExcept && includeFinally) {
 132.170 +                return NbBundle.getMessage(CreateDocString.class, "SurroundWithTEF");
 132.171 +            } else if (includeExcept) {
 132.172 +                return NbBundle.getMessage(CreateDocString.class, "SurroundWithTE");
 132.173 +            } else {
 132.174 +                assert includeFinally;
 132.175 +                return NbBundle.getMessage(CreateDocString.class, "SurroundWithTF");
 132.176 +            }
 132.177 +        }
 132.178 +
 132.179 +        @Override
 132.180 +        public boolean canPreview() {
 132.181 +            return true;
 132.182 +        }
 132.183 +
 132.184 +        @Override
 132.185 +        public EditList getEditList() throws Exception {
 132.186 +            return getEditList(true);
 132.187 +        }
 132.188 +
 132.189 +        private EditList getEditList(boolean previewOnly) throws Exception {
 132.190 +            BaseDocument doc = context.doc;
 132.191 +            EditList edits = new EditList(doc);
 132.192 +
 132.193 +            int indentSize = IndentUtils.indentLevelSize(doc);
 132.194 +            String oneIndent = IndentUtils.createIndentString(doc, indentSize);
 132.195 +            //int initialIndent = GsfUtilities.getLineIndent(doc, start);
 132.196 +            int lineStart = Utilities.getRowStart(doc, start);
 132.197 +            String initialIndentStr = IndentUtils.createIndentString(doc, IndentUtils.lineIndent(doc, lineStart));
 132.198 +            int nextLine = Utilities.getRowEnd(doc, end) + 1;
 132.199 +            if (nextLine > doc.getLength()) {
 132.200 +                nextLine = doc.getLength();
 132.201 +                edits.replace(nextLine, 0, "\n", false, 1);
 132.202 +            }
 132.203 +
 132.204 +            // Indent the selected lines
 132.205 +            edits.replace(lineStart, 0, initialIndentStr + "try:\n", false, 1);
 132.206 +            for (int offset = start; offset < end; offset = Utilities.getRowEnd(doc, offset) + 1) {
 132.207 +                edits.replace(offset, 0, oneIndent, false, 1);
 132.208 +            }
 132.209 +
 132.210 +            StringBuilder sb = new StringBuilder();
 132.211 +            if (includeExcept) {
 132.212 +                sb.append(initialIndentStr);
 132.213 +                sb.append("except ");
 132.214 +                if (!previewOnly) {
 132.215 +                    sb.append("${except default=\"");
 132.216 +                }
 132.217 +                sb.append("Exception, e");
 132.218 +                if (!previewOnly) {
 132.219 +                    sb.append("\"}");
 132.220 +                }
 132.221 +                sb.append(":\n");
 132.222 +                sb.append(initialIndentStr);
 132.223 +                sb.append(oneIndent);
 132.224 +                int caretDelta = sb.length();
 132.225 +                startPos = edits.createPosition(nextLine + caretDelta);
 132.226 +                if (!previewOnly) {
 132.227 +                    sb.append("${action default=\"");
 132.228 +                }
 132.229 +                sb.append("print \"Exception: \", e");
 132.230 +                if (!previewOnly) {
 132.231 +                    sb.append("\"}");
 132.232 +                }
 132.233 +                caretDelta = sb.length();
 132.234 +                endPos = edits.createPosition(nextLine + caretDelta);
 132.235 +                sb.append("\n");
 132.236 +                if (!previewOnly && !includeExcept) {
 132.237 +                    sb.append("${cursor}");
 132.238 +                }
 132.239 +            }
 132.240 +            if (includeFinally) {
 132.241 +                sb.append(initialIndentStr);
 132.242 +                sb.append("finally:\n");
 132.243 +                sb.append(initialIndentStr);
 132.244 +                sb.append(oneIndent);
 132.245 +                if (!previewOnly) {
 132.246 +                    sb.append("${finally default=\"\"}\n${cursor}");
 132.247 +                }
 132.248 +                int caretDelta = sb.length();
 132.249 +                if (!includeExcept) {
 132.250 +                    endPos = startPos = edits.createPosition(nextLine + caretDelta);
 132.251 +                }
 132.252 +                sb.append("\n");
 132.253 +            }
 132.254 +            if (previewOnly) {
 132.255 +                edits.replace(nextLine, 0, sb.toString(), false, 1);
 132.256 +            } else {
 132.257 +                codeTemplatePos = edits.createPosition(nextLine, Position.Bias.Backward);
 132.258 +                codeTemplateText = sb.toString();
 132.259 +            }
 132.260 +
 132.261 +            return edits;
 132.262 +        }
 132.263 +
 132.264 +        @Override
 132.265 +        public void implement() throws Exception {
 132.266 +            EditList edits = getEditList(true);
 132.267 +
 132.268 +            JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
 132.269 +            edits.apply();
 132.270 +            if (target != null) {
 132.271 +                if (codeTemplateText != null && codeTemplatePos != null) {
 132.272 +                    final CodeTemplateManager ctm = CodeTemplateManager.get(context.doc);
 132.273 +                    if (ctm != null) {
 132.274 +                        target.getCaret().setDot(codeTemplatePos.getOffset());
 132.275 +                        ctm.createTemporary(codeTemplateText).insert(target);
 132.276 +                    }
 132.277 +                } else if (startPos != null && endPos != null) {
 132.278 +                    target.setSelectionStart(startPos.getOffset());
 132.279 +                    target.setSelectionEnd(endPos.getOffset());
 132.280 +                }
 132.281 +            }
 132.282 +        }
 132.283 +
 132.284 +        @Override
 132.285 +        public boolean isSafe() {
 132.286 +            return true;
 132.287 +        }
 132.288 +
 132.289 +        @Override
 132.290 +        public boolean isInteractive() {
 132.291 +            return false;
 132.292 +        }
 132.293 +    }
 132.294 +
 132.295 +    /** @todo Prune search in traverse, ala AstPath.
 132.296 +     *  @todo Build up start and end AstPaths.
 132.297 +     */
 132.298 +    private static class ApplicabilityVisitor extends Visitor {
 132.299 +        private boolean applies = true;
 132.300 +        private final int start;
 132.301 +        private final int end;
 132.302 +
 132.303 +        static boolean applies(PythonTree root, OffsetRange astRange) {
 132.304 +            ApplicabilityVisitor visitor = new ApplicabilityVisitor(astRange);
 132.305 +            try {
 132.306 +                visitor.visit(root);
 132.307 +            } catch (Exception ex) {
 132.308 +                Exceptions.printStackTrace(ex);
 132.309 +                return false;
 132.310 +            }
 132.311 +            return visitor.isApplicable();
 132.312 +        }
 132.313 +
 132.314 +        ApplicabilityVisitor(OffsetRange astRange) {
 132.315 +            this.start = astRange.getStart();
 132.316 +            this.end = astRange.getEnd();
 132.317 +        }
 132.318 +
 132.319 +        public boolean isApplicable() {
 132.320 +            return applies;
 132.321 +        }
 132.322 +
 132.323 +        private void maybeBail(PythonTree node) {
 132.324 +            int nodeStart = node.getCharStartIndex();
 132.325 +            int nodeEnd = node.getCharStopIndex();
 132.326 +            if (nodeStart >= start && nodeStart < end) {
 132.327 +                applies = false;
 132.328 +            }
 132.329 +            if (nodeEnd > start && nodeEnd < end) {
 132.330 +                applies = false;
 132.331 +            }
 132.332 +        }
 132.333 +
 132.334 +        @Override
 132.335 +        public void traverse(PythonTree node) throws Exception {
 132.336 +            if (!applies) {
 132.337 +                return;
 132.338 +            }
 132.339 +
 132.340 +            int nodeStart = node.getCharStartIndex();
 132.341 +            int nodeStop = node.getCharStopIndex();
 132.342 +            //if (!(nodeStop < start || nodeStart > end)) {
 132.343 +            if (nodeStop >= start && nodeStart <= end) {
 132.344 +                super.traverse(node);
 132.345 +            }
 132.346 +        }
 132.347 +
 132.348 +        @Override
 132.349 +        public Object visitClassDef(ClassDef node) throws Exception {
 132.350 +            maybeBail(node);
 132.351 +            return super.visitClassDef(node);
 132.352 +        }
 132.353 +
 132.354 +        @Override
 132.355 +        public Object visitFunctionDef(FunctionDef node) throws Exception {
 132.356 +            maybeBail(node);
 132.357 +            return super.visitFunctionDef(node);
 132.358 +        }
 132.359 +
 132.360 +        @Override
 132.361 +        public Object visitImport(Import node) throws Exception {
 132.362 +            maybeBail(node);
 132.363 +            return super.visitImport(node);
 132.364 +        }
 132.365 +
 132.366 +        @Override
 132.367 +        public Object visitImportFrom(ImportFrom node) throws Exception {
 132.368 +            maybeBail(node);
 132.369 +            return super.visitImportFrom(node);
 132.370 +        }
 132.371 +
 132.372 +        // Module is okay - you get this when you select all text in a simple "script" file
 132.373 +        // with only statements
 132.374 +        //@Override
 132.375 +        //public Object visitModule(Module node) throws Exception {
 132.376 +        //    maybeBail(node);
 132.377 +        //    return super.visitModule(node);
 132.378 +        //}
 132.379 +    }
 132.380 +}
   133.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   133.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/UnresolvedClassComponents.java	Sun Sep 13 11:47:42 2015 +0200
   133.3 @@ -0,0 +1,207 @@
   133.4 +/*
   133.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   133.6 + *
   133.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   133.8 + *
   133.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  133.10 + * Other names may be trademarks of their respective owners.
  133.11 + *
  133.12 + * The contents of this file are subject to the terms of either the GNU
  133.13 + * General Public License Version 2 only ("GPL") or the Common
  133.14 + * Development and Distribution License("CDDL") (collectively, the
  133.15 + * "License"). You may not use this file except in compliance with the
  133.16 + * License. You can obtain a copy of the License at
  133.17 + * http://www.netbeans.org/cddl-gplv2.html
  133.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  133.19 + * specific language governing permissions and limitations under the
  133.20 + * License.  When distributing the software, include this License Header
  133.21 + * Notice in each file and include the License file at
  133.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  133.23 + * particular file as subject to the "Classpath" exception as provided
  133.24 + * by Oracle in the GPL Version 2 section of the License file that
  133.25 + * accompanied this code. If applicable, add the following below the
  133.26 + * License Header, with the fields enclosed by brackets [] replaced by
  133.27 + * your own identifying information:
  133.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  133.29 + *
  133.30 + * If you wish your version of this file to be governed by only the CDDL
  133.31 + * or only the GPL Version 2, indicate your decision by adding
  133.32 + * "[Contributor] elects to include this software in this distribution
  133.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  133.34 + * single choice of license, a recipient has the option to distribute
  133.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  133.36 + * to extend the choice of license to its licensees as provided above.
  133.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  133.38 + * Version 2 license, then the option applies only if the new code is
  133.39 + * made subject to such option by the copyright holder.
  133.40 + *
  133.41 + * Contributor(s):
  133.42 + *
  133.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  133.44 + */
  133.45 +package org.netbeans.modules.python.hints;
  133.46 +
  133.47 +import java.util.Collections;
  133.48 +import java.util.List;
  133.49 +import java.util.Set;
  133.50 +import java.util.prefs.Preferences;
  133.51 +import javax.swing.JComponent;
  133.52 +import org.netbeans.modules.csl.api.Hint;
  133.53 +import org.netbeans.modules.csl.api.HintFix;
  133.54 +import org.netbeans.modules.csl.api.HintSeverity;
  133.55 +import org.netbeans.modules.csl.api.OffsetRange;
  133.56 +import org.netbeans.modules.csl.api.RuleContext;
  133.57 +import org.netbeans.modules.python.source.PythonAstUtils;
  133.58 +import org.netbeans.modules.python.source.PythonParserResult;
  133.59 +import org.netbeans.modules.python.source.ImportManager;
  133.60 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  133.61 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  133.62 +import org.openide.util.NbBundle;
  133.63 +import org.python.antlr.PythonTree;
  133.64 +import org.python.antlr.ast.Module;
  133.65 +
  133.66 +/**
  133.67 + * Detect Unresolved class attributes
  133.68 + *
  133.69 + * @author Jean-Yves Mengant
  133.70 + */
  133.71 +public class UnresolvedClassComponents extends PythonAstRule {
  133.72 +
  133.73 +    private final static String CLASS_UNRESOLVED_ATTRIBUTES = "UnresolvedAttributes";
  133.74 +    private final static String CLASS_UNRESOLVED_INHERITANCE_VAR = "UnresolvedInheritanceVariable";
  133.75 +    private final static String CLASS_UNRESOLVED_ATTRIBUTES_VAR = "UnresolvedAttributesVariable";
  133.76 +    private final static String CLASS_UNRESOLVED_ATTRIBUTES_DESC = "UnresolvedAttributesDesc";
  133.77 +
  133.78 +
  133.79 +
  133.80 +    public UnresolvedClassComponents() {
  133.81 +    }
  133.82 +
  133.83 +    @Override
  133.84 +    public boolean appliesTo(RuleContext context) {
  133.85 +        return true;
  133.86 +    }
  133.87 +
  133.88 +    @Override
  133.89 +    public Set<Class> getKinds() {
  133.90 +        return Collections.<Class>singleton(Module.class);
  133.91 +    }
  133.92 +
  133.93 +    private void populateMessages( PythonParserResult info, List<PythonTree> unresolved , List<Hint> result ,boolean isClass ) {
  133.94 +        if (unresolved.size() > 0) {
  133.95 +
  133.96 +            for (PythonTree node : unresolved) {
  133.97 +                // Compute suggestions
  133.98 +                String name = PythonAstUtils.getName(node);
  133.99 +                if (name == null) {
 133.100 +                    name = "";
 133.101 +                }
 133.102 +                List<HintFix> fixList = Collections.emptyList();
 133.103 +                String message ;
 133.104 +                if ( isClass)
 133.105 +                  message = NbBundle.getMessage(NameRule.class, CLASS_UNRESOLVED_INHERITANCE_VAR, name);
 133.106 +                else
 133.107 +                  message = NbBundle.getMessage(NameRule.class, CLASS_UNRESOLVED_ATTRIBUTES_VAR, name);
 133.108 +                OffsetRange range = PythonAstUtils.getRange( node);
 133.109 +                range = PythonLexerUtils.getLexerOffsets(info, range);
 133.110 +                if (range != OffsetRange.NONE) {
 133.111 +                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
 133.112 +                    result.add(desc);
 133.113 +                }
 133.114 +            }
 133.115 +        }
 133.116 +    }
 133.117 +
 133.118 +
 133.119 +    @Override
 133.120 +    public void run(PythonRuleContext context, List<Hint> result) {
 133.121 +        PythonParserResult info = (PythonParserResult) context.parserResult;
 133.122 +        SymbolTable symbolTable = info.getSymbolTable();
 133.123 +
 133.124 +        List<PythonTree> unresolvedAttributes = symbolTable.getUnresolvedAttributes(info);
 133.125 +        populateMessages(info,unresolvedAttributes,result,false) ;
 133.126 +        List<PythonTree> unresolvedParents = symbolTable.getUnresolvedParents(info);
 133.127 +        populateMessages(info,unresolvedParents,result,true) ;
 133.128 +    }
 133.129 +
 133.130 +    @Override
 133.131 +    public String getId() {
 133.132 +        return CLASS_UNRESOLVED_ATTRIBUTES; // NOI18N
 133.133 +    }
 133.134 +
 133.135 +    @Override
 133.136 +    public String getDisplayName() {
 133.137 +        return NbBundle.getMessage(NameRule.class, CLASS_UNRESOLVED_ATTRIBUTES);
 133.138 +    }
 133.139 +
 133.140 +    @Override
 133.141 +    public String getDescription() {
 133.142 +        return NbBundle.getMessage(NameRule.class, CLASS_UNRESOLVED_ATTRIBUTES_DESC);
 133.143 +    }
 133.144 +
 133.145 +    @Override
 133.146 +    public boolean getDefaultEnabled() {
 133.147 +        return false;
 133.148 +    }
 133.149 +
 133.150 +    @Override
 133.151 +    public boolean showInTasklist() {
 133.152 +        return true;
 133.153 +    }
 133.154 +
 133.155 +    @Override
 133.156 +    public HintSeverity getDefaultSeverity() {
 133.157 +        return HintSeverity.ERROR;
 133.158 +    }
 133.159 +
 133.160 +    @Override
 133.161 +    public JComponent getCustomizer(Preferences node) {
 133.162 +        return null;
 133.163 +    }
 133.164 +
 133.165 +    private static class ImportFix implements HintFix {
 133.166 +        private final PythonRuleContext context;
 133.167 +        private final PythonTree node;
 133.168 +        private final String module;
 133.169 +
 133.170 +        private ImportFix(PythonRuleContext context, PythonTree node, String module) {
 133.171 +            this.context = context;
 133.172 +            this.node = node;
 133.173 +            this.module = module;
 133.174 +        }
 133.175 +
 133.176 +        @Override
 133.177 +        public String getDescription() {
 133.178 +            return NbBundle.getMessage(CreateDocString.class, "FixImport", module);
 133.179 +        }
 133.180 +
 133.181 +        @Override
 133.182 +        public void implement() throws Exception {
 133.183 +            String mod = this.module;
 133.184 +            String symbol = null;
 133.185 +            int colon = mod.indexOf(':');
 133.186 +            if (colon != -1) {
 133.187 +                int end = mod.indexOf('(', colon + 1);
 133.188 +                if (end == -1) {
 133.189 +                    end = mod.indexOf(';', colon + 1);
 133.190 +                    if (end == -1) {
 133.191 +                        end = mod.length();
 133.192 +                    }
 133.193 +                }
 133.194 +                symbol = mod.substring(colon + 1, end).trim();
 133.195 +                mod = mod.substring(0, colon).trim();
 133.196 +            }
 133.197 +            new ImportManager((PythonParserResult) context.parserResult).ensureImported(mod, symbol, false, false, true);
 133.198 +        }
 133.199 +
 133.200 +        @Override
 133.201 +        public boolean isSafe() {
 133.202 +            return true;
 133.203 +        }
 133.204 +
 133.205 +        @Override
 133.206 +        public boolean isInteractive() {
 133.207 +            return false;
 133.208 +        }
 133.209 +    }
 133.210 +}
   134.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   134.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/UnresolvedDetector.java	Sun Sep 13 11:47:42 2015 +0200
   134.3 @@ -0,0 +1,227 @@
   134.4 +/*
   134.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   134.6 + *
   134.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   134.8 + *
   134.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  134.10 + * Other names may be trademarks of their respective owners.
  134.11 + *
  134.12 + * The contents of this file are subject to the terms of either the GNU
  134.13 + * General Public License Version 2 only ("GPL") or the Common
  134.14 + * Development and Distribution License("CDDL") (collectively, the
  134.15 + * "License"). You may not use this file except in compliance with the
  134.16 + * License. You can obtain a copy of the License at
  134.17 + * http://www.netbeans.org/cddl-gplv2.html
  134.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  134.19 + * specific language governing permissions and limitations under the
  134.20 + * License.  When distributing the software, include this License Header
  134.21 + * Notice in each file and include the License file at
  134.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  134.23 + * particular file as subject to the "Classpath" exception as provided
  134.24 + * by Oracle in the GPL Version 2 section of the License file that
  134.25 + * accompanied this code. If applicable, add the following below the
  134.26 + * License Header, with the fields enclosed by brackets [] replaced by
  134.27 + * your own identifying information:
  134.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  134.29 + *
  134.30 + * If you wish your version of this file to be governed by only the CDDL
  134.31 + * or only the GPL Version 2, indicate your decision by adding
  134.32 + * "[Contributor] elects to include this software in this distribution
  134.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  134.34 + * single choice of license, a recipient has the option to distribute
  134.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  134.36 + * to extend the choice of license to its licensees as provided above.
  134.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  134.38 + * Version 2 license, then the option applies only if the new code is
  134.39 + * made subject to such option by the copyright holder.
  134.40 + *
  134.41 + * Contributor(s):
  134.42 + *
  134.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  134.44 + */
  134.45 +package org.netbeans.modules.python.hints;
  134.46 +
  134.47 +import java.util.ArrayList;
  134.48 +import java.util.Collections;
  134.49 +import java.util.List;
  134.50 +import java.util.Set;
  134.51 +import java.util.prefs.Preferences;
  134.52 +import javax.swing.JComponent;
  134.53 +import org.netbeans.modules.csl.api.Hint;
  134.54 +import org.netbeans.modules.csl.api.HintFix;
  134.55 +import org.netbeans.modules.csl.api.HintSeverity;
  134.56 +import org.netbeans.modules.csl.api.OffsetRange;
  134.57 +import org.netbeans.modules.csl.api.RuleContext;
  134.58 +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
  134.59 +import org.netbeans.modules.python.source.PythonAstUtils;
  134.60 +import org.netbeans.modules.python.source.PythonIndex;
  134.61 +import org.netbeans.modules.python.source.PythonParserResult;
  134.62 +import org.netbeans.modules.python.source.elements.IndexedElement;
  134.63 +import org.netbeans.modules.python.source.ImportManager;
  134.64 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  134.65 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  134.66 +import org.openide.util.NbBundle;
  134.67 +import org.python.antlr.PythonTree;
  134.68 +import org.python.antlr.ast.Attribute;
  134.69 +import org.python.antlr.ast.Call;
  134.70 +import org.python.antlr.ast.Module;
  134.71 +
  134.72 +/**
  134.73 + * Detect Unresolved variables
  134.74 + *
  134.75 + * @author Tor Norbye
  134.76 + */
  134.77 +public class UnresolvedDetector extends PythonAstRule {
  134.78 +    public UnresolvedDetector() {
  134.79 +    }
  134.80 +
  134.81 +    @Override
  134.82 +    public boolean appliesTo(RuleContext context) {
  134.83 +        return true;
  134.84 +    }
  134.85 +
  134.86 +    @Override
  134.87 +    public Set<Class> getKinds() {
  134.88 +        return Collections.<Class>singleton(Module.class);
  134.89 +    }
  134.90 +
  134.91 +    @Override
  134.92 +    public void run(PythonRuleContext context, List<Hint> result) {
  134.93 +        PythonParserResult info = (PythonParserResult) context.parserResult;
  134.94 +        SymbolTable symbolTable = info.getSymbolTable();
  134.95 +
  134.96 +        List<PythonTree> unresolvedNames = symbolTable.getUnresolved(info);
  134.97 +        if (unresolvedNames.size() > 0) {
  134.98 +            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
  134.99 +
 134.100 +            for (PythonTree node : unresolvedNames) {
 134.101 +                // Compute suggestions
 134.102 +                String name = PythonAstUtils.getName(node);
 134.103 +                if (name == null) {
 134.104 +                    name = "";
 134.105 +                }
 134.106 +                List<HintFix> fixList = new ArrayList<>(3);
 134.107 +                // Is is a reference to a module?
 134.108 +                boolean tryModule = false;
 134.109 +                if (node.getParent() instanceof Call) {
 134.110 +                    Call call = (Call)node.getParent();
 134.111 +                    PythonTree t = call.getInternalFunc();
 134.112 +                    if (t instanceof Attribute) {
 134.113 +                        tryModule = true;
 134.114 +                    }
 134.115 +                }
 134.116 +                String message = NbBundle.getMessage(NameRule.class, "UnresolvedVariable", name);
 134.117 +                if (name.equals("true")) { // NOI18N
 134.118 +                    // Help for new language converts...
 134.119 +                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "True"); // NOI18N
 134.120 +                } else if (name.equals("false")) {
 134.121 +                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "False"); // NOI18N
 134.122 +                } else if (name.equals("nil") || name.equals("null")) {
 134.123 +                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "None"); // NOI18N
 134.124 +                } else if (name.equals("this")) {
 134.125 +                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "self"); // NOI18N
 134.126 +                } else if (tryModule) {
 134.127 +                    Set<IndexedElement> moduleElements = index.getModules(name, QuerySupport.Kind.EXACT);
 134.128 +                    if (moduleElements.size() > 0) {
 134.129 +                        fixList.add(new ImportFix(context, node, name));
 134.130 +                    }
 134.131 +                } else {
 134.132 +                    Set<String> modules = index.getImportsFor(name, true);
 134.133 +                    if (modules.size() > 0) {
 134.134 +                        for (String module : modules) {
 134.135 +                            fixList.add(new ImportFix(context, node, module));
 134.136 +                        }
 134.137 +                    }
 134.138 +                }
 134.139 +
 134.140 +                OffsetRange range = PythonAstUtils.getNameRange(info, node);
 134.141 +                range = PythonLexerUtils.getLexerOffsets(info, range);
 134.142 +                if (range != OffsetRange.NONE) {
 134.143 +                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
 134.144 +                    result.add(desc);
 134.145 +                }
 134.146 +            }
 134.147 +        }
 134.148 +    }
 134.149 +
 134.150 +    @Override
 134.151 +    public String getId() {
 134.152 +        return "Unresolved"; // NOI18N
 134.153 +    }
 134.154 +
 134.155 +    @Override
 134.156 +    public String getDisplayName() {
 134.157 +        return NbBundle.getMessage(NameRule.class, "Unresolved");
 134.158 +    }
 134.159 +
 134.160 +    @Override
 134.161 +    public String getDescription() {
 134.162 +        return NbBundle.getMessage(NameRule.class, "UnresolvedDesc");
 134.163 +    }
 134.164 +
 134.165 +    @Override
 134.166 +    public boolean getDefaultEnabled() {
 134.167 +        return false;
 134.168 +    }
 134.169 +
 134.170 +    @Override
 134.171 +    public boolean showInTasklist() {
 134.172 +        return true;
 134.173 +    }
 134.174 +
 134.175 +    @Override
 134.176 +    public HintSeverity getDefaultSeverity() {
 134.177 +        return HintSeverity.ERROR;
 134.178 +    }
 134.179 +
 134.180 +    @Override
 134.181 +    public JComponent getCustomizer(Preferences node) {
 134.182 +        return null;
 134.183 +    }
 134.184 +
 134.185 +    private static class ImportFix implements HintFix {
 134.186 +        private final PythonRuleContext context;
 134.187 +        private final PythonTree node;
 134.188 +        private final String module;
 134.189 +
 134.190 +        private ImportFix(PythonRuleContext context, PythonTree node, String module) {
 134.191 +            this.context = context;
 134.192 +            this.node = node;
 134.193 +            this.module = module;
 134.194 +        }
 134.195 +
 134.196 +        @Override
 134.197 +        public String getDescription() {
 134.198 +            return NbBundle.getMessage(CreateDocString.class, "FixImport", module);
 134.199 +        }
 134.200 +
 134.201 +        @Override
 134.202 +        public void implement() throws Exception {
 134.203 +            String mod = this.module;
 134.204 +            String symbol = null;
 134.205 +            int colon = mod.indexOf(':');
 134.206 +            if (colon != -1) {
 134.207 +                int end = mod.indexOf('(', colon + 1);
 134.208 +                if (end == -1) {
 134.209 +                    end = mod.indexOf(';', colon + 1);
 134.210 +                    if (end == -1) {
 134.211 +                        end = mod.length();
 134.212 +                    }
 134.213 +                }
 134.214 +                symbol = mod.substring(colon + 1, end).trim();
 134.215 +                mod = mod.substring(0, colon).trim();
 134.216 +            }
 134.217 +            new ImportManager((PythonParserResult) context.parserResult).ensureImported(mod, symbol, false, false, true);
 134.218 +        }
 134.219 +
 134.220 +        @Override
 134.221 +        public boolean isSafe() {
 134.222 +            return true;
 134.223 +        }
 134.224 +
 134.225 +        @Override
 134.226 +        public boolean isInteractive() {
 134.227 +            return false;
 134.228 +        }
 134.229 +    }
 134.230 +}
   135.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   135.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/UnusedDetector.java	Sun Sep 13 11:47:42 2015 +0200
   135.3 @@ -0,0 +1,244 @@
   135.4 +/*
   135.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   135.6 + *
   135.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   135.8 + *
   135.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  135.10 + * Other names may be trademarks of their respective owners.
  135.11 + *
  135.12 + * The contents of this file are subject to the terms of either the GNU
  135.13 + * General Public License Version 2 only ("GPL") or the Common
  135.14 + * Development and Distribution License("CDDL") (collectively, the
  135.15 + * "License"). You may not use this file except in compliance with the
  135.16 + * License. You can obtain a copy of the License at
  135.17 + * http://www.netbeans.org/cddl-gplv2.html
  135.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  135.19 + * specific language governing permissions and limitations under the
  135.20 + * License.  When distributing the software, include this License Header
  135.21 + * Notice in each file and include the License file at
  135.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  135.23 + * particular file as subject to the "Classpath" exception as provided
  135.24 + * by Oracle in the GPL Version 2 section of the License file that
  135.25 + * accompanied this code. If applicable, add the following below the
  135.26 + * License Header, with the fields enclosed by brackets [] replaced by
  135.27 + * your own identifying information:
  135.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  135.29 + *
  135.30 + * If you wish your version of this file to be governed by only the CDDL
  135.31 + * or only the GPL Version 2, indicate your decision by adding
  135.32 + * "[Contributor] elects to include this software in this distribution
  135.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  135.34 + * single choice of license, a recipient has the option to distribute
  135.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  135.36 + * to extend the choice of license to its licensees as provided above.
  135.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  135.38 + * Version 2 license, then the option applies only if the new code is
  135.39 + * made subject to such option by the copyright holder.
  135.40 + *
  135.41 + * Contributor(s):
  135.42 + *
  135.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  135.44 + */
  135.45 +package org.netbeans.modules.python.hints;
  135.46 +
  135.47 +import java.util.ArrayList;
  135.48 +import java.util.Collections;
  135.49 +import java.util.HashSet;
  135.50 +import java.util.List;
  135.51 +import java.util.Set;
  135.52 +import java.util.prefs.Preferences;
  135.53 +import javax.swing.JComponent;
  135.54 +import org.netbeans.modules.csl.api.Hint;
  135.55 +import org.netbeans.modules.csl.api.HintFix;
  135.56 +import org.netbeans.modules.csl.api.HintSeverity;
  135.57 +import org.netbeans.modules.csl.api.OffsetRange;
  135.58 +import org.netbeans.modules.csl.api.RuleContext;
  135.59 +import org.netbeans.modules.python.source.PythonAstUtils;
  135.60 +import org.netbeans.modules.python.source.PythonParserResult;
  135.61 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  135.62 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  135.63 +import org.openide.util.NbBundle;
  135.64 +import org.python.antlr.PythonTree;
  135.65 +import org.python.antlr.ast.Assign;
  135.66 +import org.python.antlr.ast.For;
  135.67 +import org.python.antlr.ast.Module;
  135.68 +import org.python.antlr.ast.Tuple;
  135.69 +import org.python.antlr.base.expr;
  135.70 +
  135.71 +/**
  135.72 + * Detect unused variables
  135.73 + *
  135.74 + * @todo Find a more reliable way of detecting return tuples without relying on the
  135.75 + *  parent reference
  135.76 + *
  135.77 + * @author Tor Norbye
  135.78 + */
  135.79 +public class UnusedDetector extends PythonAstRule {
  135.80 +    /** Default names ignored */
  135.81 +    private static final String DEFAULT_IGNORED_NAMES = "_, dummy";
  135.82 +    private static final String PARAMS_KEY = "params"; // NOI18N
  135.83 +    private static final String SKIP_TUPLE_ASSIGN_KEY = "skipTuples"; // NOI18N
  135.84 +    private static final String IGNORED_KEY = "ignorednames"; // NOI18N
  135.85 +
  135.86 +    public UnusedDetector() {
  135.87 +    }
  135.88 +
  135.89 +    @Override
  135.90 +    public boolean appliesTo(RuleContext context) {
  135.91 +        return true;
  135.92 +    }
  135.93 +
  135.94 +    @Override
  135.95 +    public Set<Class> getKinds() {
  135.96 +        return Collections.<Class>singleton(Module.class);
  135.97 +    }
  135.98 +
  135.99 +    @Override
 135.100 +    public void run(PythonRuleContext context, List<Hint> result) {
 135.101 +        PythonParserResult info = (PythonParserResult) context.parserResult;
 135.102 +        SymbolTable symbolTable = info.getSymbolTable();
 135.103 +
 135.104 +        boolean skipParams = true;
 135.105 +        Preferences pref = context.manager.getPreferences(this);
 135.106 +        if (pref != null) {
 135.107 +            skipParams = getSkipParameters(pref);
 135.108 +        }
 135.109 +
 135.110 +        List<PythonTree> unusedNames = symbolTable.getUnused(true, skipParams);
 135.111 +        if (unusedNames.size() == 0) {
 135.112 +            return;
 135.113 +        }
 135.114 +
 135.115 +        boolean skipTupleAssigns = true;
 135.116 +        Set<String> ignoreNames = Collections.emptySet();
 135.117 +        if (pref != null) {
 135.118 +            skipParams = getSkipParameters(pref);
 135.119 +            skipTupleAssigns = getSkipTupleAssignments(pref);
 135.120 +            String ignoreNamesStr = getIgnoreNames(pref);
 135.121 +            if (ignoreNamesStr.length() > 0) {
 135.122 +                ignoreNames = new HashSet<>();
 135.123 +                for (String s : ignoreNamesStr.split(",")) { // NOI18N
 135.124 +                    ignoreNames.add(s.trim());
 135.125 +                }
 135.126 +            }
 135.127 +        }
 135.128 +
 135.129 +        for (PythonTree node : unusedNames) {
 135.130 +            if (skipTupleAssigns && isTupleAssignment(node)) {
 135.131 +                continue;
 135.132 +            }
 135.133 +            String name = PythonAstUtils.getName(node);
 135.134 +            if (name == null) {
 135.135 +                name = "";
 135.136 +            }
 135.137 +            if (ignoreNames.contains(name)) {
 135.138 +                continue;
 135.139 +            }
 135.140 +            OffsetRange range = PythonAstUtils.getNameRange(info, node);
 135.141 +            range = PythonLexerUtils.getLexerOffsets(info, range);
 135.142 +            if (range != OffsetRange.NONE) {
 135.143 +                List<HintFix> fixList = new ArrayList<>(3);
 135.144 +                String message = NbBundle.getMessage(NameRule.class, "UnusedVariable", name);
 135.145 +                Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
 135.146 +                result.add(desc);
 135.147 +            }
 135.148 +        }
 135.149 +    }
 135.150 +
 135.151 +    private boolean isTupleAssignment(PythonTree node) {
 135.152 +        // This may not work right since the parent pointers often aren't set right;
 135.153 +        // find a more efficient way to do it correctly than a path search for each node
 135.154 +        if (node.getParent() instanceof Tuple) {
 135.155 +            // Allow tuples in tuples
 135.156 +            PythonTree parentParent = node.getParent().getParent();
 135.157 +            while (parentParent instanceof Tuple) {
 135.158 +                parentParent = parentParent.getParent();
 135.159 +                node = node.getParent();
 135.160 +            }
 135.161 +            if (parentParent instanceof Assign) {
 135.162 +                Assign assign = (Assign)parentParent;
 135.163 +                List<expr> targets = assign.getInternalTargets();
 135.164 +                if (targets != null && targets.size() > 0 && targets.get(0) == node.getParent()) {
 135.165 +                    return true;
 135.166 +                }
 135.167 +            }
 135.168 +            if (parentParent instanceof For &&
 135.169 +                    ((For)parentParent).getInternalTarget() == node.getParent()) {
 135.170 +                return true;
 135.171 +            }
 135.172 +        }
 135.173 +
 135.174 +        return false;
 135.175 +    }
 135.176 +
 135.177 +    @Override
 135.178 +    public String getId() {
 135.179 +        return "Unused"; // NOI18N
 135.180 +    }
 135.181 +
 135.182 +    @Override
 135.183 +    public String getDisplayName() {
 135.184 +        return NbBundle.getMessage(NameRule.class, "Unused");
 135.185 +    }
 135.186 +
 135.187 +    @Override
 135.188 +    public String getDescription() {
 135.189 +        return NbBundle.getMessage(NameRule.class, "UnusedDesc");
 135.190 +    }
 135.191 +
 135.192 +    @Override
 135.193 +    public boolean getDefaultEnabled() {
 135.194 +        return true;
 135.195 +    }
 135.196 +
 135.197 +    @Override
 135.198 +    public boolean showInTasklist() {
 135.199 +        return true;
 135.200 +    }
 135.201 +
 135.202 +    @Override
 135.203 +    public HintSeverity getDefaultSeverity() {
 135.204 +        return HintSeverity.WARNING;
 135.205 +    }
 135.206 +
 135.207 +    @Override
 135.208 +    public JComponent getCustomizer(Preferences node) {
 135.209 +        return new UnusedDetectorPrefs(node);
 135.210 +    }
 135.211 +
 135.212 +    static boolean getSkipParameters(Preferences prefs) {
 135.213 +        return prefs.getBoolean(PARAMS_KEY, true);
 135.214 +    }
 135.215 +
 135.216 +    static void setSkipParameters(Preferences prefs, boolean skipParams) {
 135.217 +        if (skipParams) {
 135.218 +            prefs.remove(PARAMS_KEY);
 135.219 +        } else {
 135.220 +            prefs.putBoolean(PARAMS_KEY, false);
 135.221 +        }
 135.222 +    }
 135.223 +
 135.224 +    static boolean getSkipTupleAssignments(Preferences prefs) {
 135.225 +        return prefs.getBoolean(SKIP_TUPLE_ASSIGN_KEY, true);
 135.226 +    }
 135.227 +
 135.228 +    static void setSkipTupleAssignments(Preferences prefs, boolean skipTupleAssigns) {
 135.229 +        if (skipTupleAssigns) {
 135.230 +            prefs.remove(SKIP_TUPLE_ASSIGN_KEY);
 135.231 +        } else {
 135.232 +            prefs.putBoolean(SKIP_TUPLE_ASSIGN_KEY, false);
 135.233 +        }
 135.234 +    }
 135.235 +
 135.236 +    static String getIgnoreNames(Preferences prefs) {
 135.237 +        return prefs.get(IGNORED_KEY, DEFAULT_IGNORED_NAMES);
 135.238 +    }
 135.239 +
 135.240 +    static void setIgnoreNames(Preferences prefs, String ignoredNames) {
 135.241 +        if (ignoredNames.length() == 0) {
 135.242 +            prefs.remove(IGNORED_KEY);
 135.243 +        } else {
 135.244 +            prefs.put(IGNORED_KEY, ignoredNames);
 135.245 +        }
 135.246 +    }
 135.247 +}
   136.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   136.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/UnusedDetectorPrefs.form	Sun Sep 13 11:47:42 2015 +0200
   136.3 @@ -0,0 +1,84 @@
   136.4 +<?xml version="1.0" encoding="UTF-8" ?>
   136.5 +
   136.6 +<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   136.7 +  <AuxValues>
   136.8 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   136.9 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  136.10 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  136.11 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
  136.12 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  136.13 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
  136.14 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="2"/>
  136.15 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  136.16 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  136.17 +  </AuxValues>
  136.18 +
  136.19 +  <Layout>
  136.20 +    <DimensionLayout dim="0">
  136.21 +      <Group type="103" groupAlignment="0" attributes="0">
  136.22 +          <Component id="skipParams" min="-2" max="-2" attributes="0"/>
  136.23 +          <Component id="skipTupleAssignments" alignment="0" min="-2" max="-2" attributes="0"/>
  136.24 +          <Group type="102" alignment="0" attributes="0">
  136.25 +              <Component id="ignoredLabel" min="-2" max="-2" attributes="0"/>
  136.26 +              <EmptySpace max="-2" attributes="0"/>
  136.27 +              <Component id="ignoredNames" min="-2" max="-2" attributes="0"/>
  136.28 +          </Group>
  136.29 +      </Group>
  136.30 +    </DimensionLayout>
  136.31 +    <DimensionLayout dim="1">
  136.32 +      <Group type="103" groupAlignment="0" attributes="0">
  136.33 +          <Group type="102" attributes="0">
  136.34 +              <Component id="skipParams" min="-2" max="-2" attributes="0"/>
  136.35 +              <EmptySpace max="-2" attributes="0"/>
  136.36 +              <Component id="skipTupleAssignments" min="-2" max="-2" attributes="0"/>
  136.37 +              <EmptySpace max="-2" attributes="0"/>
  136.38 +              <Group type="103" groupAlignment="3" attributes="0">
  136.39 +                  <Component id="ignoredLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  136.40 +                  <Component id="ignoredNames" alignment="3" min="-2" max="-2" attributes="0"/>
  136.41 +              </Group>
  136.42 +              <EmptySpace max="32767" attributes="0"/>
  136.43 +          </Group>
  136.44 +      </Group>
  136.45 +    </DimensionLayout>
  136.46 +  </Layout>
  136.47 +  <SubComponents>
  136.48 +    <Component class="javax.swing.JCheckBox" name="skipParams">
  136.49 +      <Properties>
  136.50 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  136.51 +          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="UnusedDetectorPrefs.skipParams.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  136.52 +        </Property>
  136.53 +      </Properties>
  136.54 +      <Events>
  136.55 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
  136.56 +      </Events>
  136.57 +    </Component>
  136.58 +    <Component class="javax.swing.JCheckBox" name="skipTupleAssignments">
  136.59 +      <Properties>
  136.60 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  136.61 +          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="UnusedDetectorPrefs.skipTupleAssignments.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  136.62 +        </Property>
  136.63 +      </Properties>
  136.64 +      <Events>
  136.65 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
  136.66 +      </Events>
  136.67 +    </Component>
  136.68 +    <Component class="javax.swing.JTextField" name="ignoredNames">
  136.69 +      <Properties>
  136.70 +        <Property name="columns" type="int" value="25"/>
  136.71 +      </Properties>
  136.72 +      <Events>
  136.73 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
  136.74 +      </Events>
  136.75 +    </Component>
  136.76 +    <Component class="javax.swing.JLabel" name="ignoredLabel">
  136.77 +      <Properties>
  136.78 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  136.79 +          <ComponentRef name="ignoredNames"/>
  136.80 +        </Property>
  136.81 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  136.82 +          <ResourceString bundle="org/netbeans/modules/python/editor/hints/Bundle.properties" key="UnusedDetectorPrefs.ignoredLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  136.83 +        </Property>
  136.84 +      </Properties>
  136.85 +    </Component>
  136.86 +  </SubComponents>
  136.87 +</Form>
   137.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   137.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/UnusedDetectorPrefs.java	Sun Sep 13 11:47:42 2015 +0200
   137.3 @@ -0,0 +1,152 @@
   137.4 +/*
   137.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   137.6 + *
   137.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   137.8 + *
   137.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  137.10 + * Other names may be trademarks of their respective owners.
  137.11 + *
  137.12 + * The contents of this file are subject to the terms of either the GNU
  137.13 + * General Public License Version 2 only ("GPL") or the Common
  137.14 + * Development and Distribution License("CDDL") (collectively, the
  137.15 + * "License"). You may not use this file except in compliance with the
  137.16 + * License. You can obtain a copy of the License at
  137.17 + * http://www.netbeans.org/cddl-gplv2.html
  137.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  137.19 + * specific language governing permissions and limitations under the
  137.20 + * License.  When distributing the software, include this License Header
  137.21 + * Notice in each file and include the License file at
  137.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  137.23 + * particular file as subject to the "Classpath" exception as provided
  137.24 + * by Oracle in the GPL Version 2 section of the License file that
  137.25 + * accompanied this code. If applicable, add the following below the
  137.26 + * License Header, with the fields enclosed by brackets [] replaced by
  137.27 + * your own identifying information:
  137.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  137.29 + *
  137.30 + * If you wish your version of this file to be governed by only the CDDL
  137.31 + * or only the GPL Version 2, indicate your decision by adding
  137.32 + * "[Contributor] elects to include this software in this distribution
  137.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  137.34 + * single choice of license, a recipient has the option to distribute
  137.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  137.36 + * to extend the choice of license to its licensees as provided above.
  137.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  137.38 + * Version 2 license, then the option applies only if the new code is
  137.39 + * made subject to such option by the copyright holder.
  137.40 + *
  137.41 + * Contributor(s):
  137.42 + *
  137.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  137.44 + */
  137.45 +
  137.46 +/*
  137.47 + * UnusedDetectorPrefs.java
  137.48 + *
  137.49 + * Created on Nov 10, 2008, 9:48:35 AM
  137.50 + */
  137.51 +package org.netbeans.modules.python.hints;
  137.52 +
  137.53 +import java.awt.event.ActionListener;
  137.54 +import java.util.prefs.Preferences;
  137.55 +
  137.56 +/**
  137.57 + * Preferences where users can configure the unused detector rules
  137.58 + * 
  137.59 + * @author Tor Norbye
  137.60 + */
  137.61 +public class UnusedDetectorPrefs extends javax.swing.JPanel implements ActionListener {
  137.62 +    private Preferences prefs;
  137.63 +
  137.64 +    /** Creates new form UnusedDetectorPrefs */
  137.65 +    public UnusedDetectorPrefs(Preferences prefs) {
  137.66 +        initComponents();
  137.67 +        this.prefs = prefs;
  137.68 +        skipParams.setSelected(UnusedDetector.getSkipParameters(prefs));
  137.69 +        skipTupleAssignments.setSelected(UnusedDetector.getSkipTupleAssignments(prefs));
  137.70 +        String ignore = UnusedDetector.getIgnoreNames(prefs);
  137.71 +        if (ignore == null) {
  137.72 +            ignore = "";
  137.73 +        }
  137.74 +        ignoredNames.setText(ignore);
  137.75 +    }
  137.76 +
  137.77 +    @SuppressWarnings("unchecked")
  137.78 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  137.79 +    private void initComponents() {
  137.80 +
  137.81 +        skipParams = new javax.swing.JCheckBox();
  137.82 +        skipTupleAssignments = new javax.swing.JCheckBox();
  137.83 +        ignoredNames = new javax.swing.JTextField();
  137.84 +        ignoredLabel = new javax.swing.JLabel();
  137.85 +
  137.86 +        skipParams.setText(org.openide.util.NbBundle.getMessage(UnusedDetectorPrefs.class, "UnusedDetectorPrefs.skipParams.text")); // NOI18N
  137.87 +        skipParams.addActionListener(this);
  137.88 +
  137.89 +        skipTupleAssignments.setText(org.openide.util.NbBundle.getMessage(UnusedDetectorPrefs.class, "UnusedDetectorPrefs.skipTupleAssignments.text")); // NOI18N
  137.90 +        skipTupleAssignments.addActionListener(this);
  137.91 +
  137.92 +        ignoredNames.setColumns(25);
  137.93 +        ignoredNames.addActionListener(this);
  137.94 +
  137.95 +        ignoredLabel.setLabelFor(ignoredNames);
  137.96 +        ignoredLabel.setText(org.openide.util.NbBundle.getMessage(UnusedDetectorPrefs.class, "UnusedDetectorPrefs.ignoredLabel.text")); // NOI18N
  137.97 +
  137.98 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
  137.99 +        this.setLayout(layout);
 137.100 +        layout.setHorizontalGroup(
 137.101 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 137.102 +            .addComponent(skipParams)
 137.103 +            .addComponent(skipTupleAssignments)
 137.104 +            .addGroup(layout.createSequentialGroup()
 137.105 +                .addComponent(ignoredLabel)
 137.106 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 137.107 +                .addComponent(ignoredNames, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 137.108 +        );
 137.109 +        layout.setVerticalGroup(
 137.110 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 137.111 +            .addGroup(layout.createSequentialGroup()
 137.112 +                .addComponent(skipParams)
 137.113 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 137.114 +                .addComponent(skipTupleAssignments)
 137.115 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 137.116 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 137.117 +                    .addComponent(ignoredLabel)
 137.118 +                    .addComponent(ignoredNames, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 137.119 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 137.120 +        );
 137.121 +    }
 137.122 +
 137.123 +    // Code for dispatching events from components to event handlers.
 137.124 +
 137.125 +    public void actionPerformed(java.awt.event.ActionEvent evt) {
 137.126 +        if (evt.getSource() == skipParams) {
 137.127 +            UnusedDetectorPrefs.this.changed(evt);
 137.128 +        }
 137.129 +        else if (evt.getSource() == skipTupleAssignments) {
 137.130 +            UnusedDetectorPrefs.this.changed(evt);
 137.131 +        }
 137.132 +        else if (evt.getSource() == ignoredNames) {
 137.133 +            UnusedDetectorPrefs.this.changed(evt);
 137.134 +        }
 137.135 +    }// </editor-fold>//GEN-END:initComponents
 137.136 +
 137.137 +    private void changed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_changed
 137.138 +        Object source = evt.getSource();
 137.139 +        if (source == ignoredNames) {
 137.140 +            UnusedDetector.setIgnoreNames(prefs, ignoredNames.getText().trim());
 137.141 +        } else if (source == skipParams) {
 137.142 +            UnusedDetector.setSkipParameters(prefs, skipParams.isSelected());
 137.143 +        } else if (source == skipTupleAssignments) {
 137.144 +            UnusedDetector.setSkipTupleAssignments(prefs, skipTupleAssignments.isSelected());
 137.145 +        } else {
 137.146 +            assert false : source;
 137.147 +        }
 137.148 +    }//GEN-LAST:event_changed
 137.149 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 137.150 +    private javax.swing.JLabel ignoredLabel;
 137.151 +    private javax.swing.JTextField ignoredNames;
 137.152 +    private javax.swing.JCheckBox skipParams;
 137.153 +    private javax.swing.JCheckBox skipTupleAssignments;
 137.154 +    // End of variables declaration//GEN-END:variables
 137.155 +}
   138.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   138.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/UnusedImports.java	Sun Sep 13 11:47:42 2015 +0200
   138.3 @@ -0,0 +1,286 @@
   138.4 +/*
   138.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   138.6 + *
   138.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   138.8 + *
   138.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  138.10 + * Other names may be trademarks of their respective owners.
  138.11 + *
  138.12 + * The contents of this file are subject to the terms of either the GNU
  138.13 + * General Public License Version 2 only ("GPL") or the Common
  138.14 + * Development and Distribution License("CDDL") (collectively, the
  138.15 + * "License"). You may not use this file except in compliance with the
  138.16 + * License. You can obtain a copy of the License at
  138.17 + * http://www.netbeans.org/cddl-gplv2.html
  138.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  138.19 + * specific language governing permissions and limitations under the
  138.20 + * License.  When distributing the software, include this License Header
  138.21 + * Notice in each file and include the License file at
  138.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  138.23 + * particular file as subject to the "Classpath" exception as provided
  138.24 + * by Oracle in the GPL Version 2 section of the License file that
  138.25 + * accompanied this code. If applicable, add the following below the
  138.26 + * License Header, with the fields enclosed by brackets [] replaced by
  138.27 + * your own identifying information:
  138.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  138.29 + *
  138.30 + * If you wish your version of this file to be governed by only the CDDL
  138.31 + * or only the GPL Version 2, indicate your decision by adding
  138.32 + * "[Contributor] elects to include this software in this distribution
  138.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  138.34 + * single choice of license, a recipient has the option to distribute
  138.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  138.36 + * to extend the choice of license to its licensees as provided above.
  138.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  138.38 + * Version 2 license, then the option applies only if the new code is
  138.39 + * made subject to such option by the copyright holder.
  138.40 + *
  138.41 + * Contributor(s):
  138.42 + *
  138.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  138.44 + */
  138.45 +package org.netbeans.modules.python.hints;
  138.46 +
  138.47 +import java.util.ArrayList;
  138.48 +import java.util.Collections;
  138.49 +import java.util.HashMap;
  138.50 +import java.util.List;
  138.51 +import java.util.Map;
  138.52 +import java.util.Set;
  138.53 +import java.util.prefs.Preferences;
  138.54 +import javax.swing.JComponent;
  138.55 +import org.netbeans.editor.BaseDocument;
  138.56 +import org.netbeans.modules.csl.api.EditList;
  138.57 +import org.netbeans.modules.csl.api.Hint;
  138.58 +import org.netbeans.modules.csl.api.HintFix;
  138.59 +import org.netbeans.modules.csl.api.HintSeverity;
  138.60 +import org.netbeans.modules.csl.api.OffsetRange;
  138.61 +import org.netbeans.modules.csl.api.RuleContext;
  138.62 +import org.netbeans.modules.python.source.PythonAstUtils;
  138.63 +import org.netbeans.modules.python.source.PythonParserResult;
  138.64 +import org.netbeans.modules.python.source.ImportEntry;
  138.65 +import org.netbeans.modules.python.source.ImportManager;
  138.66 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  138.67 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  138.68 +import org.openide.filesystems.FileObject;
  138.69 +import org.openide.util.NbBundle;
  138.70 +import org.python.antlr.PythonTree;
  138.71 +import org.python.antlr.ast.Import;
  138.72 +import org.python.antlr.ast.ImportFrom;
  138.73 +import org.python.antlr.ast.Module;
  138.74 +import org.python.antlr.ast.alias;
  138.75 +
  138.76 +/**
  138.77 + * Detect unused imports
  138.78 + *
  138.79 + * @author Tor Norbye
  138.80 + */
  138.81 +public class UnusedImports extends PythonAstRule {
  138.82 +    public UnusedImports() {
  138.83 +    }
  138.84 +
  138.85 +    @Override
  138.86 +    public boolean appliesTo(RuleContext context) {
  138.87 +        FileObject fo = context.parserResult.getSnapshot().getSource().getFileObject();
  138.88 +        return fo == null || !fo.getName().equals("__init__"); // NOI18N
  138.89 +    }
  138.90 +
  138.91 +    @Override
  138.92 +    public Set<Class> getKinds() {
  138.93 +        return Collections.<Class>singleton(Module.class);
  138.94 +    }
  138.95 +
  138.96 +    @Override
  138.97 +    public void run(PythonRuleContext context, List<Hint> result) {
  138.98 +        computeUnusedImports(this, context, result, null);
  138.99 +    }
 138.100 +
 138.101 +    private static void computeUnusedImports(UnusedImports detector, PythonRuleContext context, List<Hint> result, Map<PythonTree, List<String>> unused) {
 138.102 +        assert result == null || unused == null; // compute either results or set of unused
 138.103 +
 138.104 +        PythonParserResult info = (PythonParserResult) context.parserResult;
 138.105 +        SymbolTable symbolTable = info.getSymbolTable();
 138.106 +        List<ImportEntry> unusedImports = symbolTable.getUnusedImports();
 138.107 +        if (unusedImports.isEmpty()) {
 138.108 +            return;
 138.109 +        }
 138.110 +        Map<PythonTree, List<String>> maps = new HashMap<>();
 138.111 +        for (ImportEntry entry : unusedImports) {
 138.112 +            maps.put(entry.node, new ArrayList<String>());
 138.113 +        }
 138.114 +        for (ImportEntry entry : unusedImports) {
 138.115 +            if (entry.isFromImport) {
 138.116 +                String name = entry.asName != null ? entry.asName : entry.symbol;
 138.117 +                maps.get(entry.node).add(name);
 138.118 +            } else {
 138.119 +                String name = entry.asName != null ? entry.asName : entry.module;
 138.120 +                maps.get(entry.node).add(name);
 138.121 +            }
 138.122 +        }
 138.123 +        for (Map.Entry<PythonTree, List<String>> entry : maps.entrySet()) {
 138.124 +            PythonTree node = entry.getKey();
 138.125 +            List<String> list = entry.getValue();
 138.126 +            if (node instanceof Import) {
 138.127 +                Import imp = (Import)node;
 138.128 +                List<alias> names = imp.getInternalNames();
 138.129 +                if (names != null && names.size() == list.size()) {
 138.130 +                    list.clear();
 138.131 +                }
 138.132 +            } else {
 138.133 +                assert node instanceof ImportFrom;
 138.134 +                ImportFrom imp = (ImportFrom)node;
 138.135 +                List<alias> names = imp.getInternalNames();
 138.136 +                if (names != null && names.size() == list.size()) {
 138.137 +                    list.clear();
 138.138 +                }
 138.139 +            }
 138.140 +        }
 138.141 +
 138.142 +        for (Map.Entry<PythonTree, List<String>> entry : maps.entrySet()) {
 138.143 +            PythonTree node = entry.getKey();
 138.144 +            List<String> list = entry.getValue();
 138.145 +            if (list.size() == 0) {
 138.146 +                list = null;
 138.147 +            }
 138.148 +            if (unused != null) {
 138.149 +                unused.put(node, list);
 138.150 +            } else {
 138.151 +                addError(detector, context, node, list, result);
 138.152 +            }
 138.153 +        }
 138.154 +    }
 138.155 +
 138.156 +    private static void addError(UnusedImports detector, PythonRuleContext context, PythonTree node, List<String> symbols, List<Hint> result) {
 138.157 +        PythonParserResult info = (PythonParserResult) context.parserResult;
 138.158 +        OffsetRange range = PythonAstUtils.getNameRange(info, node);
 138.159 +        range = PythonLexerUtils.getLexerOffsets(info, range);
 138.160 +        if (range != OffsetRange.NONE) {
 138.161 +            List<HintFix> fixList = new ArrayList<>(3);
 138.162 +            fixList.add(new UnusedFix(detector, context, node, symbols, false));
 138.163 +            fixList.add(new UnusedFix(detector, context, null, null, false)); // Remove All
 138.164 +            fixList.add(new UnusedFix(detector, context, null, null, true)); // Organize
 138.165 +            String message;
 138.166 +            if (symbols != null) {
 138.167 +                message = NbBundle.getMessage(NameRule.class, "UnusedImportSymbols", symbols);
 138.168 +            } else {
 138.169 +                message = NbBundle.getMessage(NameRule.class, "UnusedImport");
 138.170 +            }
 138.171 +            Hint desc = new Hint(detector, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2500);
 138.172 +            result.add(desc);
 138.173 +        }
 138.174 +    }
 138.175 +
 138.176 +    @Override
 138.177 +    public String getId() {
 138.178 +        return "UnusedImports"; // NOI18N
 138.179 +    }
 138.180 +
 138.181 +    @Override
 138.182 +    public String getDisplayName() {
 138.183 +        return NbBundle.getMessage(NameRule.class, "UnusedImports");
 138.184 +    }
 138.185 +
 138.186 +    @Override
 138.187 +    public String getDescription() {
 138.188 +        return NbBundle.getMessage(NameRule.class, "UnusedImportsDesc");
 138.189 +    }
 138.190 +
 138.191 +    @Override
 138.192 +    public boolean getDefaultEnabled() {
 138.193 +        return true;
 138.194 +    }
 138.195 +
 138.196 +    @Override
 138.197 +    public boolean showInTasklist() {
 138.198 +        return false; // ? or maybe yes?
 138.199 +    }
 138.200 +
 138.201 +    @Override
 138.202 +    public HintSeverity getDefaultSeverity() {
 138.203 +        return HintSeverity.WARNING;
 138.204 +    }
 138.205 +
 138.206 +    @Override
 138.207 +    public JComponent getCustomizer(Preferences node) {
 138.208 +        return null;
 138.209 +    }
 138.210 +
 138.211 +    /**
 138.212 +     * Fix to insert self argument or rename first argument to self
 138.213 +     */
 138.214 +    private static class UnusedFix implements /*PreviewableFix*/ HintFix { // Preview not particularly helpful and clutters menu
 138.215 +        private final UnusedImports detector;
 138.216 +        private final PythonRuleContext context;
 138.217 +        private final PythonTree node;
 138.218 +        private final List<String> symbols;
 138.219 +        private final boolean organizeOnly;
 138.220 +
 138.221 +        private UnusedFix(UnusedImports detector, PythonRuleContext context, PythonTree node, List<String> symbols, boolean organizeOnly) {
 138.222 +            this.detector = detector;
 138.223 +            this.context = context;
 138.224 +            this.node = node;
 138.225 +            this.symbols = symbols;
 138.226 +            this.organizeOnly = organizeOnly;
 138.227 +        }
 138.228 +
 138.229 +        @Override
 138.230 +        public String getDescription() {
 138.231 +            if (node == null) {
 138.232 +                if (organizeOnly) {
 138.233 +                    return NbBundle.getMessage(CreateDocString.class, "OrganizeImports");
 138.234 +                } else {
 138.235 +                    return NbBundle.getMessage(CreateDocString.class, "DeleteAllUnused");
 138.236 +                }
 138.237 +            } else if (symbols != null) {
 138.238 +                return NbBundle.getMessage(CreateDocString.class, "UnusedFixSymbols", symbols);
 138.239 +            } else {
 138.240 +                return NbBundle.getMessage(CreateDocString.class, "UnusedFix");
 138.241 +            }
 138.242 +        }
 138.243 +
 138.244 +        public boolean canPreview() {
 138.245 +            return true;
 138.246 +        }
 138.247 +
 138.248 +        public EditList getEditList() throws Exception {
 138.249 +            BaseDocument doc = context.doc;
 138.250 +            EditList edits = new EditList(doc);
 138.251 +
 138.252 +            ImportManager importManager = new ImportManager((PythonParserResult) context.parserResult);
 138.253 +
 138.254 +            if (node == null) {
 138.255 +                if (organizeOnly) {
 138.256 +                    importManager.cleanup(edits, 0, doc.getLength(), true);
 138.257 +                } else {
 138.258 +                    Map<PythonTree, List<String>> onlyNames = new HashMap<>();
 138.259 +                    computeUnusedImports(detector, context, null, onlyNames);
 138.260 +                    Set<PythonTree> candidates = onlyNames.keySet();
 138.261 +                    importManager.removeImports(edits, candidates, false, onlyNames);
 138.262 +                }
 138.263 +            } else {
 138.264 +                Set<PythonTree> candidates = Collections.singleton(node);
 138.265 +                Map<PythonTree, List<String>> onlyNames = new HashMap<>();
 138.266 +                onlyNames.put(node, symbols);
 138.267 +                importManager.removeImports(edits, candidates, false, onlyNames);
 138.268 +            }
 138.269 +
 138.270 +            return edits;
 138.271 +        }
 138.272 +
 138.273 +        @Override
 138.274 +        public void implement() throws Exception {
 138.275 +            EditList edits = getEditList();
 138.276 +            edits.apply();
 138.277 +        }
 138.278 +
 138.279 +        @Override
 138.280 +        public boolean isSafe() {
 138.281 +            return true;
 138.282 +        }
 138.283 +
 138.284 +        @Override
 138.285 +        public boolean isInteractive() {
 138.286 +            return false;
 138.287 +        }
 138.288 +    }
 138.289 +}
   139.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   139.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/layer.xml	Sun Sep 13 11:47:42 2015 +0200
   139.3 @@ -0,0 +1,61 @@
   139.4 +<?xml version="1.0" encoding="UTF-8"?>
   139.5 +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
   139.6 +<filesystem>
   139.7 +    
   139.8 +    <folder name="csl-hints">
   139.9 +        <folder name="text">
  139.10 +            <folder name="x-python">
  139.11 +                <folder name="hints">
  139.12 +                    <folder name="general">
  139.13 +                        <attr name="position" intvalue="100"/>
  139.14 +                        <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.python.editor.hints.Bundle"/>
  139.15 +                        <file name="org-netbeans-modules-python-hints-NameRule.instance"/>
  139.16 +                        <file name="org-netbeans-modules-python-hints-CreateDocString.instance"/>
  139.17 +                        <file name="org-netbeans-modules-python-hints-AssignToVariable.instance"/>
  139.18 +                        <file name="org-netbeans-modules-python-hints-SplitImports.instance"/>
  139.19 +                        <file name="org-netbeans-modules-python-hints-RelativeImports.instance"/>
  139.20 +                        <file name="org-netbeans-modules-python-hints-Deprecations.instance"/>
  139.21 +                        <file name="org-netbeans-modules-python-hints-UnusedImports.instance"/>
  139.22 +                        <file name="org-netbeans-modules-python-hints-UnusedDetector.instance"/>
  139.23 +                        <file name="org-netbeans-modules-python-hints-UnresolvedDetector.instance"/>
  139.24 +                        <file name="org-netbeans-modules-python-hints-UnresolvedClassComponents.instance"/>
  139.25 +                        <file name="org-netbeans-modules-python-hints-AllAssignExists.instance"/>
  139.26 +                        <file name="org-netbeans-modules-python-hints-AccessToProtected.instance"/>
  139.27 +                        <file name="org-netbeans-modules-python-hints-AttributeDefinedOutsideInit.instance"/>
  139.28 +                        <file name="org-netbeans-modules-python-hints-ClassCircularRedundancy.instance"/>
  139.29 +                    </folder>
  139.30 +                </folder>
  139.31 +                <folder name="selection">
  139.32 +                    <file name="org-netbeans-modules-python-editor-hints-SurroundWith.instance"/>
  139.33 +                    <file name="org-netbeans-modules-python-editor-hints-ExtractCode.instance"/>
  139.34 +                </folder>
  139.35 +            </folder>
  139.36 +        </folder>
  139.37 +    </folder>
  139.38 +    
  139.39 +    <folder name="CslPlugins">
  139.40 +        <folder name="text">
  139.41 +            <folder name="x-python">
  139.42 +                <file name="hints.instance">
  139.43 +                    <attr name="instanceClass" stringvalue="org.netbeans.modules.python.hints.PythonHintsProvider"/>
  139.44 +                </file>
  139.45 +            </folder>
  139.46 +        </folder>
  139.47 +    </folder>
  139.48 +    
  139.49 +    <folder name="OptionsDialog">
  139.50 +        <folder name="Editor">
  139.51 +            <folder name="Hints">
  139.52 +                <attr name="position" intvalue="0"/>
  139.53 +                <folder name="text">
  139.54 +                    <folder name="x-python">
  139.55 +                        <file name="PythonHints.instance">
  139.56 +                            <attr name="instanceOf" stringvalue="org.netbeans.spi.options.OptionsPanelController"/>
  139.57 +                            <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.hints.PythonHintOptions.createStatic"/>
  139.58 +                        </file>
  139.59 +                    </folder>
  139.60 +                </folder>
  139.61 +            </folder>
  139.62 +        </folder>
  139.63 +    </folder>
  139.64 +</filesystem>
   140.1 --- a/python.project/src/org/netbeans/modules/python/project/GotoTest.java	Sat Sep 12 23:03:15 2015 -0700
   140.2 +++ b/python.project/src/org/netbeans/modules/python/project/GotoTest.java	Sun Sep 13 11:47:42 2015 +0200
   140.3 @@ -48,7 +48,7 @@
   140.4  import java.util.regex.Pattern;
   140.5  
   140.6  
   140.7 -import org.netbeans.modules.python.editor.PythonUtils;
   140.8 +import org.netbeans.modules.python.source.PythonUtils;
   140.9  import org.netbeans.spi.gototest.TestLocator;
  140.10  import org.netbeans.spi.gototest.TestLocator.LocationResult;
  140.11  import org.openide.filesystems.FileObject;
   141.1 --- a/python.source/manifest.mf	Sat Sep 12 23:03:15 2015 -0700
   141.2 +++ b/python.source/manifest.mf	Sun Sep 13 11:47:42 2015 +0200
   141.3 @@ -1,5 +1,6 @@
   141.4  Manifest-Version: 1.0
   141.5  OpenIDE-Module: org.netbeans.modules.python.source
   141.6 +OpenIDE-Module-Layer: org/netbeans/modules/python/source/layer.xml
   141.7  OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/python/source/Bundle.properties
   141.8 -OpenIDE-Module-Specification-Version: 1.0
   141.9 +OpenIDE-Module-Specification-Version: 1.1
  141.10  AutoUpdate-Show-In-Client: false
   142.1 --- a/python.source/nbproject/project.xml	Sat Sep 12 23:03:15 2015 -0700
   142.2 +++ b/python.source/nbproject/project.xml	Sun Sep 13 11:47:42 2015 +0200
   142.3 @@ -7,6 +7,15 @@
   142.4              <!--<suite-component/>-->
   142.5              <module-dependencies>
   142.6                  <dependency>
   142.7 +                    <code-name-base>org.jython</code-name-base>
   142.8 +                    <build-prerequisite/>
   142.9 +                    <compile-dependency/>
  142.10 +                    <run-dependency>
  142.11 +                        <release-version>2</release-version>
  142.12 +                        <specification-version>2.12</specification-version>
  142.13 +                    </run-dependency>
  142.14 +                </dependency>
  142.15 +                <dependency>
  142.16                      <code-name-base>org.netbeans.api.annotations.common</code-name-base>
  142.17                      <build-prerequisite/>
  142.18                      <compile-dependency/>
  142.19 @@ -16,6 +25,103 @@
  142.20                      </run-dependency>
  142.21                  </dependency>
  142.22                  <dependency>
  142.23 +                    <code-name-base>org.netbeans.modules.csl.api</code-name-base>
  142.24 +                    <build-prerequisite/>
  142.25 +                    <compile-dependency/>
  142.26 +                    <run-dependency>
  142.27 +                        <release-version>2</release-version>
  142.28 +                        <specification-version>2.51</specification-version>
  142.29 +                    </run-dependency>
  142.30 +                </dependency>
  142.31 +                <dependency>
  142.32 +                    <code-name-base>org.netbeans.modules.editor.document</code-name-base>
  142.33 +                    <build-prerequisite/>
  142.34 +                    <compile-dependency/>
  142.35 +                    <run-dependency>
  142.36 +                        <specification-version>1.5</specification-version>
  142.37 +                    </run-dependency>
  142.38 +                </dependency>
  142.39 +                <dependency>
  142.40 +                    <code-name-base>org.netbeans.modules.editor.indent</code-name-base>
  142.41 +                    <build-prerequisite/>
  142.42 +                    <compile-dependency/>
  142.43 +                    <run-dependency>
  142.44 +                        <release-version>2</release-version>
  142.45 +                        <specification-version>1.42</specification-version>
  142.46 +                    </run-dependency>
  142.47 +                </dependency>
  142.48 +                <dependency>
  142.49 +                    <code-name-base>org.netbeans.modules.editor.lib</code-name-base>
  142.50 +                    <build-prerequisite/>
  142.51 +                    <compile-dependency/>
  142.52 +                    <run-dependency>
  142.53 +                        <release-version>3</release-version>
  142.54 +                        <specification-version>4.3</specification-version>
  142.55 +                    </run-dependency>
  142.56 +                </dependency>
  142.57 +                <dependency>
  142.58 +                    <code-name-base>org.netbeans.modules.editor.lib2</code-name-base>
  142.59 +                    <build-prerequisite/>
  142.60 +                    <compile-dependency/>
  142.61 +                    <run-dependency>
  142.62 +                        <release-version>1</release-version>
  142.63 +                        <specification-version>2.3</specification-version>
  142.64 +                    </run-dependency>
  142.65 +                </dependency>
  142.66 +                <dependency>
  142.67 +                    <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
  142.68 +                    <build-prerequisite/>
  142.69 +                    <compile-dependency/>
  142.70 +                    <run-dependency>
  142.71 +                        <release-version>1</release-version>
  142.72 +                        <specification-version>1.39</specification-version>
  142.73 +                    </run-dependency>
  142.74 +                </dependency>
  142.75 +                <dependency>
  142.76 +                    <code-name-base>org.netbeans.modules.editor.settings</code-name-base>
  142.77 +                    <build-prerequisite/>
  142.78 +                    <compile-dependency/>
  142.79 +                    <run-dependency>
  142.80 +                        <release-version>1</release-version>
  142.81 +                        <specification-version>1.55</specification-version>
  142.82 +                    </run-dependency>
  142.83 +                </dependency>
  142.84 +                <dependency>
  142.85 +                    <code-name-base>org.netbeans.modules.lexer</code-name-base>
  142.86 +                    <build-prerequisite/>
  142.87 +                    <compile-dependency/>
  142.88 +                    <run-dependency>
  142.89 +                        <release-version>2</release-version>
  142.90 +                        <specification-version>1.62</specification-version>
  142.91 +                    </run-dependency>
  142.92 +                </dependency>
  142.93 +                <dependency>
  142.94 +                    <code-name-base>org.netbeans.modules.options.editor</code-name-base>
  142.95 +                    <build-prerequisite/>
  142.96 +                    <compile-dependency/>
  142.97 +                    <run-dependency>
  142.98 +                        <release-version>1</release-version>
  142.99 +                        <specification-version>1.54</specification-version>
 142.100 +                    </run-dependency>
 142.101 +                </dependency>
 142.102 +                <dependency>
 142.103 +                    <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
 142.104 +                    <build-prerequisite/>
 142.105 +                    <compile-dependency/>
 142.106 +                    <run-dependency>
 142.107 +                        <release-version>1</release-version>
 142.108 +                        <specification-version>9.5</specification-version>
 142.109 +                    </run-dependency>
 142.110 +                </dependency>
 142.111 +                <dependency>
 142.112 +                    <code-name-base>org.netbeans.modules.parsing.indexing</code-name-base>
 142.113 +                    <build-prerequisite/>
 142.114 +                    <compile-dependency/>
 142.115 +                    <run-dependency>
 142.116 +                        <specification-version>9.7</specification-version>
 142.117 +                    </run-dependency>
 142.118 +                </dependency>
 142.119 +                <dependency>
 142.120                      <code-name-base>org.netbeans.modules.projectapi</code-name-base>
 142.121                      <build-prerequisite/>
 142.122                      <compile-dependency/>
 142.123 @@ -25,6 +131,31 @@
 142.124                      </run-dependency>
 142.125                  </dependency>
 142.126                  <dependency>
 142.127 +                    <code-name-base>org.netbeans.modules.python.core</code-name-base>
 142.128 +                    <build-prerequisite/>
 142.129 +                    <compile-dependency/>
 142.130 +                    <run-dependency>
 142.131 +                        <specification-version>1.4</specification-version>
 142.132 +                    </run-dependency>
 142.133 +                </dependency>
 142.134 +                <dependency>
 142.135 +                    <code-name-base>org.netbeans.modules.queries</code-name-base>
 142.136 +                    <build-prerequisite/>
 142.137 +                    <compile-dependency/>
 142.138 +                    <run-dependency>
 142.139 +                        <release-version>1</release-version>
 142.140 +                        <specification-version>1.42</specification-version>
 142.141 +                    </run-dependency>
 142.142 +                </dependency>
 142.143 +                <dependency>
 142.144 +                    <code-name-base>org.openide.awt</code-name-base>
 142.145 +                    <build-prerequisite/>
 142.146 +                    <compile-dependency/>
 142.147 +                    <run-dependency>
 142.148 +                        <specification-version>7.65</specification-version>
 142.149 +                    </run-dependency>
 142.150 +                </dependency>
 142.151 +                <dependency>
 142.152                      <code-name-base>org.openide.filesystems</code-name-base>
 142.153                      <build-prerequisite/>
 142.154                      <compile-dependency/>
 142.155 @@ -49,6 +180,38 @@
 142.156                      </run-dependency>
 142.157                  </dependency>
 142.158                  <dependency>
 142.159 +                    <code-name-base>org.openide.loaders</code-name-base>
 142.160 +                    <build-prerequisite/>
 142.161 +                    <compile-dependency/>
 142.162 +                    <run-dependency>
 142.163 +                        <specification-version>7.63</specification-version>
 142.164 +                    </run-dependency>
 142.165 +                </dependency>
 142.166 +                <dependency>
 142.167 +                    <code-name-base>org.openide.modules</code-name-base>
 142.168 +                    <build-prerequisite/>
 142.169 +                    <compile-dependency/>
 142.170 +                    <run-dependency>
 142.171 +                        <specification-version>7.47</specification-version>
 142.172 +                    </run-dependency>
 142.173 +                </dependency>
 142.174 +                <dependency>
 142.175 +                    <code-name-base>org.openide.nodes</code-name-base>
 142.176 +                    <build-prerequisite/>
 142.177 +                    <compile-dependency/>
 142.178 +                    <run-dependency>
 142.179 +                        <specification-version>7.42</specification-version>
 142.180 +                    </run-dependency>
 142.181 +                </dependency>
 142.182 +                <dependency>
 142.183 +                    <code-name-base>org.openide.text</code-name-base>
 142.184 +                    <build-prerequisite/>
 142.185 +                    <compile-dependency/>
 142.186 +                    <run-dependency>
 142.187 +                        <specification-version>6.66</specification-version>
 142.188 +                    </run-dependency>
 142.189 +                </dependency>
 142.190 +                <dependency>
 142.191                      <code-name-base>org.openide.util</code-name-base>
 142.192                      <build-prerequisite/>
 142.193                      <compile-dependency/>
 142.194 @@ -72,9 +235,21 @@
 142.195                          <specification-version>9.3</specification-version>
 142.196                      </run-dependency>
 142.197                  </dependency>
 142.198 +                <dependency>
 142.199 +                    <code-name-base>org.openide.windows</code-name-base>
 142.200 +                    <build-prerequisite/>
 142.201 +                    <compile-dependency/>
 142.202 +                    <run-dependency>
 142.203 +                        <specification-version>6.74</specification-version>
 142.204 +                    </run-dependency>
 142.205 +                </dependency>
 142.206              </module-dependencies>
 142.207              <public-packages>
 142.208 +                <package>org.netbeans.modules.python.source</package>
 142.209 +                <package>org.netbeans.modules.python.source.elements</package>
 142.210 +                <package>org.netbeans.modules.python.source.lexer</package>
 142.211                  <package>org.netbeans.modules.python.source.queries</package>
 142.212 +                <package>org.netbeans.modules.python.source.scopes</package>
 142.213              </public-packages>
 142.214          </data>
 142.215      </configuration>
   143.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   143.2 +++ b/python.source/src/org/netbeans/modules/python/source/AstPath.java	Sun Sep 13 11:47:42 2015 +0200
   143.3 @@ -0,0 +1,436 @@
   143.4 +/*
   143.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   143.6 + *
   143.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   143.8 + *
   143.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  143.10 + * Other names may be trademarks of their respective owners.
  143.11 + *
  143.12 + * The contents of this file are subject to the terms of either the GNU
  143.13 + * General Public License Version 2 only ("GPL") or the Common
  143.14 + * Development and Distribution License("CDDL") (collectively, the
  143.15 + * "License"). You may not use this file except in compliance with the
  143.16 + * License. You can obtain a copy of the License at
  143.17 + * http://www.netbeans.org/cddl-gplv2.html
  143.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  143.19 + * specific language governing permissions and limitations under the
  143.20 + * License.  When distributing the software, include this License Header
  143.21 + * Notice in each file and include the License file at
  143.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  143.23 + * particular file as subject to the "Classpath" exception as provided
  143.24 + * by Oracle in the GPL Version 2 section of the License file that
  143.25 + * accompanied this code. If applicable, add the following below the
  143.26 + * License Header, with the fields enclosed by brackets [] replaced by
  143.27 + * your own identifying information:
  143.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  143.29 + *
  143.30 + * Contributor(s):
  143.31 + *
  143.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  143.33 + */
  143.34 +package org.netbeans.modules.python.source;
  143.35 +
  143.36 +import java.util.ArrayList;
  143.37 +import java.util.Iterator;
  143.38 +import java.util.ListIterator;
  143.39 +import org.openide.util.Exceptions;
  143.40 +import org.python.antlr.PythonTree;
  143.41 +import org.python.antlr.Visitor;
  143.42 +
  143.43 +/**
  143.44 + * AstPath represents a path from a root node to a particular node in the AST.
  143.45 + * This is necessary because the parent node pointers in the nodes aren't always
  143.46 + * non null, so we can't just pass a node as a reference to a traversable path
  143.47 + * from the root to a node.
  143.48 + *
  143.49 + * @author Tor Norbye
  143.50 + */
  143.51 +public class AstPath implements Iterable<PythonTree> {
  143.52 +    private ArrayList<PythonTree> path = new ArrayList<>(30);
  143.53 +
  143.54 +    public AstPath() {
  143.55 +    }
  143.56 +
  143.57 +    public AstPath(AstPath other) {
  143.58 +        path.addAll(other.path);
  143.59 +    }
  143.60 +
  143.61 +    public AstPath(ArrayList<PythonTree> path) {
  143.62 +        this.path = path;
  143.63 +    }
  143.64 +
  143.65 +//    /**
  143.66 +//     * Initialize a node path to the given caretOffset
  143.67 +//     */
  143.68 +//    public AstPath(PythonTree root, int caretOffset) {
  143.69 +//        findPathTo(root, caretOffset);
  143.70 +//    }
  143.71 +//
  143.72 +//    /**
  143.73 +//     * Find the path to the given node in the AST
  143.74 +//     */
  143.75 +//    @SuppressWarnings("unchecked")
  143.76 +//    public AstPath(PythonTree node, PythonTree target) {
  143.77 +//        if (!find(node, target)) {
  143.78 +//            path.clear();
  143.79 +//        } else {
  143.80 +//            // Reverse the list such that node is on top
  143.81 +//            // When I get time rewrite the find method to build the list that way in the first place
  143.82 +//            Collections.reverse(path);
  143.83 +//        }
  143.84 +//    }
  143.85 +    public void descend(PythonTree node) {
  143.86 +        path.add(node);
  143.87 +    }
  143.88 +
  143.89 +    public void ascend() {
  143.90 +        path.remove(path.size() - 1);
  143.91 +    }
  143.92 +
  143.93 +    /**
  143.94 +     * Return the closest ancestor of the leaf that is of the given type
  143.95 +     */
  143.96 +    public PythonTree getTypedAncestor(Class clz) {
  143.97 +        return getTypedAncestor(clz, null);
  143.98 +    }
  143.99 +
 143.100 +    /**
 143.101 +     * Return the closest ancestor of the given node that is of the given type
 143.102 +     */
 143.103 +    public PythonTree getTypedAncestor(Class clz, PythonTree from) {
 143.104 +        int i = path.size() - 1;
 143.105 +
 143.106 +        // First find the given starting point
 143.107 +        if (from != null) {
 143.108 +            for (; i >= 0; i--) {
 143.109 +                PythonTree node = path.get(i);
 143.110 +
 143.111 +                if (node == from) {
 143.112 +                    break;
 143.113 +                }
 143.114 +            }
 143.115 +        }
 143.116 +
 143.117 +        for (; i >= 0; i--) {
 143.118 +            PythonTree node = path.get(i);
 143.119 +
 143.120 +            if (clz.isInstance(node)) {
 143.121 +                return node;
 143.122 +            }
 143.123 +        }
 143.124 +
 143.125 +        return null; // not found
 143.126 +    }
 143.127 +
 143.128 +    /**
 143.129 +     * Return true iff this path contains a node of the given node type
 143.130 +     *
 143.131 +     * @param nodeType The nodeType to check
 143.132 +     * @return true if the given nodeType is found in the path
 143.133 +     */
 143.134 +    public boolean contains(Class clz) {
 143.135 +        return getTypedAncestor(clz) != null;
 143.136 +    }
 143.137 +
 143.138 +//    /**
 143.139 +//     * Find the position closest to the given offset in the AST. Place the path from the leaf up to the path in the
 143.140 +//     * passed in path list.
 143.141 +//     */
 143.142 +//    @SuppressWarnings("unchecked")
 143.143 +//    public PythonTree findPathTo(PythonTree node, int offset) {
 143.144 +//        PythonTree result = find(node, offset);
 143.145 +//        path.add(node);
 143.146 +//
 143.147 +//        // Reverse the list such that node is on top
 143.148 +//        // When I get time rewrite the find method to build the list that way in the first place
 143.149 +//        Collections.reverse(path);
 143.150 +//
 143.151 +//        return result;
 143.152 +//    }
 143.153 +//
 143.154 +//    @SuppressWarnings("unchecked")
 143.155 +//    private PythonTree find(PythonTree node, int offset) {
 143.156 +//        int begin = node.getSourceStart();
 143.157 +//        int end = node.getSourceEnd();
 143.158 +//
 143.159 +//        if ((offset >= begin) && (offset <= end)) {
 143.160 +//            for (PythonTree child = node.getFirstChild(); child != null; child = child.getNext()) {
 143.161 +//                PythonTree found = find(child, offset);
 143.162 +//
 143.163 +//                if (found != null) {
 143.164 +//                    path.add(child);
 143.165 +//
 143.166 +//                    return found;
 143.167 +//                }
 143.168 +//            }
 143.169 +//
 143.170 +//            return node;
 143.171 +//        } else {
 143.172 +//        for (PythonTree child = node.getFirstChild(); child != null; child = child.getNext()) {
 143.173 +//                PythonTree found = find(child, offset);
 143.174 +//
 143.175 +//                if (found != null) {
 143.176 +//                    path.add(child);
 143.177 +//
 143.178 +//                    return found;
 143.179 +//                }
 143.180 +//            }
 143.181 +//
 143.182 +//            return null;
 143.183 +//        }
 143.184 +//    }
 143.185 +//
 143.186 +//    /**
 143.187 +//     * Find the path to the given node in the AST
 143.188 +//     */
 143.189 +//    @SuppressWarnings("unchecked")
 143.190 +//    public boolean find(PythonTree node, PythonTree target) {
 143.191 +//        if (node == target) {
 143.192 +//            return true;
 143.193 +//        }
 143.194 +//
 143.195 +//        for (PythonTree child = node.getFirstChild(); child != null; child = child.getNext()) {
 143.196 +//            boolean found = find(child, target);
 143.197 +//
 143.198 +//            if (found) {
 143.199 +//                path.add(child);
 143.200 +//
 143.201 +//                return found;
 143.202 +//            }
 143.203 +//        }
 143.204 +//
 143.205 +//        return false;
 143.206 +//    }
 143.207 +    @Override
 143.208 +    public String toString() {
 143.209 +        StringBuilder sb = new StringBuilder();
 143.210 +        sb.append("Path(");
 143.211 +        sb.append(path.size());
 143.212 +        sb.append(")=[");
 143.213 +
 143.214 +        for (PythonTree n : path) {
 143.215 +            String name = n.toString();
 143.216 +            name = name.substring(name.lastIndexOf('.') + 1);
 143.217 +            sb.append(name);
 143.218 +            sb.append(":");
 143.219 +        }
 143.220 +
 143.221 +        sb.append("]");
 143.222 +
 143.223 +        return sb.toString();
 143.224 +    }
 143.225 +
 143.226 +    public PythonTree leaf() {
 143.227 +        if (path.size() == 0) {
 143.228 +            return null;
 143.229 +        } else {
 143.230 +            return path.get(path.size() - 1);
 143.231 +        }
 143.232 +    }
 143.233 +
 143.234 +    public PythonTree leafParent() {
 143.235 +        if (path.size() < 2) {
 143.236 +            return null;
 143.237 +        } else {
 143.238 +            return path.get(path.size() - 2);
 143.239 +        }
 143.240 +    }
 143.241 +
 143.242 +    public PythonTree leafGrandParent() {
 143.243 +        if (path.size() < 3) {
 143.244 +            return null;
 143.245 +        } else {
 143.246 +            return path.get(path.size() - 3);
 143.247 +        }
 143.248 +    }
 143.249 +
 143.250 +    /**
 143.251 +     * Return the top/module level node -- this is not the module node
 143.252 +     * itself but the first node below it.
 143.253 +     */
 143.254 +    public PythonTree topModuleLevel() {
 143.255 +        if (path.size() >= 2) {
 143.256 +            return path.get(1);
 143.257 +        } else {
 143.258 +            return null;
 143.259 +        }
 143.260 +    }
 143.261 +
 143.262 +    public PythonTree root() {
 143.263 +        if (path.size() == 0) {
 143.264 +            return null;
 143.265 +        } else {
 143.266 +            return path.get(0);
 143.267 +        }
 143.268 +    }
 143.269 +
 143.270 +    /** Return an iterator that returns the elements from the leaf back up to the root */
 143.271 +    @Override
 143.272 +    public Iterator<PythonTree> iterator() {
 143.273 +        return new LeafToRootIterator(path);
 143.274 +    }
 143.275 +
 143.276 +    /** REturn an iterator that starts at the root and walks down to the leaf */
 143.277 +    public ListIterator<PythonTree> rootToLeaf() {
 143.278 +        return path.listIterator();
 143.279 +    }
 143.280 +
 143.281 +    /** Return an iterator that walks from the leaf back up to the root */
 143.282 +    public ListIterator<PythonTree> leafToRoot() {
 143.283 +        return new LeafToRootIterator(path);
 143.284 +    }
 143.285 +
 143.286 +    private static class LeafToRootIterator implements ListIterator<PythonTree> {
 143.287 +        private final ListIterator<PythonTree> it;
 143.288 +
 143.289 +        private LeafToRootIterator(ArrayList<PythonTree> path) {
 143.290 +            it = path.listIterator(path.size());
 143.291 +        }
 143.292 +
 143.293 +        @Override
 143.294 +        public boolean hasNext() {
 143.295 +            return it.hasPrevious();
 143.296 +        }
 143.297 +
 143.298 +        @Override
 143.299 +        public PythonTree next() {
 143.300 +            return it.previous();
 143.301 +        }
 143.302 +
 143.303 +        @Override
 143.304 +        public boolean hasPrevious() {
 143.305 +            return it.hasNext();
 143.306 +        }
 143.307 +
 143.308 +        @Override
 143.309 +        public PythonTree previous() {
 143.310 +            return it.next();
 143.311 +        }
 143.312 +
 143.313 +        @Override
 143.314 +        public int nextIndex() {
 143.315 +            return it.previousIndex();
 143.316 +        }
 143.317 +
 143.318 +        @Override
 143.319 +        public int previousIndex() {
 143.320 +            return it.nextIndex();
 143.321 +        }
 143.322 +
 143.323 +        @Override
 143.324 +        public void remove() {
 143.325 +            throw new UnsupportedOperationException("Not supported yet.");
 143.326 +        }
 143.327 +
 143.328 +        @Override
 143.329 +        public void set(PythonTree arg0) {
 143.330 +            throw new UnsupportedOperationException("Not supported yet.");
 143.331 +        }
 143.332 +
 143.333 +        @Override
 143.334 +        public void add(PythonTree arg0) {
 143.335 +            throw new UnsupportedOperationException("Not supported yet.");
 143.336 +        }
 143.337 +    }
 143.338 +
 143.339 +    private static class FindByOffsetVisitor extends Visitor {
 143.340 +        private int targetOffset;
 143.341 +        private ArrayList<PythonTree> path = new ArrayList<>();
 143.342 +
 143.343 +        private FindByOffsetVisitor(int targetOffset) {
 143.344 +            this.targetOffset = targetOffset;
 143.345 +        }
 143.346 +
 143.347 +        @Override
 143.348 +        public void traverse(PythonTree node) throws Exception {
 143.349 +            if (targetOffset >= node.getCharStartIndex() && targetOffset <= node.getCharStopIndex()) {
 143.350 +//                if (targetOffset == node.getCharStopIndex() && node.getClass() == FunctionDef.class) {
 143.351 +//                    // For functions, don't include the last offset, since we can end up with
 143.352 +//                    // functions that overlap - caret at the start position will add BOTH functions
 143.353 +//                    // which we don't want
 143.354 +//                } else {
 143.355 +                path.add(node);
 143.356 +//                }
 143.357 +                super.traverse(node);
 143.358 +            }
 143.359 +        }
 143.360 +
 143.361 +        AstPath getPath() {
 143.362 +            return new AstPath(path);
 143.363 +        }
 143.364 +    }
 143.365 +
 143.366 +    public static AstPath get(PythonTree root, int offset) {
 143.367 +        FindByOffsetVisitor finder = new FindByOffsetVisitor(offset);
 143.368 +        try {
 143.369 +            finder.visit(root);
 143.370 +            AstPath path = finder.getPath();
 143.371 +            if (path.path.size() == 0) {
 143.372 +                path.path.add(root);
 143.373 +            }
 143.374 +
 143.375 +            return path;
 143.376 +        } catch (Exception ex) {
 143.377 +            Exceptions.printStackTrace(ex);
 143.378 +        }
 143.379 +
 143.380 +        return null;
 143.381 +    }
 143.382 +
 143.383 +    private static class FindByNodeVisitor extends Visitor {
 143.384 +        private PythonTree target;
 143.385 +        private int startOffset;
 143.386 +        private int endOffset;
 143.387 +        private ArrayList<PythonTree> path = new ArrayList<>();
 143.388 +        private boolean found;
 143.389 +
 143.390 +        private FindByNodeVisitor(PythonTree target) {
 143.391 +            this.target = target;
 143.392 +            this.startOffset = target.getCharStartIndex();
 143.393 +            this.endOffset = target.getCharStopIndex();
 143.394 +        }
 143.395 +
 143.396 +        @Override
 143.397 +        public void traverse(PythonTree node) throws Exception {
 143.398 +            if (found) {
 143.399 +                return;
 143.400 +            }
 143.401 +            if (node == target) {
 143.402 +                path.add(node);
 143.403 +                found = true;
 143.404 +                return;
 143.405 +            }
 143.406 +            if (startOffset >= node.getCharStartIndex() && endOffset <= node.getCharStopIndex()) {
 143.407 +                path.add(node);
 143.408 +                node.traverse(this);
 143.409 +                if (found) {
 143.410 +                    return;
 143.411 +                }
 143.412 +                path.remove(path.size() - 1);
 143.413 +            }
 143.414 +        }
 143.415 +
 143.416 +        AstPath getPath() {
 143.417 +            return new AstPath(path);
 143.418 +        }
 143.419 +    }
 143.420 +
 143.421 +    /**
 143.422 +     * Find the path to the given node in the AST
 143.423 +     */
 143.424 +    public static AstPath get(PythonTree root, PythonTree target) {
 143.425 +        FindByNodeVisitor finder = new FindByNodeVisitor(target);
 143.426 +        try {
 143.427 +            finder.visit(root);
 143.428 +            AstPath path = finder.getPath();
 143.429 +            if (path.path.size() == 0) {
 143.430 +                path.path.add(root);
 143.431 +            }
 143.432 +
 143.433 +            return path;
 143.434 +        } catch (Exception ex) {
 143.435 +            Exceptions.printStackTrace(ex);
 143.436 +            return null;
 143.437 +        }
 143.438 +    }
 143.439 +}
   144.1 --- a/python.source/src/org/netbeans/modules/python/source/Bundle.properties	Sat Sep 12 23:03:15 2015 -0700
   144.2 +++ b/python.source/src/org/netbeans/modules/python/source/Bundle.properties	Sun Sep 13 11:47:42 2015 +0200
   144.3 @@ -1,1 +1,3 @@
   144.4  OpenIDE-Module-Name=Python Source
   144.5 +
   144.6 +NoPreference=No Preference
   145.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   145.2 +++ b/python.source/src/org/netbeans/modules/python/source/CodeStyle.java	Sun Sep 13 11:47:42 2015 +0200
   145.3 @@ -0,0 +1,738 @@
   145.4 +/*
   145.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   145.6 + *
   145.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   145.8 + *
   145.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  145.10 + * Other names may be trademarks of their respective owners.
  145.11 + *
  145.12 + * The contents of this file are subject to the terms of either the GNU
  145.13 + * General Public License Version 2 only ("GPL") or the Common
  145.14 + * Development and Distribution License("CDDL") (collectively, the
  145.15 + * "License"). You may not use this file except in compliance with the
  145.16 + * License. You can obtain a copy of the License at
  145.17 + * http://www.netbeans.org/cddl-gplv2.html
  145.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  145.19 + * specific language governing permissions and limitations under the
  145.20 + * License.  When distributing the software, include this License Header
  145.21 + * Notice in each file and include the License file at
  145.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  145.23 + * particular file as subject to the "Classpath" exception as provided
  145.24 + * by Oracle in the GPL Version 2 section of the License file that
  145.25 + * accompanied this code. If applicable, add the following below the
  145.26 + * License Header, with the fields enclosed by brackets [] replaced by
  145.27 + * your own identifying information:
  145.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  145.29 + *
  145.30 + * Contributor(s):
  145.31 + *
  145.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  145.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  145.34 + * Microsystems, Inc. All Rights Reserved.
  145.35 + *
  145.36 + * If you wish your version of this file to be governed by only the CDDL
  145.37 + * or only the GPL Version 2, indicate your decision by adding
  145.38 + * "[Contributor] elects to include this software in this distribution
  145.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  145.40 + * single choice of license, a recipient has the option to distribute
  145.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  145.42 + * to extend the choice of license to its licensees as provided above.
  145.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  145.44 + * Version 2 license, then the option applies only if the new code is
  145.45 + * made subject to such option by the copyright holder.
  145.46 + */
  145.47 +package org.netbeans.modules.python.source;
  145.48 +
  145.49 +import java.util.prefs.Preferences;
  145.50 +import javax.swing.text.Document;
  145.51 +import org.netbeans.modules.editor.indent.spi.CodeStylePreferences;
  145.52 +import org.netbeans.modules.python.source.ui.FmtOptions;
  145.53 +
  145.54 +import org.openide.filesystems.FileObject;
  145.55 +import static org.netbeans.modules.python.source.ui.FmtOptions.*;
  145.56 +
  145.57 +/** 
  145.58 + *  XXX make sure the getters get the defaults from somewhere
  145.59 + *  XXX add support for profiles
  145.60 + *  XXX get the preferences node from somewhere else in odrer to be able not to
  145.61 + *      use the getters and to be able to write to it.
  145.62 + * 
  145.63 + * @author Dusan Balek
  145.64 + */
  145.65 +public final class CodeStyle {
  145.66 +    static {
  145.67 +        FmtOptions.codeStyleProducer = new Producer();
  145.68 +    }
  145.69 +    private Preferences preferences;
  145.70 +
  145.71 +    private CodeStyle(Preferences preferences) {
  145.72 +        this.preferences = preferences;
  145.73 +    }
  145.74 +
  145.75 +//    /**
  145.76 +//     * Gets <code>CodeStyle</code> for files in the given project.
  145.77 +//     *
  145.78 +//     * <p>Please see the other two <code>getDefault</code> methods as they are
  145.79 +//     * the preferred way of getting <code>CodeStyle</code>.
  145.80 +//     *
  145.81 +//     * @param project The project to get the <code>CodeStyle</code> for.
  145.82 +//     * @return The current code style that would be used by documents opened
  145.83 +//     *   from files belonging to the <code>project</code>.
  145.84 +//     *
  145.85 +//     * @deprecated Please use {@link #getDefault(javax.swing.text.Document)}
  145.86 +//     *   or {@link #getDefault(org.openide.filesystems.FileObject)} respectively.
  145.87 +//     */
  145.88 +//    @Deprecated
  145.89 +//    public static CodeStyle getDefault(Project project) {
  145.90 +//        return getDefault(project.getProjectDirectory());
  145.91 +//    }
  145.92 +    /**
  145.93 +     * Gets <code>CodeStyle</code> for the given file. If you have a document
  145.94 +     * instance you should use the {@link #getDefault(javax.swing.text.Document)}
  145.95 +     * method.
  145.96 +     * 
  145.97 +     * @param file The file to get the <code>CodeStyle</code> for.
  145.98 +     * @return The current code style that would be used by a document if the
  145.99 +     *   <code>file</code> were opened in the editor.
 145.100 +     *
 145.101 +     * @since 0.39
 145.102 +     */
 145.103 +    public synchronized static CodeStyle getDefault(FileObject file) {
 145.104 +        Preferences prefs = CodeStylePreferences.get(file).getPreferences();
 145.105 +        return FmtOptions.codeStyleProducer.create(prefs);
 145.106 +    }
 145.107 +
 145.108 +    /**
 145.109 +     * Gets <code>CodeStyle</code> for the given document. This is the preferred
 145.110 +     * method of getting <code>CodeStyle</code>. If you don't have a document
 145.111 +     * you can use {@link #getDefault(org.openide.filesystems.FileObject)} method instead.
 145.112 +     *
 145.113 +     * @param doc The document to get the <code>CodeStyle</code> for.
 145.114 +     * @return The current code style used by a document. This is the code style that
 145.115 +     *   will be used when formatting the document or generating new code.
 145.116 +     * 
 145.117 +     * @since 0.39
 145.118 +     */
 145.119 +    public synchronized static CodeStyle getDefault(Document doc) {
 145.120 +        Preferences prefs = CodeStylePreferences.get(doc).getPreferences();
 145.121 +        return FmtOptions.codeStyleProducer.create(prefs);
 145.122 +    }
 145.123 +
 145.124 +    // General tabs and indents ------------------------------------------------
 145.125 +    public boolean expandTabToSpaces() {
 145.126 +//        System.out.println("~~~ expand-tabs=" + preferences.get(SimpleValueNames.EXPAND_TABS, null));
 145.127 +        return preferences.getBoolean(expandTabToSpaces, getDefaultAsBoolean(expandTabToSpaces));
 145.128 +    }
 145.129 +
 145.130 +    public int getTabSize() {
 145.131 +//        System.out.println("~~~ tab-size=" + preferences.get(SimpleValueNames.TAB_SIZE, null));
 145.132 +        return preferences.getInt(tabSize, getDefaultAsInt(tabSize));
 145.133 +    }
 145.134 +
 145.135 +    public int getIndentSize() {
 145.136 +//        System.out.println("~~~ indent-shift-width=" + preferences.get(SimpleValueNames.INDENT_SHIFT_WIDTH, null));
 145.137 +        int indentLevel = preferences.getInt(indentSize, getDefaultAsInt(indentSize));
 145.138 +
 145.139 +        if (indentLevel <= 0) {
 145.140 +//            System.out.println("~~~ expand-tabs=" + preferences.get(SimpleValueNames.EXPAND_TABS, null));
 145.141 +            boolean expandTabs = preferences.getBoolean(expandTabToSpaces, getDefaultAsBoolean(expandTabToSpaces));
 145.142 +            if (expandTabs) {
 145.143 +//                System.out.println("~~~ spaces-per-tab=" + preferences.get(SimpleValueNames.SPACES_PER_TAB, null));
 145.144 +                indentLevel = preferences.getInt(spacesPerTab, getDefaultAsInt(spacesPerTab));
 145.145 +            } else {
 145.146 +//                System.out.println("~~~ tab-size=" + preferences.get(SimpleValueNames.TAB_SIZE, null));
 145.147 +                indentLevel = preferences.getInt(tabSize, getDefaultAsInt(tabSize));
 145.148 +            }
 145.149 +        }
 145.150 +
 145.151 +        return indentLevel;
 145.152 +    }
 145.153 +
 145.154 +    public int getContinuationIndentSize() {
 145.155 +        return preferences.getInt(continuationIndentSize, getDefaultAsInt(continuationIndentSize));
 145.156 +    }
 145.157 +
 145.158 +    public int getLabelIndent() {
 145.159 +        return preferences.getInt(labelIndent, getDefaultAsInt(labelIndent));
 145.160 +    }
 145.161 +
 145.162 +    public boolean absoluteLabelIndent() {
 145.163 +        return preferences.getBoolean(absoluteLabelIndent, getDefaultAsBoolean(absoluteLabelIndent));
 145.164 +    }
 145.165 +
 145.166 +    public boolean indentTopLevelClassMembers() {
 145.167 +        return preferences.getBoolean(indentTopLevelClassMembers, getDefaultAsBoolean(indentTopLevelClassMembers));
 145.168 +    }
 145.169 +
 145.170 +    public boolean indentCasesFromSwitch() {
 145.171 +        return preferences.getBoolean(indentCasesFromSwitch, getDefaultAsBoolean(indentCasesFromSwitch));
 145.172 +    }
 145.173 +
 145.174 +    public int getRightMargin() {
 145.175 +        return preferences.getInt(rightMargin, getDefaultAsInt(rightMargin));
 145.176 +    }
 145.177 +
 145.178 +    /*
 145.179 +    public boolean addLeadingStarInComment() {
 145.180 +    return preferences.getBoolean(addLeadingStarInComment, getDefaultAsBoolean(addLeadingStarInComment));
 145.181 +    }
 145.182 +
 145.183 +    // Code generation ---------------------------------------------------------
 145.184 +    
 145.185 +    public boolean preferLongerNames() {
 145.186 +    return preferences.getBoolean(preferLongerNames, getDefaultAsBoolean(preferLongerNames));
 145.187 +    }
 145.188 +
 145.189 +    public String getFieldNamePrefix() {
 145.190 +    return preferences.get(fieldNamePrefix, getDefaultAsString(fieldNamePrefix));
 145.191 +    }
 145.192 +
 145.193 +    public String getFieldNameSuffix() {
 145.194 +    return preferences.get(fieldNameSuffix, getDefaultAsString(fieldNameSuffix));
 145.195 +    }
 145.196 +
 145.197 +    public String getStaticFieldNamePrefix() {
 145.198 +    return preferences.get(staticFieldNamePrefix, getDefaultAsString(staticFieldNamePrefix));
 145.199 +    }
 145.200 +
 145.201 +    public String getStaticFieldNameSuffix() {
 145.202 +    return preferences.get(staticFieldNameSuffix, getDefaultAsString(staticFieldNameSuffix));
 145.203 +    }
 145.204 +
 145.205 +    public String getParameterNamePrefix() {
 145.206 +    return preferences.get(parameterNamePrefix, getDefaultAsString(parameterNamePrefix));
 145.207 +    }
 145.208 +
 145.209 +    public String getParameterNameSuffix() {
 145.210 +    return preferences.get(parameterNameSuffix, getDefaultAsString(parameterNameSuffix));
 145.211 +    }
 145.212 +
 145.213 +    public String getLocalVarNamePrefix() {
 145.214 +    return preferences.get(localVarNamePrefix, getDefaultAsString(localVarNamePrefix));
 145.215 +    }
 145.216 +
 145.217 +    public String getLocalVarNameSuffix() {
 145.218 +    return preferences.get(localVarNameSuffix, getDefaultAsString(localVarNameSuffix));
 145.219 +    }
 145.220 +
 145.221 +    public boolean qualifyFieldAccess() {
 145.222 +    return preferences.getBoolean(qualifyFieldAccess, getDefaultAsBoolean(qualifyFieldAccess));
 145.223 +    }
 145.224 +
 145.225 +    public boolean useIsForBooleanGetters() {
 145.226 +    return preferences.getBoolean(useIsForBooleanGetters, getDefaultAsBoolean(useIsForBooleanGetters));
 145.227 +    }
 145.228 +
 145.229 +    public boolean addOverrideAnnotation() {
 145.230 +    return preferences.getBoolean(addOverrideAnnotation, getDefaultAsBoolean(addOverrideAnnotation));
 145.231 +    }
 145.232 +
 145.233 +    public boolean makeLocalVarsFinal() {
 145.234 +    return preferences.getBoolean(makeLocalVarsFinal, getDefaultAsBoolean(makeLocalVarsFinal));
 145.235 +    }
 145.236 +
 145.237 +    // Alignment ----------------------------------------------------
 145.238 +    
 145.239 +    public boolean alignMultilineMethodParams() {
 145.240 +    return preferences.getBoolean(alignMultilineMethodParams, getDefaultAsBoolean(alignMultilineMethodParams));
 145.241 +    }
 145.242 +
 145.243 +    public boolean alignMultilineCallArgs() {
 145.244 +    return preferences.getBoolean(alignMultilineCallArgs, getDefaultAsBoolean(alignMultilineCallArgs));
 145.245 +    }
 145.246 +
 145.247 +    public boolean alignMultilineAnnotationArgs() {
 145.248 +    return preferences.getBoolean(alignMultilineAnnotationArgs, getDefaultAsBoolean(alignMultilineAnnotationArgs));
 145.249 +    }
 145.250 +
 145.251 +    public boolean alignMultilineImplements() {
 145.252 +    return preferences.getBoolean(alignMultilineImplements, getDefaultAsBoolean(alignMultilineImplements));
 145.253 +    }
 145.254 +
 145.255 +    public boolean alignMultilineThrows() {
 145.256 +    return preferences.getBoolean(alignMultilineThrows, getDefaultAsBoolean(alignMultilineThrows));
 145.257 +    }
 145.258 +
 145.259 +    public boolean alignMultilineParenthesized() {
 145.260 +    return preferences.getBoolean(alignMultilineParenthesized, getDefaultAsBoolean(alignMultilineParenthesized));
 145.261 +    }
 145.262 +
 145.263 +    public boolean alignMultilineBinaryOp() {
 145.264 +    return preferences.getBoolean(alignMultilineBinaryOp, getDefaultAsBoolean(alignMultilineBinaryOp));
 145.265 +    }
 145.266 +
 145.267 +    public boolean alignMultilineTernaryOp() {
 145.268 +    return preferences.getBoolean(alignMultilineTernaryOp, getDefaultAsBoolean(alignMultilineTernaryOp));
 145.269 +    }
 145.270 +
 145.271 +    public boolean alignMultilineAssignment() {
 145.272 +    return preferences.getBoolean(alignMultilineAssignment, getDefaultAsBoolean(alignMultilineAssignment));
 145.273 +    }
 145.274 +
 145.275 +    public boolean alignMultilineFor() {
 145.276 +    return preferences.getBoolean(alignMultilineFor, getDefaultAsBoolean(alignMultilineFor));
 145.277 +    }
 145.278 +
 145.279 +    public boolean alignMultilineArrayInit() {
 145.280 +    return preferences.getBoolean(alignMultilineArrayInit, getDefaultAsBoolean(alignMultilineArrayInit));
 145.281 +    }
 145.282 +
 145.283 +    public boolean placeElseOnNewLine() {
 145.284 +    return preferences.getBoolean(placeElseOnNewLine, getDefaultAsBoolean(placeElseOnNewLine));
 145.285 +    }
 145.286 +
 145.287 +    public boolean placeWhileOnNewLine() {
 145.288 +    return preferences.getBoolean(placeWhileOnNewLine, getDefaultAsBoolean(placeWhileOnNewLine));
 145.289 +    }
 145.290 +
 145.291 +    public boolean placeCatchOnNewLine() {
 145.292 +    return preferences.getBoolean(placeCatchOnNewLine, getDefaultAsBoolean(placeCatchOnNewLine));
 145.293 +    }
 145.294 +
 145.295 +    public boolean placeFinallyOnNewLine() {
 145.296 +    return preferences.getBoolean(placeFinallyOnNewLine, getDefaultAsBoolean(placeFinallyOnNewLine));
 145.297 +    }
 145.298 +    
 145.299 +    public boolean placeNewLineAfterModifiers() {
 145.300 +    return preferences.getBoolean(placeNewLineAfterModifiers, getDefaultAsBoolean(placeNewLineAfterModifiers));
 145.301 +    }
 145.302 +
 145.303 +    // Wrapping ----------------------------------------------------------------
 145.304 +    
 145.305 +    public WrapStyle wrapExtendsImplementsKeyword() {
 145.306 +    String wrap = preferences.get(wrapExtendsImplementsKeyword, getDefaultAsString(wrapExtendsImplementsKeyword));
 145.307 +    return WrapStyle.valueOf(wrap);
 145.308 +    }
 145.309 +
 145.310 +    public WrapStyle wrapExtendsImplementsList() {
 145.311 +    String wrap = preferences.get(wrapExtendsImplementsList, getDefaultAsString(wrapExtendsImplementsList));
 145.312 +    return WrapStyle.valueOf(wrap);
 145.313 +    }
 145.314 +
 145.315 +    public WrapStyle wrapMethodParams() {
 145.316 +    String wrap = preferences.get(wrapMethodParams, getDefaultAsString(wrapMethodParams));
 145.317 +    return WrapStyle.valueOf(wrap);
 145.318 +    }
 145.319 +
 145.320 +    public WrapStyle wrapThrowsKeyword() {
 145.321 +    String wrap = preferences.get(wrapThrowsKeyword, getDefaultAsString(wrapThrowsKeyword));
 145.322 +    return WrapStyle.valueOf(wrap);
 145.323 +    }
 145.324 +
 145.325 +    public WrapStyle wrapThrowsList() {
 145.326 +    String wrap = preferences.get(wrapThrowsList, getDefaultAsString(wrapThrowsList));
 145.327 +    return WrapStyle.valueOf(wrap);
 145.328 +    }
 145.329 +
 145.330 +    public WrapStyle wrapMethodCallArgs() {
 145.331 +    String wrap = preferences.get(wrapMethodCallArgs, getDefaultAsString(wrapMethodCallArgs));
 145.332 +    return WrapStyle.valueOf(wrap);
 145.333 +    }
 145.334 +
 145.335 +    public WrapStyle wrapAnnotationArgs() {
 145.336 +    String wrap = preferences.get(wrapAnnotationArgs, getDefaultAsString(wrapAnnotationArgs));
 145.337 +    return WrapStyle.valueOf(wrap);
 145.338 +    }
 145.339 +
 145.340 +    public WrapStyle wrapChainedMethodCalls() {
 145.341 +    String wrap = preferences.get(wrapChainedMethodCalls, getDefaultAsString(wrapChainedMethodCalls));
 145.342 +    return WrapStyle.valueOf(wrap);
 145.343 +    }
 145.344 +
 145.345 +    public WrapStyle wrapArrayInit() {
 145.346 +    String wrap = preferences.get(wrapArrayInit, getDefaultAsString(wrapArrayInit));
 145.347 +    return WrapStyle.valueOf(wrap);
 145.348 +    }
 145.349 +
 145.350 +    public WrapStyle wrapFor() {
 145.351 +    String wrap = preferences.get(wrapFor, getDefaultAsString(wrapFor));
 145.352 +    return WrapStyle.valueOf(wrap);
 145.353 +    }
 145.354 +
 145.355 +    public WrapStyle wrapForStatement() {
 145.356 +    String wrap = preferences.get(wrapForStatement, getDefaultAsString(wrapForStatement));
 145.357 +    return WrapStyle.valueOf(wrap);
 145.358 +    }
 145.359 +
 145.360 +    public WrapStyle wrapIfStatement() {
 145.361 +    String wrap = preferences.get(wrapIfStatement, getDefaultAsString(wrapIfStatement));
 145.362 +    return WrapStyle.valueOf(wrap);
 145.363 +    }
 145.364 +
 145.365 +    public WrapStyle wrapWhileStatement() {
 145.366 +    String wrap = preferences.get(wrapWhileStatement, getDefaultAsString(wrapWhileStatement));
 145.367 +    return WrapStyle.valueOf(wrap);
 145.368 +    }
 145.369 +
 145.370 +    public WrapStyle wrapDoWhileStatement() {
 145.371 +    String wrap = preferences.get(wrapDoWhileStatement, getDefaultAsString(wrapDoWhileStatement));
 145.372 +    return WrapStyle.valueOf(wrap);
 145.373 +    }
 145.374 +
 145.375 +    public WrapStyle wrapAssert() {
 145.376 +    String wrap = preferences.get(wrapAssert, getDefaultAsString(wrapAssert));
 145.377 +    return WrapStyle.valueOf(wrap);
 145.378 +    }
 145.379 +
 145.380 +    public WrapStyle wrapEnumConstants() {
 145.381 +    String wrap = preferences.get(wrapEnumConstants, getDefaultAsString(wrapEnumConstants));
 145.382 +    return WrapStyle.valueOf(wrap);
 145.383 +    }
 145.384 +
 145.385 +    public WrapStyle wrapAnnotations() {
 145.386 +    String wrap = preferences.get(wrapAnnotations, getDefaultAsString(wrapAnnotations));
 145.387 +    return WrapStyle.valueOf(wrap);
 145.388 +    }
 145.389 +
 145.390 +    public WrapStyle wrapBinaryOps() {
 145.391 +    String wrap = preferences.get(wrapBinaryOps, getDefaultAsString(wrapBinaryOps));
 145.392 +    return WrapStyle.valueOf(wrap);
 145.393 +    }
 145.394 +
 145.395 +    public WrapStyle wrapTernaryOps() {
 145.396 +    String wrap = preferences.get(wrapTernaryOps, getDefaultAsString(wrapTernaryOps));
 145.397 +    return WrapStyle.valueOf(wrap);
 145.398 +    }
 145.399 +
 145.400 +    public WrapStyle wrapAssignOps() {
 145.401 +    String wrap = preferences.get(wrapAssignOps, getDefaultAsString(wrapAssignOps));
 145.402 +    return WrapStyle.valueOf(wrap);
 145.403 +    }
 145.404 +
 145.405 +    // Blank lines -------------------------------------------------------------
 145.406 +    
 145.407 +    public int getBlankLinesBeforePackage() {
 145.408 +    return preferences.getInt(blankLinesBeforePackage, getDefaultAsInt(blankLinesBeforePackage));
 145.409 +    }
 145.410 +
 145.411 +    public int getBlankLinesAfterPackage() {
 145.412 +    return preferences.getInt(blankLinesAfterPackage, getDefaultAsInt(blankLinesAfterPackage));
 145.413 +    }
 145.414 +
 145.415 +    public int getBlankLinesBeforeImports() {
 145.416 +    return preferences.getInt(blankLinesBeforeImports, getDefaultAsInt(blankLinesBeforeImports));
 145.417 +    }
 145.418 +
 145.419 +    public int getBlankLinesAfterImports() {
 145.420 +    return preferences.getInt(blankLinesAfterImports, getDefaultAsInt(blankLinesAfterImports));
 145.421 +    }
 145.422 +
 145.423 +    public int getBlankLinesBeforeClass() {
 145.424 +    return preferences.getInt(blankLinesBeforeClass, getDefaultAsInt(blankLinesBeforeClass));
 145.425 +    }
 145.426 +
 145.427 +    public int getBlankLinesAfterClass() {
 145.428 +    return preferences.getInt(blankLinesAfterClass, getDefaultAsInt(blankLinesAfterClass));
 145.429 +    }
 145.430 +
 145.431 +    public int getBlankLinesAfterClassHeader() {
 145.432 +    return preferences.getInt(blankLinesAfterClassHeader, getDefaultAsInt(blankLinesAfterClassHeader));
 145.433 +    }
 145.434 +
 145.435 +    public int getBlankLinesBeforeFields() {
 145.436 +    return preferences.getInt(blankLinesBeforeFields, getDefaultAsInt(blankLinesBeforeFields));
 145.437 +    }
 145.438 +
 145.439 +    public int getBlankLinesAfterFields() {
 145.440 +    return preferences.getInt(blankLinesAfterFields, getDefaultAsInt(blankLinesAfterFields));
 145.441 +    }
 145.442 +
 145.443 +    public int getBlankLinesBeforeMethods() {
 145.444 +    return preferences.getInt(blankLinesBeforeMethods, getDefaultAsInt(blankLinesBeforeMethods));
 145.445 +    }
 145.446 +
 145.447 +    public int getBlankLinesAfterMethods() {
 145.448 +    return preferences.getInt(blankLinesAfterMethods, getDefaultAsInt(blankLinesAfterMethods));
 145.449 +    }
 145.450 +
 145.451 +    // Spaces ------------------------------------------------------------------
 145.452 +    
 145.453 +    public boolean spaceBeforeWhile() {
 145.454 +    return preferences.getBoolean(spaceBeforeWhile, getDefaultAsBoolean(spaceBeforeWhile));
 145.455 +    }
 145.456 +
 145.457 +    public boolean spaceBeforeElse() {
 145.458 +    return preferences.getBoolean(spaceBeforeElse, getDefaultAsBoolean(spaceBeforeElse));
 145.459 +    }
 145.460 +
 145.461 +    public boolean spaceBeforeCatch() {
 145.462 +    return preferences.getBoolean(spaceBeforeCatch, getDefaultAsBoolean(spaceBeforeCatch));
 145.463 +    }
 145.464 +
 145.465 +    public boolean spaceBeforeFinally() {
 145.466 +    return preferences.getBoolean(spaceBeforeFinally, getDefaultAsBoolean(spaceBeforeFinally));
 145.467 +    }
 145.468 +
 145.469 +    public boolean spaceBeforeMethodDeclParen() {
 145.470 +    return preferences.getBoolean(spaceBeforeMethodDeclParen, getDefaultAsBoolean(spaceBeforeMethodDeclParen));
 145.471 +    }
 145.472 +
 145.473 +    public boolean spaceBeforeMethodCallParen() {
 145.474 +    return preferences.getBoolean(spaceBeforeMethodCallParen, getDefaultAsBoolean(spaceBeforeMethodCallParen));
 145.475 +    }
 145.476 +
 145.477 +    public boolean spaceBeforeIfParen() {
 145.478 +    return preferences.getBoolean(spaceBeforeIfParen, getDefaultAsBoolean(spaceBeforeIfParen));
 145.479 +    }
 145.480 +
 145.481 +    public boolean spaceBeforeForParen() {
 145.482 +    return preferences.getBoolean(spaceBeforeForParen, getDefaultAsBoolean(spaceBeforeForParen));
 145.483 +    }
 145.484 +
 145.485 +    public boolean spaceBeforeWhileParen() {
 145.486 +    return preferences.getBoolean(spaceBeforeWhileParen, getDefaultAsBoolean(spaceBeforeWhileParen));
 145.487 +    }
 145.488 +
 145.489 +    public boolean spaceBeforeCatchParen() {
 145.490 +    return preferences.getBoolean(spaceBeforeCatchParen, getDefaultAsBoolean(spaceBeforeCatchParen));
 145.491 +    }
 145.492 +
 145.493 +    public boolean spaceBeforeSwitchParen() {
 145.494 +    return preferences.getBoolean(spaceBeforeSwitchParen, getDefaultAsBoolean(spaceBeforeSwitchParen));
 145.495 +    }
 145.496 +
 145.497 +    public boolean spaceBeforeSynchronizedParen() {
 145.498 +    return preferences.getBoolean(spaceBeforeSynchronizedParen, getDefaultAsBoolean(spaceBeforeSynchronizedParen));
 145.499 +    }
 145.500 +
 145.501 +    public boolean spaceBeforeAnnotationParen() {
 145.502 +    return preferences.getBoolean(spaceBeforeAnnotationParen, getDefaultAsBoolean(spaceBeforeAnnotationParen));
 145.503 +    }
 145.504 +
 145.505 +    public boolean spaceAroundUnaryOps() {
 145.506 +    return preferences.getBoolean(spaceAroundUnaryOps, getDefaultAsBoolean(spaceAroundUnaryOps));
 145.507 +    }
 145.508 +
 145.509 +    public boolean spaceAroundBinaryOps() {
 145.510 +    return preferences.getBoolean(spaceAroundBinaryOps, getDefaultAsBoolean(spaceAroundBinaryOps));
 145.511 +    }
 145.512 +
 145.513 +    public boolean spaceAroundTernaryOps() {
 145.514 +    return preferences.getBoolean(spaceAroundTernaryOps, getDefaultAsBoolean(spaceAroundTernaryOps));
 145.515 +    }
 145.516 +
 145.517 +    public boolean spaceAroundAssignOps() {
 145.518 +    return preferences.getBoolean(spaceAroundAssignOps, getDefaultAsBoolean(spaceAroundAssignOps));
 145.519 +    }
 145.520 +
 145.521 +    public boolean spaceBeforeClassDeclLeftBrace() {
 145.522 +    return preferences.getBoolean(spaceBeforeClassDeclLeftBrace, getDefaultAsBoolean(spaceBeforeClassDeclLeftBrace));
 145.523 +    }
 145.524 +
 145.525 +    public boolean spaceBeforeMethodDeclLeftBrace() {
 145.526 +    return preferences.getBoolean(spaceBeforeMethodDeclLeftBrace, getDefaultAsBoolean(spaceBeforeMethodDeclLeftBrace));
 145.527 +    }
 145.528 +
 145.529 +    public boolean spaceBeforeIfLeftBrace() {
 145.530 +    return preferences.getBoolean(spaceBeforeIfLeftBrace, getDefaultAsBoolean(spaceBeforeIfLeftBrace));
 145.531 +    }
 145.532 +
 145.533 +    public boolean spaceBeforeElseLeftBrace() {
 145.534 +    return preferences.getBoolean(spaceBeforeElseLeftBrace, getDefaultAsBoolean(spaceBeforeElseLeftBrace));
 145.535 +    }
 145.536 +
 145.537 +    public boolean spaceBeforeWhileLeftBrace() {
 145.538 +    return preferences.getBoolean(spaceBeforeWhileLeftBrace, getDefaultAsBoolean(spaceBeforeWhileLeftBrace));
 145.539 +    }
 145.540 +
 145.541 +    public boolean spaceBeforeForLeftBrace() {
 145.542 +    return preferences.getBoolean(spaceBeforeForLeftBrace, getDefaultAsBoolean(spaceBeforeForLeftBrace));
 145.543 +    }
 145.544 +
 145.545 +    public boolean spaceBeforeDoLeftBrace() {
 145.546 +    return preferences.getBoolean(spaceBeforeDoLeftBrace, getDefaultAsBoolean(spaceBeforeDoLeftBrace));
 145.547 +    }
 145.548 +
 145.549 +    public boolean spaceBeforeSwitchLeftBrace() {
 145.550 +    return preferences.getBoolean(spaceBeforeSwitchLeftBrace, getDefaultAsBoolean(spaceBeforeSwitchLeftBrace));
 145.551 +    }
 145.552 +
 145.553 +    public boolean spaceBeforeTryLeftBrace() {
 145.554 +    return preferences.getBoolean(spaceBeforeTryLeftBrace, getDefaultAsBoolean(spaceBeforeTryLeftBrace));
 145.555 +    }
 145.556 +
 145.557 +    public boolean spaceBeforeCatchLeftBrace() {
 145.558 +    return preferences.getBoolean(spaceBeforeCatchLeftBrace, getDefaultAsBoolean(spaceBeforeCatchLeftBrace));
 145.559 +    }
 145.560 +
 145.561 +    public boolean spaceBeforeFinallyLeftBrace() {
 145.562 +    return preferences.getBoolean(spaceBeforeFinallyLeftBrace, getDefaultAsBoolean(spaceBeforeFinallyLeftBrace));
 145.563 +    }
 145.564 +
 145.565 +    public boolean spaceBeforeSynchronizedLeftBrace() {
 145.566 +    return preferences.getBoolean(spaceBeforeSynchronizedLeftBrace, getDefaultAsBoolean(spaceBeforeSynchronizedLeftBrace));
 145.567 +    }
 145.568 +
 145.569 +    public boolean spaceBeforeStaticInitLeftBrace() {
 145.570 +    return preferences.getBoolean(spaceBeforeStaticInitLeftBrace, getDefaultAsBoolean(spaceBeforeStaticInitLeftBrace));
 145.571 +    }
 145.572 +
 145.573 +    public boolean spaceBeforeArrayInitLeftBrace() {
 145.574 +    return preferences.getBoolean(spaceBeforeArrayInitLeftBrace, getDefaultAsBoolean(spaceBeforeArrayInitLeftBrace));
 145.575 +    }
 145.576 +
 145.577 +    public boolean spaceWithinParens() {
 145.578 +    return preferences.getBoolean(spaceWithinParens, getDefaultAsBoolean(spaceWithinParens));
 145.579 +    }
 145.580 +
 145.581 +    public boolean spaceWithinMethodDeclParens() {
 145.582 +    return preferences.getBoolean(spaceWithinMethodDeclParens, getDefaultAsBoolean(spaceWithinMethodDeclParens));
 145.583 +    }
 145.584 +
 145.585 +    public boolean spaceWithinMethodCallParens() {
 145.586 +    return preferences.getBoolean(spaceWithinMethodCallParens, getDefaultAsBoolean(spaceWithinMethodCallParens));
 145.587 +    }
 145.588 +
 145.589 +    public boolean spaceWithinIfParens() {
 145.590 +    return preferences.getBoolean(spaceWithinIfParens, getDefaultAsBoolean(spaceWithinIfParens));
 145.591 +    }
 145.592 +
 145.593 +    public boolean spaceWithinForParens() {
 145.594 +    return preferences.getBoolean(spaceWithinForParens, getDefaultAsBoolean(spaceWithinForParens));
 145.595 +    }
 145.596 +
 145.597 +    public boolean spaceWithinWhileParens() {
 145.598 +    return preferences.getBoolean(spaceWithinWhileParens, getDefaultAsBoolean(spaceWithinWhileParens));
 145.599 +    }
 145.600 +
 145.601 +    public boolean spaceWithinSwitchParens() {
 145.602 +    return preferences.getBoolean(spaceWithinSwitchParens, getDefaultAsBoolean(spaceWithinSwitchParens));
 145.603 +    }
 145.604 +
 145.605 +    public boolean spaceWithinCatchParens() {
 145.606 +    return preferences.getBoolean(spaceWithinCatchParens, getDefaultAsBoolean(spaceWithinCatchParens));
 145.607 +    }
 145.608 +
 145.609 +    public boolean spaceWithinSynchronizedParens() {
 145.610 +    return preferences.getBoolean(spaceWithinSynchronizedParens, getDefaultAsBoolean(spaceWithinSynchronizedParens));
 145.611 +    }
 145.612 +
 145.613 +    public boolean spaceWithinTypeCastParens() {
 145.614 +    return preferences.getBoolean(spaceWithinTypeCastParens, getDefaultAsBoolean(spaceWithinTypeCastParens));
 145.615 +    }
 145.616 +
 145.617 +    public boolean spaceWithinAnnotationParens() {
 145.618 +    return preferences.getBoolean(spaceWithinAnnotationParens, getDefaultAsBoolean(spaceWithinAnnotationParens));
 145.619 +    }
 145.620 +
 145.621 +    public boolean spaceWithinBraces() {
 145.622 +    return preferences.getBoolean(spaceWithinBraces, getDefaultAsBoolean(spaceWithinBraces));
 145.623 +    }
 145.624 +
 145.625 +    public boolean spaceWithinArrayInitBrackets() {
 145.626 +    return preferences.getBoolean(spaceWithinArrayInitBrackets, getDefaultAsBoolean(spaceWithinArrayInitBrackets));
 145.627 +    }
 145.628 +
 145.629 +    public boolean spaceBeforeComma() {
 145.630 +    return preferences.getBoolean(spaceBeforeComma, getDefaultAsBoolean(spaceBeforeComma));
 145.631 +    }
 145.632 +
 145.633 +    public boolean spaceAfterComma() {
 145.634 +    return preferences.getBoolean(spaceAfterComma, getDefaultAsBoolean(spaceAfterComma));
 145.635 +    }
 145.636 +
 145.637 +    public boolean spaceBeforeSemi() {
 145.638 +    return preferences.getBoolean(spaceBeforeSemi, getDefaultAsBoolean(spaceBeforeSemi));
 145.639 +    }
 145.640 +
 145.641 +    public boolean spaceAfterSemi() {
 145.642 +    return preferences.getBoolean(spaceAfterSemi, getDefaultAsBoolean(spaceAfterSemi));
 145.643 +    }
 145.644 +
 145.645 +    public boolean spaceBeforeColon() {
 145.646 +    return preferences.getBoolean(spaceBeforeColon, getDefaultAsBoolean(spaceBeforeColon));
 145.647 +    }
 145.648 +
 145.649 +    public boolean spaceAfterColon() {
 145.650 +    return preferences.getBoolean(spaceAfterColon, getDefaultAsBoolean(spaceAfterColon));
 145.651 +    }
 145.652 +
 145.653 +    public boolean spaceAfterTypeCast() {
 145.654 +    return preferences.getBoolean(spaceAfterTypeCast, getDefaultAsBoolean(spaceAfterTypeCast));
 145.655 +    }
 145.656 +
 145.657 +     */
 145.658 +    // Spaces -----------------------------------------------------------------
 145.659 +    public boolean addSpaceAroundOperators() {
 145.660 +        return preferences.getBoolean(addSpaceAroundOperators, getDefaultAsBoolean(addSpaceAroundOperators));
 145.661 +    }
 145.662 +
 145.663 +    public boolean removeSpaceInsideParens() {
 145.664 +        return preferences.getBoolean(removeSpaceInParens, getDefaultAsBoolean(removeSpaceInParens));
 145.665 +    }
 145.666 +
 145.667 +    public boolean addSpaceAfterComma() {
 145.668 +        return preferences.getBoolean(addSpaceAfterComma, getDefaultAsBoolean(addSpaceAfterComma));
 145.669 +    }
 145.670 +
 145.671 +    public boolean removeSpaceBeforeSep() {
 145.672 +        return preferences.getBoolean(removeSpaceBeforeSep, getDefaultAsBoolean(removeSpaceBeforeSep));
 145.673 +    }
 145.674 +
 145.675 +    public boolean removeSpaceInParamAssign() {
 145.676 +        return preferences.getBoolean(removeSpaceInParamAssign, getDefaultAsBoolean(removeSpaceInParamAssign));
 145.677 +    }
 145.678 +
 145.679 +    public boolean collapseSpaces() {
 145.680 +        return preferences.getBoolean(collapseSpaces, getDefaultAsBoolean(collapseSpaces));
 145.681 +    }
 145.682 +
 145.683 +    // Imports -----------------------------------------------------------------
 145.684 +    public boolean formatImports() {
 145.685 +        return preferences.getBoolean(formatImports, getDefaultAsBoolean(formatImports));
 145.686 +    }
 145.687 +
 145.688 +    public boolean oneImportPerLine() {
 145.689 +        return preferences.getBoolean(oneImportPerLine, getDefaultAsBoolean(oneImportPerLine));
 145.690 +    }
 145.691 +
 145.692 +    public boolean removeDuplicates() {
 145.693 +        return preferences.getBoolean(removeDuplicates, getDefaultAsBoolean(removeDuplicates));
 145.694 +    }
 145.695 +
 145.696 +    public boolean systemLibsFirst() {
 145.697 +        return preferences.getBoolean(systemLibsFirst, getDefaultAsBoolean(systemLibsFirst));
 145.698 +    }
 145.699 +
 145.700 +    public boolean preferSymbolImports() {
 145.701 +        return preferences.getBoolean(preferSymbolImports, getDefaultAsBoolean(preferSymbolImports));
 145.702 +    }
 145.703 +
 145.704 +    public boolean sortImports() {
 145.705 +        return preferences.getBoolean(sortImports, getDefaultAsBoolean(sortImports));
 145.706 +    }
 145.707 +
 145.708 +    public boolean separateFromImps() {
 145.709 +        return preferences.getBoolean(separateFromImps, getDefaultAsBoolean(separateFromImps));
 145.710 +    }
 145.711 +
 145.712 +    public ImportCleanupStyle cleanupImports() {
 145.713 +        String cleanup = preferences.get(cleanupUnusedImports, getDefaultAsString(cleanupUnusedImports));
 145.714 +        return ImportCleanupStyle.valueOf(cleanup);
 145.715 +    }
 145.716 +
 145.717 +    public String[] getPackagesForStarImport() {
 145.718 +        return null;
 145.719 +    }
 145.720 +
 145.721 +    // Nested classes ----------------------------------------------------------
 145.722 +    public enum WrapStyle {
 145.723 +        WRAP_ALWAYS,
 145.724 +        WRAP_IF_LONG,
 145.725 +        WRAP_NEVER
 145.726 +    }
 145.727 +
 145.728 +    public enum ImportCleanupStyle {
 145.729 +        LEAVE_ALONE,
 145.730 +        COMMENT_OUT,
 145.731 +        DELETE
 145.732 +    }
 145.733 +
 145.734 +    // Communication with non public packages ----------------------------------
 145.735 +    private static class Producer implements FmtOptions.CodeStyleProducer {
 145.736 +        @Override
 145.737 +        public CodeStyle create(Preferences preferences) {
 145.738 +            return new CodeStyle(preferences);
 145.739 +        }
 145.740 +    }
 145.741 +}
   146.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   146.2 +++ b/python.source/src/org/netbeans/modules/python/source/ImportEntry.java	Sun Sep 13 11:47:42 2015 +0200
   146.3 @@ -0,0 +1,171 @@
   146.4 +/*
   146.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   146.6 + *
   146.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   146.8 + *
   146.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  146.10 + * Other names may be trademarks of their respective owners.
  146.11 + *
  146.12 + * The contents of this file are subject to the terms of either the GNU
  146.13 + * General Public License Version 2 only ("GPL") or the Common
  146.14 + * Development and Distribution License("CDDL") (collectively, the
  146.15 + * "License"). You may not use this file except in compliance with the
  146.16 + * License. You can obtain a copy of the License at
  146.17 + * http://www.netbeans.org/cddl-gplv2.html
  146.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  146.19 + * specific language governing permissions and limitations under the
  146.20 + * License.  When distributing the software, include this License Header
  146.21 + * Notice in each file and include the License file at
  146.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  146.23 + * particular file as subject to the "Classpath" exception as provided
  146.24 + * by Oracle in the GPL Version 2 section of the License file that
  146.25 + * accompanied this code. If applicable, add the following below the
  146.26 + * License Header, with the fields enclosed by brackets [] replaced by
  146.27 + * your own identifying information:
  146.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  146.29 + *
  146.30 + * Contributor(s):
  146.31 + *
  146.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  146.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  146.34 + * Microsystems, Inc. All Rights Reserved.
  146.35 + *
  146.36 + * If you wish your version of this file to be governed by only the CDDL
  146.37 + * or only the GPL Version 2, indicate your decision by adding
  146.38 + * "[Contributor] elects to include this software in this distribution
  146.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  146.40 + * single choice of license, a recipient has the option to distribute
  146.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  146.42 + * to extend the choice of license to its licensees as provided above.
  146.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  146.44 + * Version 2 license, then the option applies only if the new code is
  146.45 + * made subject to such option by the copyright holder.
  146.46 + */
  146.47 +package org.netbeans.modules.python.source;
  146.48 +
  146.49 +import org.python.antlr.PythonTree;
  146.50 +
  146.51 +/**
  146.52 + * State about a single atomic import. (A single import statement in Python
  146.53 + *  can correspond to many atomic imports: one for each symbol or module
  146.54 + *  imported)
  146.55 + *
  146.56 + * @author Tor Norbye
  146.57 + */
  146.58 +public class ImportEntry implements Comparable<ImportEntry> {
  146.59 +    public final String module;
  146.60 +    public final String asName;
  146.61 +    public final String symbol;
  146.62 +    public final boolean isSystem;
  146.63 +    public final boolean isFromImport;
  146.64 +    /**
  146.65 +     * Natural order of import statements (in the source). This will be non zero if
  146.66 +     * we want to preserve the original order rather than the alphabetical order.
  146.67 +     */
  146.68 +    public int ordinal;
  146.69 +    /** 
  146.70 +     * Corresponding import statement node. This will be non null if we want to consider
  146.71 +     * duplicate import statements as different 
  146.72 +     */
  146.73 +    public PythonTree node;
  146.74 +    /**
  146.75 +     * Whether we have a symbol import AND we're sorting by symbol imports.
  146.76 +     * Will be false even for symbol imports when we're not sorting by symbols.
  146.77 +     */
  146.78 +    public boolean sortedFrom;
  146.79 +
  146.80 +    public ImportEntry(String module, String symbol, String asName, boolean isSystem, PythonTree node, int ordinal) {
  146.81 +        super();
  146.82 +        this.module = module;
  146.83 +        this.symbol = symbol;
  146.84 +        this.asName = asName;
  146.85 +        this.isSystem = isSystem;
  146.86 +        this.isFromImport = symbol != null;
  146.87 +        this.node = node;
  146.88 +        this.ordinal = ordinal;
  146.89 +
  146.90 +        this.sortedFrom = symbol != null;
  146.91 +    }
  146.92 +
  146.93 +    public ImportEntry(String module, String asName, boolean isSystem, PythonTree node, int ordinal) {
  146.94 +        this(module, null, asName, isSystem, node, ordinal);
  146.95 +    }
  146.96 +
  146.97 +    @Override
  146.98 +    public boolean equals(Object obj) {
  146.99 +        if (obj == null) {
 146.100 +            return false;
 146.101 +        }
 146.102 +        if (getClass() != obj.getClass()) {
 146.103 +            return false;
 146.104 +        }
 146.105 +        final ImportEntry other = (ImportEntry)obj;
 146.106 +        if (this.node != other.node) {
 146.107 +            return false;
 146.108 +        }
 146.109 +        if ((this.module == null) ? (other.module != null) : !this.module.equals(other.module)) {
 146.110 +            return false;
 146.111 +        }
 146.112 +        if ((this.asName == null) ? (other.asName != null) : !this.asName.equals(other.asName)) {
 146.113 +            return false;
 146.114 +        }
 146.115 +        if ((this.symbol == null) ? (other.symbol != null) : !this.symbol.equals(other.symbol)) {
 146.116 +            return false;
 146.117 +        }
 146.118 +        return true;
 146.119 +    }
 146.120 +
 146.121 +    @Override
 146.122 +    public int hashCode() {
 146.123 +        int hash = 7;
 146.124 +        hash = 29 * hash + (this.module != null ? this.module.hashCode() : 0);
 146.125 +        return hash;
 146.126 +    }
 146.127 +
 146.128 +    @Override
 146.129 +    public int compareTo(ImportEntry other) {
 146.130 +        boolean thisIsFuture = "__future__".equals(module); // NOI18N
 146.131 +        boolean otherIsFuture = "__future__".equals(other.module); // NOI18N
 146.132 +        if (thisIsFuture != otherIsFuture) {
 146.133 +            return thisIsFuture ? -1 : 1;
 146.134 +        }
 146.135 +        if (isSystem != other.isSystem) {
 146.136 +            return isSystem ? -1 : 1;
 146.137 +        }
 146.138 +        if (sortedFrom != other.sortedFrom) {
 146.139 +            return sortedFrom ? 1 : -1;
 146.140 +        }
 146.141 +        if (ordinal != other.ordinal) {
 146.142 +            return ordinal - other.ordinal;
 146.143 +        }
 146.144 +        // Then we sort by module name
 146.145 +        int result = module.compareTo(other.module);
 146.146 +        if (result != 0) {
 146.147 +            return result;
 146.148 +        }
 146.149 +        // And then, for each module, first the imports, then the from imports
 146.150 +        if (isFromImport != other.isFromImport) {
 146.151 +            return isFromImport ? 1 : -1;
 146.152 +        }
 146.153 +        if (symbol != null) {
 146.154 +            assert other.symbol != null;
 146.155 +            // since isFromImport==
 146.156 +            result = symbol.compareTo(other.symbol);
 146.157 +            if (result != 0) {
 146.158 +                return result;
 146.159 +            }
 146.160 +        }
 146.161 +        if (asName == null) {
 146.162 +            return (other.asName == null) ? 0 : 1;
 146.163 +        }
 146.164 +        if (other.asName == null) {
 146.165 +            return -1;
 146.166 +        }
 146.167 +        return asName.compareTo(other.asName);
 146.168 +    }
 146.169 +
 146.170 +    @Override
 146.171 +    public String toString() {
 146.172 +        return "ImportEntry(" + module + ", " + symbol + ", " + asName + ")"; // NOI18N
 146.173 +    }
 146.174 +}
   147.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   147.2 +++ b/python.source/src/org/netbeans/modules/python/source/ImportManager.java	Sun Sep 13 11:47:42 2015 +0200
   147.3 @@ -0,0 +1,1048 @@
   147.4 +/*
   147.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   147.6 + *
   147.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   147.8 + *
   147.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  147.10 + * Other names may be trademarks of their respective owners.
  147.11 + *
  147.12 + * The contents of this file are subject to the terms of either the GNU
  147.13 + * General Public License Version 2 only ("GPL") or the Common
  147.14 + * Development and Distribution License("CDDL") (collectively, the
  147.15 + * "License"). You may not use this file except in compliance with the
  147.16 + * License. You can obtain a copy of the License at
  147.17 + * http://www.netbeans.org/cddl-gplv2.html
  147.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  147.19 + * specific language governing permissions and limitations under the
  147.20 + * License.  When distributing the software, include this License Header
  147.21 + * Notice in each file and include the License file at
  147.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  147.23 + * particular file as subject to the "Classpath" exception as provided
  147.24 + * by Oracle in the GPL Version 2 section of the License file that
  147.25 + * accompanied this code. If applicable, add the following below the
  147.26 + * License Header, with the fields enclosed by brackets [] replaced by
  147.27 + * your own identifying information:
  147.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  147.29 + *
  147.30 + * If you wish your version of this file to be governed by only the CDDL
  147.31 + * or only the GPL Version 2, indicate your decision by adding
  147.32 + * "[Contributor] elects to include this software in this distribution
  147.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  147.34 + * single choice of license, a recipient has the option to distribute
  147.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  147.36 + * to extend the choice of license to its licensees as provided above.
  147.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  147.38 + * Version 2 license, then the option applies only if the new code is
  147.39 + * made subject to such option by the copyright holder.
  147.40 + *
  147.41 + * Contributor(s):
  147.42 + *
  147.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  147.44 + */
  147.45 +package org.netbeans.modules.python.source;
  147.46 +
  147.47 +import java.awt.Toolkit;
  147.48 +import java.util.ArrayList;
  147.49 +import java.util.Collection;
  147.50 +import java.util.Collections;
  147.51 +import java.util.HashMap;
  147.52 +import java.util.HashSet;
  147.53 +import java.util.List;
  147.54 +import java.util.Map;
  147.55 +import java.util.Set;
  147.56 +import javax.swing.text.BadLocationException;
  147.57 +import org.netbeans.api.editor.EditorRegistry;
  147.58 +import org.netbeans.editor.BaseDocument;
  147.59 +import org.netbeans.editor.Utilities;
  147.60 +import org.netbeans.modules.csl.api.EditList;
  147.61 +import org.netbeans.modules.csl.api.OffsetRange;
  147.62 +import org.netbeans.modules.csl.spi.GsfUtilities;
  147.63 +import org.netbeans.modules.editor.indent.api.IndentUtils;
  147.64 +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
  147.65 +import org.netbeans.modules.python.source.ImportEntry;
  147.66 +import org.netbeans.modules.python.source.PythonAstUtils;
  147.67 +import org.netbeans.modules.python.source.PythonIndex;
  147.68 +import org.netbeans.modules.python.source.PythonParserResult;
  147.69 +import org.netbeans.modules.python.source.elements.IndexedElement;
  147.70 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  147.71 +import org.netbeans.modules.python.source.CodeStyle;
  147.72 +import org.netbeans.modules.python.source.CodeStyle.ImportCleanupStyle;
  147.73 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  147.74 +import org.netbeans.modules.python.source.scopes.SymInfo;
  147.75 +import org.openide.util.Exceptions;
  147.76 +import org.openide.util.NbBundle;
  147.77 +import org.python.antlr.PythonTree;
  147.78 +import org.python.antlr.ast.Import;
  147.79 +import org.python.antlr.ast.ImportFrom;
  147.80 +import org.python.antlr.ast.Str;
  147.81 +import org.python.antlr.ast.alias;
  147.82 +
  147.83 +/**
  147.84 + * Computations regarding module imports.
  147.85 + *
  147.86 + * @todo Handle commenting out portions of imports
  147.87 + * @todo If I can make this fast, consider highlighting unused imports.
  147.88 + * @todo On code completion I should import the corresponding package+class (make the
  147.89 + *   class part optional)
  147.90 + * @todo Watch out for commented out imports getting wiped out in organize imports
  147.91 + *   because it's between imports. These need to be moved to the end!!!
  147.92 + * @todo Offer to group imports
  147.93 + * @todo Don't import functions
  147.94 + *
  147.95 + * @author Tor Norbye
  147.96 + */
  147.97 +public final class ImportManager {
  147.98 +
  147.99 +    private PythonParserResult info;
 147.100 +    private List<Import> imports;
 147.101 +    private List<ImportFrom> importsFrom;
 147.102 +    private PythonTree root;
 147.103 +    private BaseDocument doc;
 147.104 +    private List<PythonTree> mainImports;
 147.105 +    private Set<PythonTree> topLevelImports;
 147.106 +
 147.107 +    // Settings
 147.108 +    private boolean systemLibsFirst = true;
 147.109 +    private boolean splitImports = true;
 147.110 +    private boolean sortImports = true;
 147.111 +    private boolean separateFromImps = false;
 147.112 +    private ImportCleanupStyle cleanup = ImportCleanupStyle.COMMENT_OUT;
 147.113 +    private boolean removeDuplicates;
 147.114 +    private int rightMargin;
 147.115 +
 147.116 +    public ImportManager(PythonParserResult info) {
 147.117 +        this(info, GsfUtilities.getDocument(info.getSnapshot().getSource().getFileObject(), false), null);
 147.118 +    }
 147.119 +
 147.120 +    public ImportManager(PythonParserResult info, BaseDocument doc) {
 147.121 +        this(info, doc, null);
 147.122 +    }
 147.123 +
 147.124 +    public ImportManager(PythonParserResult info, BaseDocument doc, CodeStyle codeStyle) {
 147.125 +        this.info = info;
 147.126 +
 147.127 +        root = PythonAstUtils.getRoot(info);
 147.128 +
 147.129 +        SymbolTable symbolTable = PythonAstUtils.getParseResult(info).getSymbolTable();
 147.130 +        imports = symbolTable.getImports();
 147.131 +        importsFrom = symbolTable.getImportsFrom();
 147.132 +        topLevelImports = symbolTable.getTopLevelImports();
 147.133 +        mainImports = symbolTable.getMainImports();
 147.134 +
 147.135 +        this.doc = doc;
 147.136 +
 147.137 +        if (codeStyle == null) {
 147.138 +            codeStyle = CodeStyle.getDefault(doc);
 147.139 +        }
 147.140 +        systemLibsFirst = codeStyle.systemLibsFirst();
 147.141 +        splitImports = codeStyle.oneImportPerLine();
 147.142 +        cleanup = codeStyle.cleanupImports();
 147.143 +        sortImports = codeStyle.sortImports();
 147.144 +        separateFromImps = codeStyle.separateFromImps();
 147.145 +        if (separateFromImps) {
 147.146 +            sortImports = true;
 147.147 +        }
 147.148 +        removeDuplicates = codeStyle.removeDuplicates();
 147.149 +        rightMargin = codeStyle.getRightMargin();
 147.150 +
 147.151 +    }
 147.152 +
 147.153 +    public static boolean isFutureImport(ImportFrom fromStatement) {
 147.154 +        return "__future__".equals(fromStatement.getInternalModule()); // NOI18N
 147.155 +    }
 147.156 +
 147.157 +    public void setCleanup(ImportCleanupStyle cleanup) {
 147.158 +        this.cleanup = cleanup;
 147.159 +    }
 147.160 +
 147.161 +    public void cleanup(EditList edits, int startOffset, int endOffset, boolean force) {
 147.162 +        OffsetRange lexRange = getMainImportsRange();
 147.163 +        if (lexRange == OffsetRange.NONE ||
 147.164 +                !(new OffsetRange(startOffset, endOffset).overlaps(lexRange))) {
 147.165 +            // Not touching imports
 147.166 +            return;
 147.167 +        }
 147.168 +
 147.169 +        if (cleanup != ImportCleanupStyle.LEAVE_ALONE) {
 147.170 +            List<String> ambiguousSymbols = new ArrayList<>();
 147.171 +            Map<String, String> defaultLists = new HashMap<>();
 147.172 +            Map<String, List<String>> alternatives = new HashMap<>();
 147.173 +            Set<ImportEntry> unused = new HashSet<>();
 147.174 +            Set<ImportEntry> duplicates = new HashSet<>();
 147.175 +
 147.176 +            computeImports(ambiguousSymbols, defaultLists, alternatives, unused, duplicates);
 147.177 +            if (ambiguousSymbols.size() == 0 || force) {
 147.178 +                apply(edits, new String[0], unused, duplicates);
 147.179 +                return;
 147.180 +            }
 147.181 +        } else if (removeDuplicates) {
 147.182 +            Set<ImportEntry> duplicates = findDuplicates();
 147.183 +            apply(edits, new String[0], Collections.<ImportEntry>emptySet(), duplicates);
 147.184 +            return;
 147.185 +        }
 147.186 +
 147.187 +        apply(edits, new String[0], Collections.<ImportEntry>emptySet(), Collections.<ImportEntry>emptySet());
 147.188 +    }
 147.189 +
 147.190 +    public List<Import> getImports() {
 147.191 +        return imports;
 147.192 +    }
 147.193 +
 147.194 +    public List<ImportFrom> getImportsFrom() {
 147.195 +        return importsFrom;
 147.196 +    }
 147.197 +
 147.198 +    private Set<ImportEntry> findDuplicates() {
 147.199 +        Set<ImportEntry> duplicates = new HashSet<>();
 147.200 +        // TODO!
 147.201 +
 147.202 +        return duplicates;
 147.203 +    }
 147.204 +
 147.205 +    public boolean computeImports(
 147.206 +            List<String> ambiguousSymbols,
 147.207 +            Map<String, String> defaults,
 147.208 +            Map<String, List<String>> alternatives, Set<ImportEntry> unused, Set<ImportEntry> duplicates) {
 147.209 +
 147.210 +        boolean ambiguous = false;
 147.211 +
 147.212 +        SymbolTable symbolTable = new SymbolTable(PythonAstUtils.getRoot(info), info.getSnapshot().getSource().getFileObject());
 147.213 +        Map<String, SymInfo> unresolved = symbolTable.getUnresolvedNames(info);
 147.214 +
 147.215 +        if (unresolved.size() > 0) {
 147.216 +            ambiguousSymbols.addAll(unresolved.keySet());
 147.217 +            Collections.sort(ambiguousSymbols);
 147.218 +
 147.219 +            // Try to compute suggestions.
 147.220 +            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 147.221 +            Set<IndexedElement> modules = index.getModules("", QuerySupport.Kind.PREFIX);
 147.222 +            for (IndexedElement module : modules) {
 147.223 +                String name = module.getName();
 147.224 +                if (unresolved.containsKey(name)) {
 147.225 +                    List<String> list = new ArrayList<>(4);
 147.226 +                    list.add(name);
 147.227 +                    defaults.put(name, name);
 147.228 +                    alternatives.put(name, list);
 147.229 +                }
 147.230 +            }
 147.231 +
 147.232 +            List<String> unresolvedList = new ArrayList<>(unresolved.keySet());
 147.233 +            Collections.sort(unresolvedList);
 147.234 +            for (String symbol : unresolvedList) {
 147.235 +                // TODO - determine if it's a call or variable
 147.236 +                // TODO - track import usages too!
 147.237 +                Collection<String> importsFor = index.getImportsFor(symbol, true);
 147.238 +                // TODO - insert symbols   + " (whole module)"
 147.239 +                if (importsFor.size() > 0) {
 147.240 +                    if (importsFor.size() > 1) {
 147.241 +                        List<String> l = new ArrayList<>(importsFor);
 147.242 +                        Collections.sort(l);
 147.243 +                        importsFor = l;
 147.244 +                    }
 147.245 +                    List<String> list = alternatives.get(symbol);
 147.246 +                    if (list == null) {
 147.247 +                        list = new ArrayList<>();
 147.248 +                        alternatives.put(symbol, list);
 147.249 +                    }
 147.250 +                    for (String s : importsFor) {
 147.251 +                        if (!list.contains(s)) {
 147.252 +                            list.add(s);
 147.253 +                        }
 147.254 +                    }
 147.255 +                    if (list.size() > 1) {
 147.256 +                        ambiguous = true;
 147.257 +                    }
 147.258 +
 147.259 +                // TODO - if it's a call, try to match functions instead of imported symbols
 147.260 +                } else {
 147.261 +                    ambiguous = true;
 147.262 +                }
 147.263 +            }
 147.264 +
 147.265 +        // TODO - look up -functions- and -data- defined across all modules
 147.266 +        // that might define these guys
 147.267 +
 147.268 +        }
 147.269 +
 147.270 +        List<String> unambiguousNames = new ArrayList<>();
 147.271 +        for (Map.Entry<String, List<String>> entry : alternatives.entrySet()) {
 147.272 +            List<String> list = entry.getValue();
 147.273 +            if (list == null || list.size() == 0) {
 147.274 +                ambiguous = true;
 147.275 +            } else if (list.size() == 1) {
 147.276 +                String key = entry.getKey();
 147.277 +                unambiguousNames.add(key);
 147.278 +            }
 147.279 +        }
 147.280 +
 147.281 +        // If we've had to choose certain libraries (e.g. because they're the
 147.282 +        // only choice available in some cases) then make those libraries default
 147.283 +        // for all the ambiguous cases as well
 147.284 +        if (!unambiguousNames.isEmpty()) {
 147.285 +            for (String name : alternatives.keySet()) {
 147.286 +                List<String> list = alternatives.get(name);
 147.287 +                for (String choice : list) {
 147.288 +                    if (unambiguousNames.contains(choice)) {
 147.289 +                        defaults.put(name, choice);
 147.290 +                    }
 147.291 +                }
 147.292 +            }
 147.293 +        }
 147.294 +
 147.295 +        unused.addAll(symbolTable.getUnusedImports());
 147.296 +
 147.297 +// During development
 147.298 +//ambiguous = true;
 147.299 +
 147.300 +        return ambiguous;
 147.301 +    }
 147.302 +
 147.303 +    public void apply(EditList edits, String[] selections, Set<ImportEntry> removeEntries, Set<ImportEntry> duplicates) {
 147.304 +        // Update the imports
 147.305 +        // Sort the imports
 147.306 +        // Delete the unused imports
 147.307 +        boolean apply = false;
 147.308 +        if (edits == null) {
 147.309 +            edits = new EditList(doc);
 147.310 +            apply = true;
 147.311 +        }
 147.312 +
 147.313 +        Set<PythonTree> removedAlready = new HashSet<>();
 147.314 +
 147.315 +        Set<PythonTree> mainImport;
 147.316 +        //if (sortImports) {
 147.317 +        mainImport = new HashSet<>(mainImports);
 147.318 +        //} else {
 147.319 +        //    mainImport = Collections.<PythonTree>emptySet();
 147.320 +        //}
 147.321 +        Set<PythonTree> topLevel = topLevelImports;
 147.322 +
 147.323 +//
 147.324 +//        // Remove duplicates. Note - these are always removed, not just commented out.
 147.325 +//        if (duplicates.size() > 0 && cleanup != ImportCleanupStyle.LEAVE_ALONE) {
 147.326 +//            Set<PythonTree> candidates = new HashSet<PythonTree>();
 147.327 +//            // Map from import node to list of names that should be removed, if only some are duplicates
 147.328 +//            Map<PythonTree,List<String>> names = new HashMap<PythonTree,List<String>>();
 147.329 +//            // Find the corresponding import
 147.330 +//            //List<PythonTree> candidates = new ArrayList<PythonTree>();
 147.331 +//            boolean foundFirst = false;
 147.332 +//            for (Import imp : imports) {
 147.333 +//                if (imp.names != null) {
 147.334 +//                    boolean all = true;
 147.335 +//                    boolean some = false;
 147.336 +//                    for (alias at : imp.getInternalNames()) {
 147.337 +//                        if (duplicates.contains(at.getInternalName())) {
 147.338 +//                            if (!foundFirst) {
 147.339 +//                                foundFirst = true;
 147.340 +//                            } else {
 147.341 +//                                some = true;
 147.342 +//                                List<String> nameList = names.get(imp);
 147.343 +//                                if (nameList == null) {
 147.344 +//                                    nameList = new ArrayList<String>();
 147.345 +//                                    names.put(imp, nameList);
 147.346 +//                                }
 147.347 +//                                nameList.add(at.getInternalName());
 147.348 +//                            }
 147.349 +//                            break;
 147.350 +//                        } else {
 147.351 +//                            all = false;
 147.352 +//                        }
 147.353 +//                    }
 147.354 +//                    if (some) {
 147.355 +//                        candidates.add(imp);
 147.356 +//                        if (all) {
 147.357 +//                            // No need to limit deletion to just one
 147.358 +//                            names.put(imp, null);
 147.359 +//                        }
 147.360 +//                    }
 147.361 +//                }
 147.362 +//            }
 147.363 +//
 147.364 +//            for (ImportFrom from : importsFrom) {
 147.365 +//                if (from.names != null) {
 147.366 +//                    boolean all = true;
 147.367 +//                    boolean some = false;
 147.368 +//                    for (alias at : from.names) {
 147.369 +//                        assert at.getInternalName() != null;
 147.370 +//                        String value;
 147.371 +//                        if (at.getInternalAsname() != null) {
 147.372 +//                            value = from.module + ":" + at.getInternalName() + ":" + at.getInternalAsname();
 147.373 +//                        } else {
 147.374 +//                            value = from.module + ":" + at.getInternalName();
 147.375 +//                        }
 147.376 +//                        if (duplicates.contains(value)) {
 147.377 +//                            if (!foundFirst) {
 147.378 +//                                foundFirst = true;
 147.379 +//                            } else {
 147.380 +//                                some = true;
 147.381 +//                                List<String> nameList = names.get(from);
 147.382 +//                                if (nameList == null) {
 147.383 +//                                    nameList = new ArrayList<String>();
 147.384 +//                                    names.put(from, nameList);
 147.385 +//                                }
 147.386 +//                                nameList.add(at.getInternalName());
 147.387 +//                            }
 147.388 +//                        } else {
 147.389 +//                            all = false;
 147.390 +//                        }
 147.391 +//                    }
 147.392 +//                    if (some) {
 147.393 +//                        candidates.add(from);
 147.394 +//                        if (all) {
 147.395 +//                            // No need to limit deletion to just one
 147.396 +//                            names.put(from, null);
 147.397 +//                        }
 147.398 +//                    }
 147.399 +//                }
 147.400 +//            }
 147.401 +//
 147.402 +//            Set<PythonTree> filtered = new HashSet<PythonTree>();
 147.403 +//            for (PythonTree node : candidates) {
 147.404 +//                if (!mainImport.contains(node) && topLevel.contains(node)) {
 147.405 +//                    filtered.add(node);
 147.406 +//                }
 147.407 +//            }
 147.408 +//
 147.409 +//            removedAlready.addAll(filtered);
 147.410 +//
 147.411 +//            // Note - we always REMOVE duplicate imports rather than just commenting
 147.412 +//            // them out. We may sometimes be wrong about unused imports, so we let
 147.413 +//            // users leave them commented out when we clean up to make it easier
 147.414 +//            // to backtrack if we were wrong. However, duplicate imports is something
 147.415 +//            // we can accurately detect and leaving them commented out isn't something
 147.416 +//            // users will probably want.
 147.417 +//            removeImports(edits, filtered, /*commentOut*/false, names);
 147.418 +//        }
 147.419 +
 147.420 +        if (cleanup == ImportCleanupStyle.LEAVE_ALONE) {
 147.421 +            removeEntries.clear();
 147.422 +        } else {
 147.423 +            Set<ImportEntry> newSet = new HashSet<>();
 147.424 +            Set<PythonTree> filtered = new HashSet<>();
 147.425 +            for (ImportEntry entry : removeEntries) {
 147.426 +                PythonTree node = entry.node;
 147.427 +                if (!mainImport.contains(node) && topLevel.contains(node)) {
 147.428 +                    filtered.add(node);
 147.429 +                } else {
 147.430 +                    if (removeDuplicates) {
 147.431 +                        entry.node = null;
 147.432 +                    }
 147.433 +                    if (sortImports) {
 147.434 +                        entry.ordinal = 0;
 147.435 +                    }
 147.436 +                    if (!separateFromImps) {
 147.437 +                        entry.sortedFrom = false;
 147.438 +                    }
 147.439 +                }
 147.440 +
 147.441 +                newSet.add(entry);
 147.442 +            }
 147.443 +            removeEntries = newSet;
 147.444 +//        int ordinal = 0;
 147.445 +//        if (unused.size() > 0 && cleanup != ImportCleanupStyle.LEAVE_ALONE) {
 147.446 +//            Set<PythonTree> candidates = new HashSet<PythonTree>();
 147.447 +//            Map<PythonTree,List<String>> names = new HashMap<PythonTree,List<String>>();
 147.448 +//            // Find the corresponding import
 147.449 +//            //List<PythonTree> candidates = new ArrayList<PythonTree>();
 147.450 +//            for (Import imp : imports) {
 147.451 +//                if (imp.names != null) {
 147.452 +//                    boolean all = true;
 147.453 +//                    boolean some = false;
 147.454 +//                    for (alias at : imp.getInternalNames()) {
 147.455 +//                        if (unused.contains(at.getInternalName())) {
 147.456 +//                            some = true;
 147.457 +//                            List<String> nameList = names.get(imp);
 147.458 +//                            if (nameList == null) {
 147.459 +//                                nameList = new ArrayList<String>();
 147.460 +//                                names.put(imp, nameList);
 147.461 +//                            }
 147.462 +//                            nameList.add(at.getInternalName());
 147.463 +//
 147.464 +//                            boolean isSystem = false; // Don't care what it is for deletion
 147.465 +//                            removeEntries.add(new ImportEntry(at.getInternalName(), at.getInternalAsname(), isSystem,
 147.466 +//                                    removeDuplicates ? null : imp,
 147.467 +//                                    sortImports ? 0 : ordinal++));
 147.468 +//                          break;
 147.469 +//                        } else {
 147.470 +//                            all = false;
 147.471 +//                        }
 147.472 +//                    }
 147.473 +//
 147.474 +//                    if (some) {
 147.475 +//                        candidates.add(imp);
 147.476 +//                        if (all) {
 147.477 +//                            // No need to limit deletion to just one
 147.478 +//                            names.put(imp, null);
 147.479 +//                        }
 147.480 +//                    }
 147.481 +//                }
 147.482 +//            }
 147.483 +//
 147.484 +//            for (ImportFrom from : importsFrom) {
 147.485 +//                if (from.names != null) {
 147.486 +//                    boolean all = true;
 147.487 +//                    boolean some = false;
 147.488 +//                    for (alias at : from.names) {
 147.489 +//                        boolean isSystem = false; // Don't care what it is for deletion
 147.490 +//
 147.491 +//                        assert at.getInternalName() != null;
 147.492 +//                        String value;
 147.493 +//                        if (at.getInternalAsname() != null) {
 147.494 +//                            value = from.module + ":" + at.getInternalName() + ":" + at.getInternalAsname();
 147.495 +//                        } else {
 147.496 +//                            value = from.module + ":" + at.getInternalName();
 147.497 +//                        }
 147.498 +//                        if (unused.contains(value)) {
 147.499 +//                            removeEntries.add(new ImportEntry(from.module, at.getInternalName(), at.getInternalAsname(), isSystem,
 147.500 +//                                    removeDuplicates ? null : from,
 147.501 +//                                    sortImports ? 0 : ordinal++));
 147.502 +//                            some = true;
 147.503 +//                            List<String> nameList = names.get(from);
 147.504 +//                            if (nameList == null) {
 147.505 +//                                nameList = new ArrayList<String>();
 147.506 +//                                names.put(from, nameList);
 147.507 +//                            }
 147.508 +//                            nameList.add(at.getInternalName());
 147.509 +//                        } else {
 147.510 +//                            all = false;
 147.511 +//                        }
 147.512 +//                    }
 147.513 +//                    if (some) {
 147.514 +//                        candidates.add(from);
 147.515 +//                        if (all) {
 147.516 +//                            // No need to limit deletion to just one
 147.517 +//                            names.put(from, null);
 147.518 +//                        }
 147.519 +//                    }
 147.520 +//                }
 147.521 +//            }
 147.522 +//
 147.523 +//            // Don't try to delete nodes we've already deleted or commented out
 147.524 +//            // because they are unused
 147.525 +//
 147.526 +//            candidates.removeAll(removedAlready);
 147.527 +//
 147.528 +//            Set<PythonTree> filtered = new HashSet<PythonTree>();
 147.529 +//            for (PythonTree node : candidates) {
 147.530 +//                if (!mainImport.contains(node) && topLevel.contains(node)) {
 147.531 +//                    filtered.add(node);
 147.532 +//                }
 147.533 +//            }
 147.534 +
 147.535 +            removeImports(edits, filtered, cleanup == ImportCleanupStyle.COMMENT_OUT, null);
 147.536 +        }
 147.537 +
 147.538 +        PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 147.539 +
 147.540 +        Collection<ImportEntry> newEntries = new ArrayList<>();
 147.541 +        if (selections != null) {
 147.542 +            for (String module : selections) {
 147.543 +                if (module.startsWith("<html>")) { // NOI18N
 147.544 +                    // Skip cannot resolve stuff
 147.545 +                    continue;
 147.546 +                }
 147.547 +                int colon = module.indexOf(':');
 147.548 +                if (colon != -1) {
 147.549 +                    int end = module.indexOf('(', colon + 1);
 147.550 +                    if (end == -1) {
 147.551 +                        end = module.indexOf(';', colon + 1);
 147.552 +                        if (end == -1) {
 147.553 +                            end = module.length();
 147.554 +                        }
 147.555 +                    }
 147.556 +                    String symbol = module.substring(colon + 1, end).trim();
 147.557 +                    module = module.substring(0, colon).trim();
 147.558 +                    boolean isSystem = systemLibsFirst && index.isSystemModule(module);
 147.559 +                    ImportEntry importEntry = new ImportEntry(module, symbol, null, isSystem, null, 0);
 147.560 +                    if (!separateFromImps) {
 147.561 +                        importEntry.sortedFrom = false;
 147.562 +                    }
 147.563 +                    newEntries.add(importEntry);
 147.564 +                } else {
 147.565 +                    boolean isSystem = systemLibsFirst && index.isSystemModule(module);
 147.566 +                    ImportEntry importEntry = new ImportEntry(module, null, null, isSystem, null, 0);
 147.567 +                    if (!separateFromImps) {
 147.568 +                        importEntry.sortedFrom = false;
 147.569 +                    }
 147.570 +                    newEntries.add(importEntry);
 147.571 +                }
 147.572 +            }
 147.573 +        }
 147.574 +
 147.575 +        rewriteMainImports(edits, newEntries, removeEntries);
 147.576 +
 147.577 +        if (apply) {
 147.578 +            edits.apply();
 147.579 +        }
 147.580 +    }
 147.581 +
 147.582 +    public boolean isTopLevel(PythonTree node) {
 147.583 +        return topLevelImports.contains(node);
 147.584 +    }
 147.585 +
 147.586 +    /**
 147.587 +     * Remove or comment out the given import statements (Import or ImportFrom).
 147.588 +     * @param edits The edit list to add edits for comment or removal
 147.589 +     * @param candidates The set of Import or ImportFrom nodes
 147.590 +     * @param commentOut If true, comment out the import, or else, delete it
 147.591 +     * @param onlyNames A map from nodes to lists where if the list is null,
 147.592 +     *   remove or comment out the entire import, otherwise comment
 147.593 +     *   or delete only the specified name portions.
 147.594 +     */
 147.595 +    public void removeImports(EditList edits, Set<PythonTree> candidates, boolean commentOut, Map<PythonTree, List<String>> onlyNames) {
 147.596 +        for (PythonTree node : candidates) {
 147.597 +            // Don't touch imports that aren't top level!!!
 147.598 +            // These can be inside If blocks and such so we don't
 147.599 +            // have enough knowledge to mess with them
 147.600 +            if (!isTopLevel(node)) {
 147.601 +                continue;
 147.602 +            }
 147.603 +
 147.604 +            OffsetRange astRange = PythonAstUtils.getRange(node);
 147.605 +            OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 147.606 +            if (lexRange == OffsetRange.NONE) {
 147.607 +                continue;
 147.608 +            }
 147.609 +
 147.610 +            List<String> names = onlyNames.get(node);
 147.611 +            if (names != null) {
 147.612 +
 147.613 +                // TODO Handle commenting out portions of a line! An idea which
 147.614 +                // might work is to replace the whole import with a new import
 147.615 +                // that moves the commented out portions to the end!!
 147.616 +
 147.617 +                // Only delete/comment out a portion of the line
 147.618 +//                if (commentOut) {
 147.619 +// TODO
 147.620 +//                } else {
 147.621 +                // Determine offsets within the line
 147.622 +                List<OffsetRange> ranges = new ArrayList<>();
 147.623 +                try {
 147.624 +                    int start = lexRange.getStart();
 147.625 +                    int end = lexRange.getEnd();
 147.626 +                    if (end > doc.getLength()) {
 147.627 +                        end = doc.getLength();
 147.628 +                        if (start > doc.getLength()) {
 147.629 +                            start = doc.getLength();
 147.630 +                        }
 147.631 +                    }
 147.632 +                    String line = doc.getText(start, end - start);
 147.633 +                    for (String name : names) {
 147.634 +                        int index = line.indexOf(name);
 147.635 +                        if (index != -1) {
 147.636 +                            int nameEnd = index + name.length();
 147.637 +                            boolean removedComma = false;
 147.638 +                            for (int i = nameEnd; i < line.length(); i++) {
 147.639 +                                char c = line.charAt(i);
 147.640 +                                if (c == ',') {
 147.641 +                                    removedComma = true;
 147.642 +                                    nameEnd = i + 1;
 147.643 +                                    if (nameEnd < line.length() && line.charAt(nameEnd) == ' ') {
 147.644 +                                        // Include space after comma in deletion
 147.645 +                                        nameEnd++;
 147.646 +                                    }
 147.647 +                                    break;
 147.648 +                                } else if (c == ' ' || c == '\t') {
 147.649 +                                    continue;
 147.650 +                                } else {
 147.651 +                                    break;
 147.652 +                                }
 147.653 +                            }
 147.654 +                            if (!removedComma) {
 147.655 +                                // If I removed the last name on the line there is no
 147.656 +                                // comma at the end, so I should try removing one -before-
 147.657 +                                // the name instead
 147.658 +                                for (int i = index - 1; i >= 0; i--) {
 147.659 +                                    char c = line.charAt(i);
 147.660 +                                    if (c == ',') {
 147.661 +                                        index = i;
 147.662 +                                        break;
 147.663 +                                    } else if (c == ' ' || c == '\t') {
 147.664 +                                        continue;
 147.665 +                                    } else {
 147.666 +                                        break;
 147.667 +                                    }
 147.668 +                                }
 147.669 +                            }
 147.670 +                            OffsetRange remove = new OffsetRange(start + index, start + nameEnd);
 147.671 +
 147.672 +                            // Prevent overlaps
 147.673 +                            for (OffsetRange range : ranges) {
 147.674 +                                if (range.overlaps(remove)) {
 147.675 +                                    if (range.getStart() < remove.getStart()) {
 147.676 +                                        remove = new OffsetRange(range.getEnd(), Math.max(remove.getEnd(), range.getEnd()));
 147.677 +                                    } else {
 147.678 +                                        remove = new OffsetRange(Math.min(remove.getStart(), range.getStart()), range.getStart());
 147.679 +                                    }
 147.680 +                                }
 147.681 +                            }
 147.682 +
 147.683 +                            ranges.add(remove);
 147.684 +                        }
 147.685 +                    }
 147.686 +                    int prio = 0;
 147.687 +                    for (OffsetRange range : ranges) {
 147.688 +                        edits.replace(range.getStart(), range.getLength(), null, false, prio++);
 147.689 +                    }
 147.690 +                } catch (BadLocationException ex) {
 147.691 +                    Exceptions.printStackTrace(ex);
 147.692 +                }
 147.693 +//                }
 147.694 +            } else {
 147.695 +                int start = lexRange.getStart();
 147.696 +                if (commentOut) {
 147.697 +                    edits.replace(start, 0, "#", false, 0); // NOI18N
 147.698 +                } else {
 147.699 +                    int length = lexRange.getLength();
 147.700 +                    // See if this leaves an empty line and if so remove it
 147.701 +                    int endPos = lexRange.getEnd();
 147.702 +                    if (endPos < doc.getLength()) {
 147.703 +                        try {
 147.704 +                            char c = doc.getText(endPos, 1).charAt(0);
 147.705 +                            if (c == '\n') {
 147.706 +                                length++;
 147.707 +                            }
 147.708 +                        } catch (BadLocationException ex) {
 147.709 +                            Exceptions.printStackTrace(ex);
 147.710 +                        }
 147.711 +                    }
 147.712 +                    edits.replace(start, length, null, false, 0);
 147.713 +                }
 147.714 +            }
 147.715 +        }
 147.716 +    }
 147.717 +
 147.718 +    private OffsetRange getMainImportsRange() {
 147.719 +        // Compute editor range required
 147.720 +        int begin = Integer.MAX_VALUE;
 147.721 +        int end = Integer.MIN_VALUE;
 147.722 +        OffsetRange lexRange;
 147.723 +        if (mainImports.size() == 0) {
 147.724 +            if (mainImports.size() == 1) {
 147.725 +                OffsetRange astRange = PythonAstUtils.getRange(mainImports.get(0));
 147.726 +                lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 147.727 +            } else {
 147.728 +                assert mainImports.size() == 0;
 147.729 +                begin = getImportsLexOffset(null);
 147.730 +                end = begin;
 147.731 +                lexRange = new OffsetRange(begin, end);
 147.732 +            }
 147.733 +        } else {
 147.734 +            for (PythonTree node : mainImports) {
 147.735 +                OffsetRange range = PythonAstUtils.getRange(node);
 147.736 +                if (range.getStart() < begin) {
 147.737 +                    begin = range.getStart();
 147.738 +                }
 147.739 +                if (range.getEnd() > end) {
 147.740 +                    end = range.getEnd();
 147.741 +                }
 147.742 +            }
 147.743 +            OffsetRange astReplace = new OffsetRange(begin, end);
 147.744 +            lexRange = PythonLexerUtils.getLexerOffsets(info, astReplace);
 147.745 +        }
 147.746 +
 147.747 +        return lexRange;
 147.748 +    }
 147.749 +
 147.750 +    public void rewriteMainImports(EditList edits, Collection<ImportEntry> newEntries, Set<ImportEntry> remove) {
 147.751 +        // Items to be deleted should be deleted after this
 147.752 +
 147.753 +        PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 147.754 +
 147.755 +        // TODO:
 147.756 +        // Look for comments to preserve
 147.757 +        // Replace the entire editor block
 147.758 +        Set<ImportEntry> entries = new HashSet<>();
 147.759 +        int ordinal = 0;
 147.760 +        for (PythonTree node : mainImports) {
 147.761 +            if (node instanceof Import) {
 147.762 +                Import imp = (Import)node;
 147.763 +                // TODO - look up for at.getInternalName()!
 147.764 +                List<alias> names = imp.getInternalNames();
 147.765 +                if (names != null) {
 147.766 +                    for (alias at : names) {
 147.767 +                        ImportEntry importEntry = new ImportEntry(at.getInternalName(), at.getInternalAsname(), systemLibsFirst && index.isSystemModule(at.getInternalName()),
 147.768 +                                removeDuplicates ? null : imp, sortImports ? 0 : ordinal++);
 147.769 +                        if (!separateFromImps) {
 147.770 +                            importEntry.sortedFrom = false;
 147.771 +                        }
 147.772 +                        entries.add(importEntry);
 147.773 +                    }
 147.774 +                }
 147.775 +            } else {
 147.776 +                assert node instanceof ImportFrom;
 147.777 +                ImportFrom imp = (ImportFrom)node;
 147.778 +                List<alias> names = imp.getInternalNames();
 147.779 +                if (names != null && names.size() > 0) {
 147.780 +                    // TODO - look up for imp.getInternalModule()!
 147.781 +                    boolean isSystemLibrary = systemLibsFirst && index.isSystemModule(imp.getInternalModule());
 147.782 +                    for (alias at : names) {
 147.783 +                        ImportEntry importEntry = new ImportEntry(imp.getInternalModule(), at.getInternalName(), at.getInternalAsname(), isSystemLibrary,
 147.784 +                                removeDuplicates ? null : imp, sortImports ? 0 : ordinal++);
 147.785 +                        if (!separateFromImps) {
 147.786 +                            importEntry.sortedFrom = false;
 147.787 +                        }
 147.788 +                        entries.add(importEntry);
 147.789 +                    }
 147.790 +                }
 147.791 +            }
 147.792 +        }
 147.793 +
 147.794 +        // Add in entries discovered as needed by the import manager
 147.795 +        if (newEntries.size() > 0) {
 147.796 +            entries.addAll(newEntries);
 147.797 +        }
 147.798 +
 147.799 +        // Remove any items that needs to be removed
 147.800 +        if (remove.size() > 0) {
 147.801 +            entries.removeAll(remove);
 147.802 +        }
 147.803 +
 147.804 +        // Sort imports -- first by system/nonsystem, then alphabetically
 147.805 +        List<ImportEntry> sortedEntries = new ArrayList<>(entries);
 147.806 +        Collections.sort(sortedEntries);
 147.807 +
 147.808 +        // Write out existing imports
 147.809 +        StringBuilder sb = new StringBuilder();
 147.810 +        int size = sortedEntries.size();
 147.811 +        if (size > 0) {
 147.812 +            boolean prevSystem = sortedEntries.get(0).isSystem;
 147.813 +
 147.814 +            for (int i = 0; i < size; i++) {
 147.815 +                ImportEntry entry = sortedEntries.get(i);
 147.816 +                if (systemLibsFirst && entry.isSystem != prevSystem) {
 147.817 +                    prevSystem = entry.isSystem;
 147.818 +                    sb.append("\n"); // NOI18N Separate system and regular libs
 147.819 +                }
 147.820 +
 147.821 +                if (entry.isFromImport) {
 147.822 +                    int start = sb.length();
 147.823 +                    sb.append("from "); // NOI18N
 147.824 +                    sb.append(entry.module);
 147.825 +                    sb.append(" import "); // NOI18N
 147.826 +                    sb.append(entry.symbol);
 147.827 +                    if (entry.asName != null) {
 147.828 +                        sb.append(" as "); // NOI18N
 147.829 +                        sb.append(entry.asName);
 147.830 +                    }
 147.831 +
 147.832 +                    if (!splitImports) {
 147.833 +                        // Look ahead and combine subsequent entries
 147.834 +                        int lookahead = i + 1;
 147.835 +                        for (; lookahead < size; lookahead++) {
 147.836 +                            ImportEntry next = sortedEntries.get(lookahead);
 147.837 +                            if (next.isFromImport != entry.isFromImport ||
 147.838 +                                    !next.module.equals(entry.module)) {
 147.839 +                                break;
 147.840 +                            }
 147.841 +                            sb.append(", "); // NOI18N
 147.842 +
 147.843 +                            if (sb.length() - start > rightMargin && (rightMargin > 30)) {
 147.844 +                                sb.append("\\\n");
 147.845 +                                start = sb.length();
 147.846 +                                sb.append(IndentUtils.createIndentString(doc, IndentUtils.indentLevelSize(doc)));
 147.847 +                            }
 147.848 +
 147.849 +                            sb.append(next.symbol);
 147.850 +                            if (next.asName != null) {
 147.851 +                                sb.append(" as ");
 147.852 +                                sb.append(next.asName);
 147.853 +                            }
 147.854 +                        }
 147.855 +                        i = lookahead - 1;
 147.856 +                    }
 147.857 +                    sb.append("\n"); // NOI18N
 147.858 +                } else {
 147.859 +                    // Plain import
 147.860 +                    // We never combine imports
 147.861 +                    sb.append("import "); // NOI18N
 147.862 +                    sb.append(entry.module);
 147.863 +                    if (entry.asName != null) {
 147.864 +                        sb.append(" as "); // NOI18N
 147.865 +                        sb.append(entry.asName);
 147.866 +                    }
 147.867 +                    sb.append("\n"); // NOI18N
 147.868 +                }
 147.869 +            }
 147.870 +        }
 147.871 +
 147.872 +        // Write commented out deleted entries as well
 147.873 +        if (remove.size() > 0 && cleanup == ImportCleanupStyle.COMMENT_OUT) {
 147.874 +            size = remove.size();
 147.875 +            List<ImportEntry> sortedRemove = new ArrayList<>();
 147.876 +            sortedRemove.addAll(remove);
 147.877 +            Collections.sort(sortedRemove);
 147.878 +            for (ImportEntry entry : sortedRemove) {
 147.879 +                if (entry.isFromImport) {
 147.880 +                    sb.append("#from "); // NOI18N
 147.881 +                    sb.append(entry.module);
 147.882 +                    sb.append(" import "); // NOI18N
 147.883 +                    sb.append(entry.symbol);
 147.884 +                    if (entry.asName != null) {
 147.885 +                        sb.append(" as "); // NOI18N
 147.886 +                        sb.append(entry.asName);
 147.887 +                    }
 147.888 +                    sb.append("\n"); // NOI18N
 147.889 +                } else {
 147.890 +                    sb.append("#import "); // NOI18N
 147.891 +                    sb.append(entry.module);
 147.892 +                    if (entry.asName != null) {
 147.893 +                        sb.append(" as "); // NOI18N
 147.894 +                        sb.append(entry.asName);
 147.895 +                    }
 147.896 +                    sb.append("\n"); // NOI18N
 147.897 +                }
 147.898 +            }
 147.899 +        }
 147.900 +
 147.901 +        // Compute editor range required
 147.902 +        OffsetRange lexRange = getMainImportsRange();
 147.903 +
 147.904 +        // Replace final newline if it's there so we don't grow whitespace around the imports
 147.905 +        int lastNewlineDelta = 0;
 147.906 +        try {
 147.907 +            if (lexRange.getEnd() < doc.getLength() && doc.getText(lexRange.getEnd(), 1).charAt(0) == '\n') {
 147.908 +                lastNewlineDelta++;
 147.909 +            }
 147.910 +        } catch (BadLocationException ex) {
 147.911 +            Exceptions.printStackTrace(ex);
 147.912 +        }
 147.913 +
 147.914 +        edits.replace(lexRange.getStart(), lexRange.getLength() + lastNewlineDelta, sb.toString(), false, 0);
 147.915 +    }
 147.916 +
 147.917 +    /** Compute the location where the main import block should be located */
 147.918 +    public int getImportsLexOffset(String module) {
 147.919 +        int begin = 0;
 147.920 +
 147.921 +        // First try computing a position in the standard imports
 147.922 +        if (module != null) {
 147.923 +            PythonTree last = null;
 147.924 +            for (PythonTree node : mainImports) {
 147.925 +                boolean stop = false;
 147.926 +                if (node instanceof Import) {
 147.927 +                    Import imp = (Import)node;
 147.928 +                    List<alias> names = imp.getInternalNames();
 147.929 +                    if (names != null && names.size() > 0 &&
 147.930 +                            names.get(0).getInternalName().compareTo(module) >= 0) {
 147.931 +                        stop = true;
 147.932 +                    }
 147.933 +                } else {
 147.934 +                    assert node instanceof ImportFrom;
 147.935 +                    ImportFrom imp = (ImportFrom)node;
 147.936 +                    if (imp.getInternalModule().compareTo(module) >= 0) {
 147.937 +                        stop = true;
 147.938 +                    }
 147.939 +                }
 147.940 +
 147.941 +                if (stop) {
 147.942 +                    return PythonLexerUtils.getLexerOffsets(info,
 147.943 +                            PythonAstUtils.getRange(node)).getStart();
 147.944 +                }
 147.945 +
 147.946 +                last = node;
 147.947 +            }
 147.948 +
 147.949 +            if (last != null) {
 147.950 +                return PythonLexerUtils.getLexerOffsets(info,
 147.951 +                        PythonAstUtils.getRange(last)).getStart();
 147.952 +            }
 147.953 +        }
 147.954 +
 147.955 +        Str documentationNode = PythonAstUtils.getDocumentationNode(root);
 147.956 +        if (documentationNode != null) {
 147.957 +            int astEnd = documentationNode.getCharStopIndex();
 147.958 +            begin = PythonLexerUtils.getLexerOffset(info, astEnd);
 147.959 +            if (begin == -1) {
 147.960 +                begin = 0;
 147.961 +            } else {
 147.962 +                begin = Math.min(doc.getLength(), begin);
 147.963 +                try {
 147.964 +                    begin = Utilities.getRowEnd(doc, begin) + 1;
 147.965 +                    begin = Math.min(begin, doc.getLength());
 147.966 +                } catch (BadLocationException ex) {
 147.967 +                    Exceptions.printStackTrace(ex);
 147.968 +                    begin = 0;
 147.969 +                }
 147.970 +            }
 147.971 +        }
 147.972 +
 147.973 +        // TODO - I should even do a lexical lookup for this in case we're in an embedded scenario!
 147.974 +        return begin;
 147.975 +    }
 147.976 +
 147.977 +    /** Determine if the given module is imported (for the given symbol) */
 147.978 +    public boolean isImported(String module, String ident) {
 147.979 +        for (Import imp : imports) {
 147.980 +            List<alias> names = imp.getInternalNames();
 147.981 +            if (names != null) {
 147.982 +                for (alias at : names) {
 147.983 +                    if (module.equals(at.getInternalName()) && (ident == null || (ident.equals(module) || ident.equals(at.getInternalAsname())))) {
 147.984 +                        return true;
 147.985 +                    }
 147.986 +                }
 147.987 +            }
 147.988 +        }
 147.989 +
 147.990 +        for (ImportFrom from : importsFrom) {
 147.991 +            if (module.equals(from.getInternalModule())) {
 147.992 +                // Make sure -this- symbol hasn't been imported!
 147.993 +                if (ident != null) {
 147.994 +                    List<alias> names = from.getInternalNames();
 147.995 +                    if (names != null) {
 147.996 +                        for (alias at : names) {
 147.997 +                            if (at.getInternalAsname() == null) {
 147.998 +                                // If you have "from module1 import Class1 as Class2", then
 147.999 +                                // "Class1" is not already imported, and "Class2" is.
147.1000 +                                if (ident.equals(at.getInternalName())) {
147.1001 +                                    return true;
147.1002 +                                }
147.1003 +                            } else if (ident.equals(at.getInternalAsname())) {
147.1004 +                                return true;
147.1005 +                            }
147.1006 +                        }
147.1007 +                    }
147.1008 +                }
147.1009 +            }
147.1010 +        }
147.1011 +
147.1012 +        return false;
147.1013 +    }
147.1014 +
147.1015 +    public void ensureImported(String name, String ident, boolean packageImport, boolean useFqn, boolean warnIfExists) {
147.1016 +        // TODO - look up the splitImports setting and add to existing import if possible...
147.1017 +
147.1018 +        if (PythonIndex.isBuiltinModule(name)) {
147.1019 +            return;
147.1020 +        }
147.1021 +
147.1022 +        // Test whether already imported
147.1023 +        if (isImported(name, ident)) {
147.1024 +            if (warnIfExists) {
147.1025 +                Utilities.setStatusText(EditorRegistry.lastFocusedComponent(),
147.1026 +                        NbBundle.getMessage(
147.1027 +                        ImportManager.class,
147.1028 +                        packageImport ? "MSG_PackageAlreadyImported" : "MSG_ClassAlreadyImported",
147.1029 +                        name, ident));
147.1030 +                Toolkit.getDefaultToolkit().beep();
147.1031 +            }
147.1032 +            return;
147.1033 +        }
147.1034 +
147.1035 +        int begin = getImportsLexOffset(ident);
147.1036 +        try {
147.1037 +            // TODO - warp to the new import and let you edit the "AS" part??
147.1038 +
147.1039 +            if (useFqn || ident == null) {
147.1040 +                doc.insertString(begin, "import " + name + "\n", null); // NOI18N
147.1041 +            } else if (packageImport) {
147.1042 +                //doc.insertString(begin, "import " + name + "\n", null); // NOI18N
147.1043 +                doc.insertString(begin, "from " + name + " import *\n", null); // NOI18N
147.1044 +            } else {
147.1045 +                doc.insertString(begin, "from " + name + " import " + ident + "\n", null); // NOI18N
147.1046 +            }
147.1047 +        } catch (BadLocationException ble) {
147.1048 +            Exceptions.printStackTrace(ble);
147.1049 +        }
147.1050 +    }
147.1051 +}
   148.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   148.2 +++ b/python.source/src/org/netbeans/modules/python/source/NameStyle.java	Sun Sep 13 11:47:42 2015 +0200
   148.3 @@ -0,0 +1,198 @@
   148.4 +/*
   148.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   148.6 + *
   148.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   148.8 + *
   148.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  148.10 + * Other names may be trademarks of their respective owners.
  148.11 + *
  148.12 + * The contents of this file are subject to the terms of either the GNU
  148.13 + * General Public License Version 2 only ("GPL") or the Common
  148.14 + * Development and Distribution License("CDDL") (collectively, the
  148.15 + * "License"). You may not use this file except in compliance with the
  148.16 + * License. You can obtain a copy of the License at
  148.17 + * http://www.netbeans.org/cddl-gplv2.html
  148.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  148.19 + * specific language governing permissions and limitations under the
  148.20 + * License.  When distributing the software, include this License Header
  148.21 + * Notice in each file and include the License file at
  148.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  148.23 + * particular file as subject to the "Classpath" exception as provided
  148.24 + * by Oracle in the GPL Version 2 section of the License file that
  148.25 + * accompanied this code. If applicable, add the following below the
  148.26 + * License Header, with the fields enclosed by brackets [] replaced by
  148.27 + * your own identifying information:
  148.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  148.29 + *
  148.30 + * If you wish your version of this file to be governed by only the CDDL
  148.31 + * or only the GPL Version 2, indicate your decision by adding
  148.32 + * "[Contributor] elects to include this software in this distribution
  148.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  148.34 + * single choice of license, a recipient has the option to distribute
  148.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  148.36 + * to extend the choice of license to its licensees as provided above.
  148.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  148.38 + * Version 2 license, then the option applies only if the new code is
  148.39 + * made subject to such option by the copyright holder.
  148.40 + *
  148.41 + * Contributor(s):
  148.42 + *
  148.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  148.44 + */
  148.45 +
  148.46 +package org.netbeans.modules.python.source;
  148.47 +
  148.48 +import org.openide.util.NbBundle;
  148.49 +
  148.50 +/**
  148.51 + *
  148.52 + * @author Tor Norbye
  148.53 + */
  148.54 +public enum NameStyle {
  148.55 +    NO_PREFERENCE(NbBundle.getMessage(NameStyle.class, "NoPreference")),
  148.56 +    LOWERCASE("lowercase"),
  148.57 +    LOWERCASE_WITH_UNDERSCORES("lowercase_with_underscores"),
  148.58 +    UPPERCASE("UPPERCASE"),
  148.59 +    UPPERCASE_WITH_UNDERSCORES("UPPERCASE_WITH_UNDERSCORES"),
  148.60 +    CAPITALIZED_WORDS("CapitalizedWords"),
  148.61 +    MIXED_CASE("mixedCase"),
  148.62 +    CAPITALIZED_WITH_UNDERSCORES("Capitalized_With_Underscores");
  148.63 +
  148.64 +    private String displayName;
  148.65 +
  148.66 +    NameStyle(String displayName) {
  148.67 +        this.displayName = displayName;
  148.68 +    }
  148.69 +
  148.70 +    public String getDisplayName() {
  148.71 +        return displayName;
  148.72 +    }
  148.73 +
  148.74 +    public boolean complies(String name) {
  148.75 +        if (name.length() == 0) {
  148.76 +            return true;
  148.77 +        }
  148.78 +
  148.79 +        // Always allow one or two "_" at the beginning and end of the name since
  148.80 +        // these are used to indicate private, builtin, etc.
  148.81 +        int start = 0;
  148.82 +        int end = name.length();
  148.83 +        if (name.startsWith("__")) { // NOI18N
  148.84 +            start = 2;
  148.85 +        } else if (name.startsWith("_")) { // NOI18N
  148.86 +            start = 1;
  148.87 +        }
  148.88 +
  148.89 +        if (name.endsWith("__")) { // NOI18N
  148.90 +            end -= 2;
  148.91 +        } else if (name.endsWith("_")) { // NOI18N
  148.92 +            end -= 1;
  148.93 +        }
  148.94 +
  148.95 +        if (start >= end) {
  148.96 +            return false;
  148.97 +        }
  148.98 +
  148.99 +        switch (this) {
 148.100 +            case NO_PREFERENCE:
 148.101 +                return true;
 148.102 +
 148.103 +            case LOWERCASE_WITH_UNDERSCORES:
 148.104 +            case LOWERCASE:
 148.105 +                for (int i = start; i < end; i++) {
 148.106 +                    char c = name.charAt(i);
 148.107 +                    if (c == '_') {
 148.108 +                        if (this != LOWERCASE_WITH_UNDERSCORES) {
 148.109 +                            return false;
 148.110 +                        }
 148.111 +                    } else if (Character.isDigit(c)) {
 148.112 +                    } else if (!Character.isLowerCase(c)) {
 148.113 +                        return false;
 148.114 +                    }
 148.115 +                }
 148.116 +                
 148.117 +                return true;
 148.118 +                
 148.119 +
 148.120 +            case UPPERCASE:
 148.121 +            case UPPERCASE_WITH_UNDERSCORES:
 148.122 +                for (int i = start; i < end; i++) {
 148.123 +                    char c = name.charAt(i);
 148.124 +                    if (c == '_') {
 148.125 +                        if (this != UPPERCASE_WITH_UNDERSCORES) {
 148.126 +                            return false;
 148.127 +                        }
 148.128 +                    } else if (Character.isDigit(c)) {
 148.129 +                    } else if (!Character.isUpperCase(c)) {
 148.130 +                        return false;
 148.131 +                    }
 148.132 +                }
 148.133 +
 148.134 +                return true;
 148.135 +
 148.136 +            case MIXED_CASE:
 148.137 +            // TODO - require that characters after _ are capitalized?
 148.138 +            case CAPITALIZED_WORDS:
 148.139 +            case CAPITALIZED_WITH_UNDERSCORES:
 148.140 +                if (this == MIXED_CASE) {
 148.141 +                    // Must begin with lowercase
 148.142 +                    if (!Character.isLowerCase(name.charAt(start))) {
 148.143 +                        return false;
 148.144 +                    }
 148.145 +                } else if (this == CAPITALIZED_WORDS || this == CAPITALIZED_WITH_UNDERSCORES) {
 148.146 +                    // Must begin with uppercase
 148.147 +                    if (!Character.isUpperCase(name.charAt(start))) {
 148.148 +                        return false;
 148.149 +                    }
 148.150 +                }
 148.151 +                for (int i = start+1; i < end; i++) {
 148.152 +                    char c = name.charAt(i);
 148.153 +                    if (c == '_') {
 148.154 +                        if (this != CAPITALIZED_WITH_UNDERSCORES) {
 148.155 +                           return false;
 148.156 +                        }
 148.157 +                    } else if (Character.isDigit(c)) {
 148.158 +                    } else if (!Character.isUpperCase(c) && !Character.isLowerCase(c)) {
 148.159 +                        return false;
 148.160 +                    }
 148.161 +
 148.162 +                    // What about digits?
 148.163 +                }
 148.164 +
 148.165 +                return true;
 148.166 +            default:
 148.167 +                assert false : this;
 148.168 +        }
 148.169 +        
 148.170 +        return true;
 148.171 +    }
 148.172 +    
 148.173 +    public static boolean isProtectedName(String name) {
 148.174 +        // Protected variable starts with a single _
 148.175 +        // this is a convention only
 148.176 +        if (!name.startsWith("__")) {
 148.177 +            // NOI18N
 148.178 +            if (name.startsWith("_")) {
 148.179 +                // NOI18N
 148.180 +                return true;
 148.181 +            }
 148.182 +        }
 148.183 +        return false;
 148.184 +    }
 148.185 +
 148.186 +    public static boolean isPrivateName(String name) {
 148.187 +        // Private variables: start with __ but doesn't end with __
 148.188 +        // Section 9.6 Private Variables - http://docs.python.org/tut/node11.html
 148.189 +        if (name != null && name.startsWith("__") && !name.endsWith("__")) {
 148.190 +            // NOI18N
 148.191 +            return true;
 148.192 +        } else if (name != null && name.startsWith("_") && !name.endsWith("_")) {
 148.193 +            // NOI18N
 148.194 +            // From PEP8: Single_leading_underscore: weak "internal use" indicator
 148.195 +            // (e.g. "from M import *" does not import objects whose name
 148.196 +            // starts with an underscore).
 148.197 +            return true;
 148.198 +        }
 148.199 +        return false;
 148.200 +    }
 148.201 +}
   149.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   149.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonAstUtils.java	Sun Sep 13 11:47:42 2015 +0200
   149.3 @@ -0,0 +1,1007 @@
   149.4 +/*
   149.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   149.6 + *
   149.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   149.8 + *
   149.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  149.10 + * Other names may be trademarks of their respective owners.
  149.11 + *
  149.12 + * The contents of this file are subject to the terms of either the GNU
  149.13 + * General Public License Version 2 only ("GPL") or the Common
  149.14 + * Development and Distribution License("CDDL") (collectively, the
  149.15 + * "License"). You may not use this file except in compliance with the
  149.16 + * License. You can obtain a copy of the License at
  149.17 + * http://www.netbeans.org/cddl-gplv2.html
  149.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  149.19 + * specific language governing permissions and limitations under the
  149.20 + * License.  When distributing the software, include this License Header
  149.21 + * Notice in each file and include the License file at
  149.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  149.23 + * particular file as subject to the "Classpath" exception as provided
  149.24 + * by Oracle in the GPL Version 2 section of the License file that
  149.25 + * accompanied this code. If applicable, add the following below the
  149.26 + * License Header, with the fields enclosed by brackets [] replaced by
  149.27 + * your own identifying information:
  149.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  149.29 + *
  149.30 + * Contributor(s):
  149.31 + *
  149.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  149.33 + */
  149.34 +package org.netbeans.modules.python.source;
  149.35 +
  149.36 +import java.util.ArrayList;
  149.37 +import java.util.Collections;
  149.38 +import java.util.HashSet;
  149.39 +import java.util.Iterator;
  149.40 +import java.util.List;
  149.41 +import java.util.Set;
  149.42 +import java.util.logging.Level;
  149.43 +import java.util.logging.Logger;
  149.44 +import javax.swing.text.BadLocationException;
  149.45 +import javax.swing.text.Document;
  149.46 +import org.netbeans.api.lexer.LanguagePath;
  149.47 +import org.netbeans.api.lexer.TokenHierarchy;
  149.48 +import org.netbeans.api.lexer.TokenSequence;
  149.49 +import org.netbeans.api.lexer.TokenUtilities;
  149.50 +import org.netbeans.editor.BaseDocument;
  149.51 +import org.netbeans.editor.Finder;
  149.52 +import org.netbeans.editor.FinderFactory;
  149.53 +import org.netbeans.modules.csl.api.ElementKind;
  149.54 +import org.netbeans.modules.csl.api.OffsetRange;
  149.55 +import org.netbeans.modules.csl.api.StructureItem;
  149.56 +import org.netbeans.modules.csl.spi.GsfUtilities;
  149.57 +import org.netbeans.modules.csl.spi.ParserResult;
  149.58 +import org.netbeans.modules.parsing.api.ParserManager;
  149.59 +import org.netbeans.modules.parsing.api.ResultIterator;
  149.60 +import org.netbeans.modules.parsing.api.Source;
  149.61 +import org.netbeans.modules.parsing.api.UserTask;
  149.62 +import org.netbeans.modules.parsing.spi.ParseException;
  149.63 +import org.netbeans.modules.python.source.elements.IndexedElement;
  149.64 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  149.65 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
  149.66 +import org.netbeans.modules.python.source.lexer.PythonCommentTokenId;
  149.67 +import org.netbeans.modules.python.source.scopes.ScopeInfo;
  149.68 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  149.69 +import org.netbeans.modules.python.source.scopes.SymInfo;
  149.70 +import org.openide.filesystems.FileObject;
  149.71 +import org.openide.util.Exceptions;
  149.72 +import org.python.antlr.PythonTree;
  149.73 +import org.python.antlr.Visitor;
  149.74 +import org.python.antlr.ast.Assign;
  149.75 +import org.python.antlr.ast.Attribute;
  149.76 +import org.python.antlr.ast.Call;
  149.77 +import org.python.antlr.ast.ClassDef;
  149.78 +import org.python.antlr.ast.Expr;
  149.79 +import org.python.antlr.ast.FunctionDef;
  149.80 +import org.python.antlr.ast.Import;
  149.81 +import org.python.antlr.ast.ImportFrom;
  149.82 +import org.python.antlr.ast.Module;
  149.83 +import org.python.antlr.ast.Name;
  149.84 +import org.python.antlr.ast.Str;
  149.85 +import org.python.antlr.ast.arguments;
  149.86 +import org.python.antlr.base.expr;
  149.87 +import org.python.antlr.base.stmt;
  149.88 +
  149.89 +/**
  149.90 + * Utility functions for dealing with the Jython AST
  149.91 + *
  149.92 + * @author Tor Norbye
  149.93 + */
  149.94 +public class PythonAstUtils {
  149.95 +    private PythonAstUtils() {
  149.96 +        // This is just a utility class, no instances expected so private constructor
  149.97 +    }
  149.98 +
  149.99 +    public static int getAstOffset(ParserResult result, int lexOffset) {
 149.100 +        if (result != null) {
 149.101 +            return result.getSnapshot().getEmbeddedOffset(lexOffset);
 149.102 +        }
 149.103 +
 149.104 +        return lexOffset;
 149.105 +    }
 149.106 +
 149.107 +    public static OffsetRange getAstOffsets(ParserResult result, OffsetRange lexicalRange) {
 149.108 +        if (result != null) {
 149.109 +            int rangeStart = lexicalRange.getStart();
 149.110 +            int start = result.getSnapshot().getEmbeddedOffset(rangeStart);
 149.111 +            if (start == rangeStart) {
 149.112 +                return lexicalRange;
 149.113 +            } else if (start == -1) {
 149.114 +                return OffsetRange.NONE;
 149.115 +            } else {
 149.116 +                // Assumes the translated range maintains size
 149.117 +                return new OffsetRange(start, start + lexicalRange.getLength());
 149.118 +            }
 149.119 +        }
 149.120 +        return lexicalRange;
 149.121 +    }
 149.122 +
 149.123 +    public static PythonParserResult getParseResult(ParserResult result) {
 149.124 +        if(result == null || !(result instanceof PythonParserResult)) {
 149.125 +            return null;
 149.126 +        } else {
 149.127 +            return ((PythonParserResult)result);
 149.128 +        }
 149.129 +    }
 149.130 +
 149.131 +    public static PythonTree getRoot(ParserResult r) {
 149.132 +        assert r instanceof PythonParserResult;
 149.133 +
 149.134 +        PythonParserResult result = (PythonParserResult)r;
 149.135 +
 149.136 +        return result.getRoot();
 149.137 +    }
 149.138 +
 149.139 +    /**
 149.140 +     * Return a range that matches the given node's source buffer range
 149.141 +     */
 149.142 +    @SuppressWarnings("unchecked")
 149.143 +    public static OffsetRange getNameRange(PythonParserResult info, PythonTree node) {
 149.144 +//        final int type = node.getType();
 149.145 +//        switch (type) {
 149.146 +//        case Token.FUNCTION: {
 149.147 +//            if (node.hasChildren()) {
 149.148 +//                for (PythonTree child = node.getFirstChild(); child != null; child = child.getNext()) {
 149.149 +//                    if (child.getType() == Token.FUNCNAME) {
 149.150 +//                        return getNameRange(child);
 149.151 +//                    }
 149.152 +//                }
 149.153 +//            }
 149.154 +//
 149.155 +//            return getRange(node);
 149.156 +//        }
 149.157 +//        case Token.NAME:
 149.158 +//        case Token.BINDNAME:
 149.159 +//        case Token.FUNCNAME:
 149.160 +//        case Token.PARAMETER:
 149.161 +//        case Token.OBJLITNAME:
 149.162 +//            int start = node.getSourceStart();
 149.163 +//            String name = node.getString();
 149.164 +//            return new OffsetRange(start, start+name.length());
 149.165 +//        case Token.CALL:
 149.166 +//            PythonTree namePythonTree = findCallNamePythonTree(node);
 149.167 +//            if (namePythonTree != null) {
 149.168 +//                return getNameRange(namePythonTree);
 149.169 +//            }
 149.170 +//        }
 149.171 +
 149.172 +        // XXX Is there a faster way to determine if it's a function,
 149.173 +        // e.g. some kind of "kind" or "id" or "type" enum attribute on the tree node
 149.174 +        if (node instanceof FunctionDef) {
 149.175 +            FunctionDef def = (FunctionDef)node;
 149.176 +            //node.getType();
 149.177 +
 149.178 +            int defStart = def.getCharStartIndex();
 149.179 +
 149.180 +            // Turns out that when you have decorators, the function start offset
 149.181 +            // -includes- the decorators which precede the "def" keyword, thus we
 149.182 +            // have to scan forwards to find the true beginning.
 149.183 +            List<expr> decorators = def.getInternalDecorator_list();
 149.184 +            if (decorators != null && decorators.size() > 0) {
 149.185 +                int maxEnd = 0;
 149.186 +                for (expr expr : decorators) {
 149.187 +                    int exprEnd = expr.getCharStopIndex();
 149.188 +                    if (exprEnd > maxEnd) {
 149.189 +                        maxEnd = exprEnd;
 149.190 +                    }
 149.191 +                }
 149.192 +                if (decorators.size() > 1) {
 149.193 +                    maxEnd++;
 149.194 +                }
 149.195 +                defStart = maxEnd;
 149.196 +
 149.197 +                // At first I was justlooking for the largest end offset of the decorators,
 149.198 +                // but if you have additional comments etc. that won't work right, so
 149.199 +                // in this case, go and look at the actual document
 149.200 +                if (info != null) {
 149.201 +                    BaseDocument doc = GsfUtilities.getDocument(info.getSnapshot().getSource().getFileObject(), false);
 149.202 +                    if (doc != null) {
 149.203 +                        int lexOffset = PythonLexerUtils.getLexerOffset(info, defStart);
 149.204 +                        int limitOffset = PythonLexerUtils.getLexerOffset(info, def.getCharStopIndex());
 149.205 +                        if (lexOffset != -1 && limitOffset != -1) {
 149.206 +                            Finder finder = new FinderFactory.StringFwdFinder("def ", true);
 149.207 +                            try {
 149.208 +                                int foundOffset = doc.find(finder, lexOffset, limitOffset);
 149.209 +                                if (foundOffset != -1) {
 149.210 +                                    defStart = foundOffset;
 149.211 +                                }
 149.212 +                            } catch (BadLocationException ex) {
 149.213 +                                Exceptions.printStackTrace(ex);
 149.214 +                            }
 149.215 +                        }
 149.216 +                    }
 149.217 +                }
 149.218 +            }
 149.219 +
 149.220 +            // HACK: There's no separate node for the name offset itself, so I need
 149.221 +            // to figure it out. For now assume that it's exactly 4 characters away
 149.222 +            // from the beginning of "def" - def plus space. If there are multiple spaces
 149.223 +            // this won't work. I ought to look in the document and ensure that the character
 149.224 +            // there in fact is the start of the name, and if not, search forwards for it.
 149.225 +            int DELTA = 4; // HACK:
 149.226 +            int start = defStart + DELTA;
 149.227 +            int end = start + def.getInternalName().length();
 149.228 +
 149.229 +            // TODO - look up offset
 149.230 +
 149.231 +            return new OffsetRange(start, end);
 149.232 +        } else if (node instanceof ClassDef) {
 149.233 +            ClassDef def = (ClassDef)node;
 149.234 +            //node.getType();
 149.235 +
 149.236 +            // HACK: There's no separate node for the name offset itself, so I need
 149.237 +            // to figure it out. For now assume that it's exactly 6 characters away
 149.238 +            // from the beginning of "class" - class plus space. If there are multiple spaces
 149.239 +            // this won't work. I ought to look in the document and ensure that the character
 149.240 +            // there in fact is the start of the name, and if not, search forwards for it.
 149.241 +            int DELTA = 6; // HACK:
 149.242 +            int start = def.getCharStartIndex() + DELTA;
 149.243 +            int end = start + def.getInternalName().length();
 149.244 +
 149.245 +            // TODO - look up offset
 149.246 +
 149.247 +            return new OffsetRange(start, end);
 149.248 +        } else if (node instanceof Attribute) {
 149.249 +            Attribute attr = (Attribute)node;
 149.250 +            return getNameRange(info, attr.getInternalValue());
 149.251 +        } else if (node instanceof Call) {
 149.252 +            Call call = (Call)node;
 149.253 +            if (call.getInternalFunc() instanceof Name) {
 149.254 +                return getNameRange(info, call.getInternalFunc());
 149.255 +            } else if (call.getInternalFunc() instanceof Attribute) {
 149.256 +                // The call name is in the value part of the name.value part
 149.257 +                Attribute attr = (Attribute)call.getInternalFunc();
 149.258 +                int start = attr.getInternalValue().getCharStopIndex() + 1; // +1: Skip .
 149.259 +                String name = attr.getInternalAttr();
 149.260 +                return new OffsetRange(start, start + name.length());
 149.261 +            } else {
 149.262 +                String name = getCallName(call);
 149.263 +                if (name != null) {
 149.264 +                    int start = call.getCharStartIndex();
 149.265 +                    return new OffsetRange(start, start + name.length());
 149.266 +                }
 149.267 +            }
 149.268 +        }
 149.269 +
 149.270 +        return getRange(node);
 149.271 +    }
 149.272 +
 149.273 +    /**
 149.274 +     * Return a range that matches the given node's source buffer range
 149.275 +     */
 149.276 +    @SuppressWarnings("unchecked")
 149.277 +    public static OffsetRange getRange(PythonTree node) {
 149.278 +        final int start = node.getCharStartIndex();
 149.279 +        final int end = node.getCharStopIndex();
 149.280 +
 149.281 +//        assert end >= start : "Invalid offsets for " + node + ": start=" + start + " and end=" + end;
 149.282 +        if (end < start) {
 149.283 +            Logger logger = Logger.getLogger(PythonAstUtils.class.getName());
 149.284 +            logger.log(Level.WARNING, "Invalid offsets for " + node + ": start=" + start + " and end=" + end);
 149.285 +            return new OffsetRange(start, start);
 149.286 +        }
 149.287 +
 149.288 +        return new OffsetRange(start, end);
 149.289 +    }
 149.290 +
 149.291 +    public static boolean isNameNode(PythonTree node) {
 149.292 +        if (node instanceof Name) {
 149.293 +            return true;
 149.294 +        }
 149.295 +
 149.296 +        return false;
 149.297 +    }
 149.298 +
 149.299 +    /** Return if a function is a staticmethod **/
 149.300 +    public static boolean isStaticMethod(PythonTree node) {
 149.301 +        if (node instanceof FunctionDef) {
 149.302 +            FunctionDef def = (FunctionDef)node;
 149.303 +            List<expr> decorators = def.getInternalDecorator_list();
 149.304 +            if (decorators != null && decorators.size() > 0) {
 149.305 +                for (expr decorator : decorators) {
 149.306 +                    if (decorator instanceof Name) {
 149.307 +                        String decoratorName = ((Name)decorator).getText();
 149.308 +                        if (decoratorName.equals("staticmethod")) { // NOI18N
 149.309 +                            return true;
 149.310 +                        }
 149.311 +                    }
 149.312 +                }
 149.313 +            }
 149.314 +        }
 149.315 +
 149.316 +        return false;
 149.317 +    }
 149.318 +
 149.319 +    /** Compute the module/class name for the given node path */
 149.320 +    public static String getFqnName(AstPath path) {
 149.321 +        StringBuilder sb = new StringBuilder();
 149.322 +
 149.323 +        Iterator<PythonTree> it = path.rootToLeaf();
 149.324 +
 149.325 +        while (it.hasNext()) {
 149.326 +            PythonTree node = it.next();
 149.327 +
 149.328 +            if (node instanceof ClassDef) {
 149.329 +                if (sb.length() > 0) {
 149.330 +                    sb.append('.'); // NOI18N
 149.331 +                }
 149.332 +                ClassDef cls = (ClassDef)node;
 149.333 +                sb.append(cls.getInternalName());
 149.334 +            }
 149.335 +        }
 149.336 +
 149.337 +        return sb.toString();
 149.338 +    }
 149.339 +
 149.340 +    /** Return the node for the local scope containing the given node */
 149.341 +    public static PythonTree getLocalScope(AstPath path) {
 149.342 +        for (PythonTree node : path) {
 149.343 +            if (node instanceof FunctionDef) {
 149.344 +                return node;
 149.345 +            }
 149.346 +        }
 149.347 +
 149.348 +        return path.root();
 149.349 +    }
 149.350 +
 149.351 +    public static PythonTree getClassScope(AstPath path) {
 149.352 +        for (PythonTree node : path) {
 149.353 +            if (node instanceof ClassDef) {
 149.354 +                return node;
 149.355 +            }
 149.356 +        }
 149.357 +
 149.358 +        return path.root();
 149.359 +    }
 149.360 +
 149.361 +    public static ClassDef getClassDef(AstPath path) {
 149.362 +        for (PythonTree node : path) {
 149.363 +            if (node instanceof ClassDef) {
 149.364 +                return (ClassDef)node;
 149.365 +            }
 149.366 +        }
 149.367 +
 149.368 +        return null;
 149.369 +    }
 149.370 +
 149.371 +    public static boolean isClassMethod(AstPath path, FunctionDef def) {
 149.372 +        // Check to see if (a) the function is inside a class, and (b) it's
 149.373 +        // not nested in a function
 149.374 +        for (PythonTree node : path) {
 149.375 +            if (node instanceof ClassDef) {
 149.376 +                return true;
 149.377 +            }
 149.378 +            // Nested method private to this one?
 149.379 +            if (node instanceof FunctionDef && node != def) {
 149.380 +                return false;
 149.381 +            }
 149.382 +        }
 149.383 +
 149.384 +        return false;
 149.385 +    }
 149.386 +
 149.387 +    public static FunctionDef getFuncDef(AstPath path) {
 149.388 +        for (PythonTree node : path) {
 149.389 +            if (node instanceof FunctionDef) {
 149.390 +                return (FunctionDef)node;
 149.391 +            }
 149.392 +        }
 149.393 +
 149.394 +        return null;
 149.395 +    }
 149.396 +
 149.397 +    /**
 149.398 +     * Return true iff this call looks like a "getter". If we're not sure,
 149.399 +     * return the default value passed into this method, unknownDefault. 
 149.400 +     */
 149.401 +    public static boolean isGetter(Call call, boolean unknownDefault) {
 149.402 +        String name = PythonAstUtils.getCallName(call);
 149.403 +        if (name == null) {
 149.404 +            return unknownDefault;
 149.405 +        }
 149.406 +
 149.407 +        return name.startsWith("get") || name.startsWith("_get"); // NOI18N
 149.408 +    }
 149.409 +
 149.410 +    public static String getCallName(Call call) {
 149.411 +        expr func = call.getInternalFunc();
 149.412 +
 149.413 +        return getExprName(func);
 149.414 +    }
 149.415 +
 149.416 +    public static String getExprName(expr type) {
 149.417 +        if (type instanceof Attribute) {
 149.418 +            Attribute attr = (Attribute)type;
 149.419 +            return attr.getInternalAttr();
 149.420 +        } else if (type instanceof Name) {
 149.421 +            return ((Name)type).getInternalId();
 149.422 +        } else if (type instanceof Call) {
 149.423 +            Call call = (Call)type;
 149.424 +            return getExprName(call.getInternalFunc());
 149.425 +            //} else if (type instanceof Str) {
 149.426 +            //    return ((Str)type).getText();
 149.427 +        } else {
 149.428 +            return null;
 149.429 +        }
 149.430 +    }
 149.431 +
 149.432 +    public static String getName(PythonTree node) {
 149.433 +        if (node instanceof Name) {
 149.434 +            return ((Name)node).getInternalId();
 149.435 +        }
 149.436 +        if (node instanceof Attribute) {
 149.437 +            Attribute attrib = (Attribute)node;
 149.438 +            String prefix = getName(attrib.getInternalValue());
 149.439 +            return (prefix + '.' + attrib.getInternalAttr());
 149.440 +        }
 149.441 +        NameVisitor visitor = new NameVisitor();
 149.442 +        try {
 149.443 +            Object result = visitor.visit(node);
 149.444 +            if (result instanceof String) {
 149.445 +                return (String)result;
 149.446 +            } else {
 149.447 +                // TODO HANDLE THIS!
 149.448 +            }
 149.449 +        } catch (Exception ex) {
 149.450 +            Exceptions.printStackTrace(ex);
 149.451 +        }
 149.452 +
 149.453 +        return null;
 149.454 +    }
 149.455 +
 149.456 +    public static List<String> getParameters(FunctionDef def) {
 149.457 +        arguments args = def.getInternalArgs();
 149.458 +        List<String> params = new ArrayList<>();
 149.459 +
 149.460 +        NameVisitor visitor = new NameVisitor();
 149.461 +
 149.462 +        for (expr e : args.getInternalArgs()) {
 149.463 +            try {
 149.464 +                Object result = visitor.visit(e);
 149.465 +                if (result instanceof String) {
 149.466 +                    params.add((String)result);
 149.467 +                } else {
 149.468 +                    // TODO HANDLE THIS!
 149.469 +                }
 149.470 +            } catch (Exception ex) {
 149.471 +                Exceptions.printStackTrace(ex);
 149.472 +            }
 149.473 +        }
 149.474 +
 149.475 +        String vararg = args.getInternalVararg();
 149.476 +        if (vararg != null) {
 149.477 +            params.add(vararg);
 149.478 +        }
 149.479 +        String kwarg = args.getInternalKwarg();
 149.480 +        if (kwarg != null) {
 149.481 +            params.add(kwarg);
 149.482 +        }
 149.483 +
 149.484 +        return params;
 149.485 +    }
 149.486 +
 149.487 +    private static Str searchForDocNode(stmt stmt) {
 149.488 +        if (stmt instanceof Expr) {
 149.489 +            Expr expr = (Expr)stmt;
 149.490 +            expr value = expr.getInternalValue();
 149.491 +            if (value instanceof Str) {
 149.492 +                return (Str)value;
 149.493 +            }
 149.494 +        }
 149.495 +
 149.496 +        return null;
 149.497 +    }
 149.498 +
 149.499 +    public static Str getDocumentationNode(PythonTree node) {
 149.500 +        // DocString processing.
 149.501 +        // See http://www.python.org/dev/peps/pep-0257/
 149.502 +
 149.503 +        // For modules, it's the first Str in the document.
 149.504 +        // For classes and methods, it's the first Str in the object.
 149.505 +        // For others, nothing.
 149.506 +
 149.507 +        if (node instanceof FunctionDef) {
 149.508 +            // Function
 149.509 +            FunctionDef def = (FunctionDef)node;
 149.510 +            List<stmt> body = def.getInternalBody();
 149.511 +            if (body != null && body.size() > 0) {
 149.512 +                return searchForDocNode(body.get(0));
 149.513 +            }
 149.514 +        } else if (node instanceof ClassDef) {
 149.515 +            // Class
 149.516 +            ClassDef def = (ClassDef)node;
 149.517 +            List<stmt> body = def.getInternalBody();
 149.518 +            if (body != null && body.size() > 0) {
 149.519 +                return searchForDocNode(body.get(0));
 149.520 +            }
 149.521 +        } else if (node instanceof Module) {
 149.522 +            // Module
 149.523 +            Module module = (Module)node;
 149.524 +            List<stmt> body = module.getInternalBody();
 149.525 +            if (body != null && body.size() > 0) {
 149.526 +                return searchForDocNode(body.get(0));
 149.527 +            }
 149.528 +        }
 149.529 +        // TODO: As per http://www.python.org/dev/peps/pep-0257/ I should
 149.530 +        // also look for "additional docstrings" (Str node following a Str node)
 149.531 +        // and Assign str nodes
 149.532 +
 149.533 +        return null;
 149.534 +    }
 149.535 +
 149.536 +    public static String getStrContent(Str str) {
 149.537 +        String doc = str.getText();
 149.538 +
 149.539 +        // Strip quotes
 149.540 +        // and U and/or R for unicode/raw string. U must always preceede r if present.
 149.541 +        if (doc.startsWith("ur") || doc.startsWith("UR") || // NOI18N
 149.542 +                doc.startsWith("Ur") || doc.startsWith("uR")) { // NOI18N
 149.543 +            doc = doc.substring(2);
 149.544 +        } else if (doc.startsWith("r") || doc.startsWith("u") || // NOI18N
 149.545 +                doc.startsWith("R") || doc.startsWith("U")) { // NOI18N
 149.546 +            doc = doc.substring(1);
 149.547 +        }
 149.548 +
 149.549 +        if (doc.startsWith("\"\"\"") && doc.endsWith("\"\"\"")) { // NOI18N
 149.550 +            doc = doc.substring(3, doc.length() - 3);
 149.551 +        } else if (doc.startsWith("r\"\"\"") && doc.endsWith("\"\"\"")) { // NOI18N
 149.552 +            doc = doc.substring(4, doc.length() - 3);
 149.553 +        } else if (doc.startsWith("'''") && doc.endsWith("'''")) { // NOI18N
 149.554 +            doc = doc.substring(3, doc.length() - 3);
 149.555 +        } else if (doc.startsWith("r'''") && doc.endsWith("'''")) { // NOI18N
 149.556 +            doc = doc.substring(4, doc.length() - 3);
 149.557 +        } else if (doc.startsWith("\"") && doc.endsWith("\"")) { // NOI18N
 149.558 +            doc = doc.substring(1, doc.length() - 1);
 149.559 +        } else if (doc.startsWith("'") && doc.endsWith("'")) { // NOI18N
 149.560 +            doc = doc.substring(1, doc.length() - 1);
 149.561 +        }
 149.562 +
 149.563 +        return doc;
 149.564 +    }
 149.565 +
 149.566 +    public static String getDocumentation(PythonTree node) {
 149.567 +        Str str = getDocumentationNode(node);
 149.568 +        if (str != null) {
 149.569 +            return getStrContent(str);
 149.570 +        }
 149.571 +
 149.572 +        return null;
 149.573 +    }
 149.574 +
 149.575 +    public static PythonTree getForeignNode(final IndexedElement o, PythonParserResult[] parserResultRet) {
 149.576 +        FileObject fo = o.getFileObject();
 149.577 +
 149.578 +        if (fo == null) {
 149.579 +            return null;
 149.580 +        }
 149.581 +        
 149.582 +        Source source = Source.create(fo);
 149.583 +        if(source == null) {
 149.584 +            return null;
 149.585 +        }
 149.586 +        final PythonParserResult[] resultHolder = new PythonParserResult[1];
 149.587 +        try {
 149.588 +            ParserManager.parse(Collections.singleton(source), new UserTask() {
 149.589 +                
 149.590 +                @Override
 149.591 +                public void run(ResultIterator resultIterator) throws Exception {
 149.592 +                    resultHolder[0] = (PythonParserResult) resultIterator.getParserResult();
 149.593 +                }
 149.594 +            });
 149.595 +        } catch (ParseException ex) {
 149.596 +            Exceptions.printStackTrace(ex);
 149.597 +        }
 149.598 +
 149.599 +        PythonParserResult info = resultHolder[0];
 149.600 +        if (parserResultRet != null) {
 149.601 +            parserResultRet[0] = info;
 149.602 +        }
 149.603 +        PythonParserResult result = getParseResult(info);
 149.604 +        if (result == null) {
 149.605 +            return null;
 149.606 +        }
 149.607 +
 149.608 +        PythonTree root = getRoot(result);
 149.609 +        if (root == null) {
 149.610 +            return null;
 149.611 +        }
 149.612 +
 149.613 +        if (o.getKind() == ElementKind.MODULE && root instanceof Module) {
 149.614 +            return root;
 149.615 +        }
 149.616 +
 149.617 +        String signature = o.getSignature();
 149.618 +
 149.619 +        if (signature == null) {
 149.620 +            return null;
 149.621 +        }
 149.622 +
 149.623 +        SymbolTable symbolTable = result.getSymbolTable();
 149.624 +        SymInfo sym = symbolTable.findBySignature(o.getKind(), signature);
 149.625 +        if (sym != null && sym.node != null) {
 149.626 +            // Temporary diagnostic checking
 149.627 +            //assert ((o.getKind() != ElementKind.CONSTRUCTOR && o.getKind() != ElementKind.METHOD) ||
 149.628 +            //        sym.node instanceof FunctionDef);
 149.629 +            //assert o.getKind() != ElementKind.CLASS || sym.node instanceof ClassDef;
 149.630 +
 149.631 +            return sym.node;
 149.632 +        }
 149.633 +
 149.634 +        // TODO - check args etc.
 149.635 +//        String name = o.getName();
 149.636 +//        boolean lookForFunction = o.getKind() == ElementKind.CONSTRUCTOR || o.getKind() == ElementKind.METHOD;
 149.637 +//        if (lookForFunction) {
 149.638 +//            for (AstElement element : result.getStructure().getElements()) {
 149.639 +//                if (element.getName().equals(name) && element.getSignature().equals(signature)) {
 149.640 +//                        return element.getNode();
 149.641 +//                    }
 149.642 +//                }
 149.643 +//            }
 149.644 +//        }
 149.645 +
 149.646 +        ElementKind kind = o.getKind();
 149.647 +        List<PythonStructureItem> items = PythonStructureScanner.analyze(info).getElements();
 149.648 +        if (items != null) {
 149.649 +            return find(items, signature, kind);
 149.650 +        } else {
 149.651 +            return null;
 149.652 +        }
 149.653 +    }
 149.654 +
 149.655 +    private static PythonTree find(List<? extends StructureItem> items, String signature, ElementKind kind) {
 149.656 +        for (StructureItem item : items) {
 149.657 +            ElementKind childKind = item.getKind();
 149.658 +            if (childKind == kind &&
 149.659 +                    item instanceof PythonStructureItem &&
 149.660 +                    signature.equals(((PythonStructureItem)item).getSignature())) {
 149.661 +                return ((PythonStructureItem)item).getNode();
 149.662 +            }
 149.663 +            if (childKind == ElementKind.CLASS && signature.contains(item.getName())) {
 149.664 +                @SuppressWarnings("unchecked")
 149.665 +                List<? extends StructureItem> children = item.getNestedItems();
 149.666 +                PythonTree result = find(children, signature, kind);
 149.667 +                if (result != null) {
 149.668 +                    return result;
 149.669 +                }
 149.670 +            }
 149.671 +        }
 149.672 +
 149.673 +        return null;
 149.674 +    }
 149.675 +
 149.676 +    public static Set<OffsetRange> getAllOffsets(PythonParserResult info, AstPath path, int lexOffset, String name, boolean abortOnFree) {
 149.677 +        if (path == null) {
 149.678 +            path = AstPath.get(PythonAstUtils.getRoot(info), lexOffset);
 149.679 +        }
 149.680 +        PythonTree scope = PythonAstUtils.getLocalScope(path);
 149.681 +        SymbolTable symbolTable = PythonAstUtils.getParseResult(info).getSymbolTable();
 149.682 +        List<PythonTree> nodes = symbolTable.getOccurrences(scope, name, abortOnFree);
 149.683 +        if (nodes == null) {
 149.684 +            return null;
 149.685 +        }
 149.686 +        Set<OffsetRange> offsets = new HashSet<>();
 149.687 +        Document doc = GsfUtilities.getDocument(info.getSnapshot().getSource().getFileObject(), false);
 149.688 +        if (doc == null) {
 149.689 +            return Collections.emptySet();
 149.690 +        }
 149.691 +        for (PythonTree node : nodes) {
 149.692 +            OffsetRange astRange = PythonAstUtils.getNameRange(info, node);
 149.693 +            OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 149.694 +
 149.695 +            if (node instanceof Import || node instanceof ImportFrom) {
 149.696 +                // Try to find the exact spot
 149.697 +                if (abortOnFree) {
 149.698 +                    return null;
 149.699 +                } else {
 149.700 +                    lexRange = PythonLexerUtils.getImportNameOffset((BaseDocument)doc, lexRange, node, name);
 149.701 +                }
 149.702 +            } else if (abortOnFree && (node instanceof FunctionDef || node instanceof ClassDef)) {
 149.703 +                return null;
 149.704 +            }
 149.705 +
 149.706 +            if (lexRange != OffsetRange.NONE) {
 149.707 +                offsets.add(lexRange);
 149.708 +            }
 149.709 +        }
 149.710 +        // Look for type variables
 149.711 +        ScopeInfo scopeInfo = symbolTable.getScopeInfo(scope);
 149.712 +        if (scopeInfo != null) {
 149.713 +            SymInfo sym = scopeInfo.tbl.get(name);
 149.714 +            if (sym != null && sym.isVariable(false)) {
 149.715 +                // Look for type declarations that can apply to this variable
 149.716 +                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, PythonAstUtils.getRange(scope));
 149.717 +                if (lexRange != OffsetRange.NONE) {
 149.718 +                    BaseDocument bdoc = (BaseDocument)doc;
 149.719 +                    try {
 149.720 +                        bdoc.readLock(); // For TokenHierarchy usage
 149.721 +                        TokenHierarchy hi = TokenHierarchy.get(doc);
 149.722 +                        LanguagePath languagePath = LanguagePath.get(LanguagePath.get(PythonTokenId.language()), PythonCommentTokenId.language());
 149.723 +                        int startOffset = Math.min(lexRange.getStart(), doc.getLength());
 149.724 +                        if (scope instanceof Module) {
 149.725 +                            startOffset = 0; // Pick up comments before code starts
 149.726 +                        }
 149.727 +                        int endOffset = Math.min(lexRange.getEnd(), doc.getLength());
 149.728 +                        @SuppressWarnings("unchecked")
 149.729 +                        List<TokenSequence<? extends PythonCommentTokenId>> tsl = hi.tokenSequenceList(languagePath, startOffset, endOffset);
 149.730 +                        for (TokenSequence<? extends PythonCommentTokenId> ts : tsl) {
 149.731 +                            ts.moveStart();
 149.732 +                            while (ts.moveNext()) {
 149.733 +                                PythonCommentTokenId id = ts.token().id();
 149.734 +                                if (id == PythonCommentTokenId.TYPEKEY) {
 149.735 +                                    if (ts.moveNext() && // skip separator
 149.736 +                                            ts.moveNext()) {
 149.737 +                                        if (ts.token().id() == PythonCommentTokenId.VARNAME) {
 149.738 +                                            if (TokenUtilities.equals(ts.token().text(), name)) {
 149.739 +                                                int start = ts.offset();
 149.740 +                                                OffsetRange nameRange = new OffsetRange(start, start + name.length());
 149.741 +                                                offsets.add(nameRange);
 149.742 +                                            }
 149.743 +                                        }
 149.744 +                                    }
 149.745 +                                }
 149.746 +                            }
 149.747 +                        }
 149.748 +                    } finally {
 149.749 +                        bdoc.readUnlock();
 149.750 +                    }
 149.751 +
 149.752 +                }
 149.753 +            }
 149.754 +        }
 149.755 +
 149.756 +        return offsets;
 149.757 +    }
 149.758 +
 149.759 +    private static final class NameVisitor extends Visitor {
 149.760 +        @Override
 149.761 +        public Object visitName(Name name) throws Exception {
 149.762 +            return name.getInternalId();
 149.763 +        }
 149.764 +    }
 149.765 +
 149.766 +    public static Set<OffsetRange> getLocalVarOffsets(PythonParserResult info, int lexOffset) {
 149.767 +        int astOffset = getAstOffset(info, lexOffset);
 149.768 +        if (astOffset != -1) {
 149.769 +            PythonTree root = getRoot(info);
 149.770 +            if (root != null) {
 149.771 +                AstPath path = AstPath.get(root, astOffset);
 149.772 +                if (path != null) {
 149.773 +                    PythonTree closest = path.leaf();
 149.774 +                    PythonTree scope = getLocalScope(path);
 149.775 +                    String name = ((Name)closest).getInternalId();
 149.776 +
 149.777 +                    return getLocalVarOffsets(info, scope, name);
 149.778 +                }
 149.779 +            }
 149.780 +        }
 149.781 +
 149.782 +        return Collections.emptySet();
 149.783 +    }
 149.784 +
 149.785 +    public static Set<OffsetRange> getLocalVarOffsets(PythonParserResult info, PythonTree scope, String name) {
 149.786 +        LocalVarVisitor visitor = new LocalVarVisitor(info, name, false, true);
 149.787 +        try {
 149.788 +            visitor.visit(scope);
 149.789 +            return visitor.getOffsets();
 149.790 +        } catch (Exception ex) {
 149.791 +            Exceptions.printStackTrace(ex);
 149.792 +            return Collections.emptySet();
 149.793 +        }
 149.794 +    }
 149.795 +
 149.796 +    public static List<Name> getLocalVarNodes(PythonParserResult info, PythonTree scope, String name) {
 149.797 +        LocalVarVisitor visitor = new LocalVarVisitor(info, name, true, false);
 149.798 +        try {
 149.799 +            visitor.visit(scope);
 149.800 +            return visitor.getVars();
 149.801 +        } catch (Exception ex) {
 149.802 +            Exceptions.printStackTrace(ex);
 149.803 +            return Collections.emptyList();
 149.804 +        }
 149.805 +    }
 149.806 +
 149.807 +    public static List<Name> getLocalVarAssignNodes(PythonParserResult info, PythonTree scope, String name) {
 149.808 +        LocalVarAssignVisitor visitor = new LocalVarAssignVisitor(info, name, true, false);
 149.809 +        try {
 149.810 +            visitor.visit(scope);
 149.811 +            return visitor.getVars();
 149.812 +        } catch (Exception ex) {
 149.813 +            Exceptions.printStackTrace(ex);
 149.814 +            return Collections.emptyList();
 149.815 +        }
 149.816 +    }
 149.817 +
 149.818 +    private static class LocalVarVisitor extends Visitor {
 149.819 +        private List<Name> vars = new ArrayList<>();
 149.820 +        private Set<OffsetRange> offsets = new HashSet<>();
 149.821 +        private String name;
 149.822 +        private PythonParserResult info;
 149.823 +        private boolean collectNames;
 149.824 +        private boolean collectOffsets;
 149.825 +        private PythonTree parent;
 149.826 +
 149.827 +        private LocalVarVisitor(PythonParserResult info, String name, boolean collectNames, boolean collectOffsets) {
 149.828 +            this.info = info;
 149.829 +            this.name = name;
 149.830 +            this.collectNames = collectNames;
 149.831 +            this.collectOffsets = collectOffsets;
 149.832 +        }
 149.833 +
 149.834 +        @Override
 149.835 +        public void traverse(PythonTree node) throws Exception {
 149.836 +            PythonTree oldParent = parent;
 149.837 +            parent = node;
 149.838 +            super.traverse(node);
 149.839 +            parent = oldParent;
 149.840 +        }
 149.841 +
 149.842 +        @Override
 149.843 +        public Object visitName(Name node) throws Exception {
 149.844 +            if (parent instanceof Call && ((Call)parent).getInternalFunc() == node) {
 149.845 +                return super.visitName(node);
 149.846 +            }
 149.847 +
 149.848 +            if ((name == null && !PythonUtils.isClassName(node.getInternalId(), false)) ||
 149.849 +                    (name != null && name.equals(node.getInternalId()))) {
 149.850 +                if (collectOffsets) {
 149.851 +                    OffsetRange astRange = PythonAstUtils.getNameRange(info, node);
 149.852 +                    OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 149.853 +                    if (lexRange != OffsetRange.NONE) {
 149.854 +                        offsets.add(astRange);
 149.855 +                    }
 149.856 +                }
 149.857 +                if (collectNames) {
 149.858 +                    vars.add(node);
 149.859 +                }
 149.860 +            }
 149.861 +
 149.862 +            return super.visitName(node);
 149.863 +        }
 149.864 +
 149.865 +        public Set<OffsetRange> getOffsets() {
 149.866 +            return offsets;
 149.867 +        }
 149.868 +
 149.869 +        public List<Name> getVars() {
 149.870 +            return vars;
 149.871 +        }
 149.872 +    }
 149.873 +
 149.874 +    private static class LocalVarAssignVisitor extends Visitor {
 149.875 +        private List<Name> vars = new ArrayList<>();
 149.876 +        private Set<OffsetRange> offsets = new HashSet<>();
 149.877 +        private String name;
 149.878 +        private PythonParserResult info;
 149.879 +        private boolean collectNames;
 149.880 +        private boolean collectOffsets;
 149.881 +        private PythonTree parent;
 149.882 +
 149.883 +        private LocalVarAssignVisitor(PythonParserResult info, String name, boolean collectNames, boolean collectOffsets) {
 149.884 +            this.info = info;
 149.885 +            this.name = name;
 149.886 +            this.collectNames = collectNames;
 149.887 +            this.collectOffsets = collectOffsets;
 149.888 +        }
 149.889 +
 149.890 +        @Override
 149.891 +        public Object visitName(Name node) throws Exception {
 149.892 +            if (parent instanceof FunctionDef || parent instanceof Assign) {
 149.893 +                if ((name == null && !PythonUtils.isClassName(node.getInternalId(), false)) ||
 149.894 +                        (name != null && name.equals(node.getInternalId()))) {
 149.895 +                    if (collectOffsets) {
 149.896 +                        OffsetRange astRange = PythonAstUtils.getNameRange(info, node);
 149.897 +                        OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 149.898 +                        if (lexRange != OffsetRange.NONE) {
 149.899 +                            offsets.add(astRange);
 149.900 +                        }
 149.901 +                    }
 149.902 +                    if (collectNames) {
 149.903 +                        vars.add(node);
 149.904 +                    }
 149.905 +                }
 149.906 +            }
 149.907 +
 149.908 +            return super.visitName(node);
 149.909 +        }
 149.910 +
 149.911 +        @Override
 149.912 +        public void traverse(PythonTree node) throws Exception {
 149.913 +            PythonTree oldParent = parent;
 149.914 +            parent = node;
 149.915 +            super.traverse(node);
 149.916 +            parent = oldParent;
 149.917 +        }
 149.918 +
 149.919 +        public Set<OffsetRange> getOffsets() {
 149.920 +            return offsets;
 149.921 +        }
 149.922 +
 149.923 +        public List<Name> getVars() {
 149.924 +            return vars;
 149.925 +        }
 149.926 +    }
 149.927 +
 149.928 +    /** Collect nodes of the given types (node.nodeId==NodeTypes.x) under the given root */
 149.929 +    public static void addNodesByType(PythonTree root, Class[] nodeClasses, List<PythonTree> result) {
 149.930 +        try {
 149.931 +            new NodeTypeVisitor(result, nodeClasses).visit(root);
 149.932 +        } catch (Exception ex) {
 149.933 +            Exceptions.printStackTrace(ex);
 149.934 +        }
 149.935 +    }
 149.936 +
 149.937 +    private static class NodeTypeVisitor extends Visitor {
 149.938 +        private Class[] nodeClasses;
 149.939 +        private List<PythonTree> result;
 149.940 +
 149.941 +        NodeTypeVisitor(List<PythonTree> result, Class[] nodeClasses) {
 149.942 +            this.result = result;
 149.943 +            this.nodeClasses = nodeClasses;
 149.944 +        }
 149.945 +
 149.946 +        @Override
 149.947 +        public void traverse(PythonTree node) throws Exception {
 149.948 +            for (Class nodeClasse : nodeClasses) {
 149.949 +                if (node.getClass() == nodeClasse) {
 149.950 +                    result.add(node);
 149.951 +                    break;
 149.952 +                }
 149.953 +            }
 149.954 +
 149.955 +            super.traverse(node);
 149.956 +        }
 149.957 +    }
 149.958 +
 149.959 +    public static Name getParentClassFromNode(AstPath path, PythonTree from, String name) {
 149.960 +        ClassDef curClass = (ClassDef)path.getTypedAncestor(ClassDef.class, from);
 149.961 +        if (curClass == null) {
 149.962 +            return null;
 149.963 +        }
 149.964 +
 149.965 +        List<expr> baseClasses = curClass.getInternalBases();
 149.966 +        if (baseClasses == null) {
 149.967 +            return null; // no inheritance ;
 149.968 +        }
 149.969 +        int ii = 0;
 149.970 +        while (ii < baseClasses.size()) {
 149.971 +            if (baseClasses.get(ii) instanceof Name) {
 149.972 +                Name cur = (Name)baseClasses.get(ii);
 149.973 +                if (cur.getInternalId().equals(name)) {
 149.974 +                    return cur;
 149.975 +                }
 149.976 +            }
 149.977 +            ii++;
 149.978 +        }
 149.979 +        return null;
 149.980 +    }
 149.981 +
 149.982 +    /**
 149.983 +     * Look for the caret offset in the parameter list; return the
 149.984 +     * index of the parameter that contains it.
 149.985 +     */
 149.986 +    public static int findArgumentIndex(Call call, int astOffset, AstPath path) {
 149.987 +
 149.988 +        // On the name part in the call rather than the args?
 149.989 +        if (astOffset <= call.getInternalFunc().getCharStopIndex()) {
 149.990 +            return -1;
 149.991 +        }
 149.992 +        List<expr> args = call.getInternalArgs();
 149.993 +        if (args != null) {
 149.994 +            int index = 0;
 149.995 +            for (; index < args.size(); index++) {
 149.996 +                expr et = args.get(index);
 149.997 +                if (et.getCharStopIndex() >= astOffset) {
 149.998 +                    return index;
 149.999 +                }
149.1000 +            }
149.1001 +        }
149.1002 +
149.1003 +        // TODO what about the other stuff in there -- 
149.1004 +        //call.keywords;
149.1005 +        //call.kwargs;
149.1006 +        //call.starargs;
149.1007 +
149.1008 +        return -1;
149.1009 +    }
149.1010 +}
   150.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   150.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonExample.py	Sun Sep 13 11:47:42 2015 +0200
   150.3 @@ -0,0 +1,10 @@
   150.4 +"""Sample Module"""
   150.5 +import foo
   150.6 +CONSTANT = "VALUE"
   150.7 +
   150.8 +class Foo(Bar):
   150.9 +    """Class doc"""
  150.10 +
  150.11 +    def __init__(self,args=''):
  150.12 +        # Comment
  150.13 +        print 1+2.0
   151.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   151.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonFormatter.java	Sun Sep 13 11:47:42 2015 +0200
   151.3 @@ -0,0 +1,655 @@
   151.4 +/*
   151.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   151.6 + *
   151.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   151.8 + *
   151.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  151.10 + * Other names may be trademarks of their respective owners.
  151.11 + *
  151.12 + * The contents of this file are subject to the terms of either the GNU
  151.13 + * General Public License Version 2 only ("GPL") or the Common
  151.14 + * Development and Distribution License("CDDL") (collectively, the
  151.15 + * "License"). You may not use this file except in compliance with the
  151.16 + * License. You can obtain a copy of the License at
  151.17 + * http://www.netbeans.org/cddl-gplv2.html
  151.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  151.19 + * specific language governing permissions and limitations under the
  151.20 + * License.  When distributing the software, include this License Header
  151.21 + * Notice in each file and include the License file at
  151.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  151.23 + * particular file as subject to the "Classpath" exception as provided
  151.24 + * by Oracle in the GPL Version 2 section of the License file that
  151.25 + * accompanied this code. If applicable, add the following below the
  151.26 + * License Header, with the fields enclosed by brackets [] replaced by
  151.27 + * your own identifying information:
  151.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  151.29 + *
  151.30 + * If you wish your version of this file to be governed by only the CDDL
  151.31 + * or only the GPL Version 2, indicate your decision by adding
  151.32 + * "[Contributor] elects to include this software in this distribution
  151.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  151.34 + * single choice of license, a recipient has the option to distribute
  151.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  151.36 + * to extend the choice of license to its licensees as provided above.
  151.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  151.38 + * Version 2 license, then the option applies only if the new code is
  151.39 + * made subject to such option by the copyright holder.
  151.40 + *
  151.41 + * Contributor(s):
  151.42 + *
  151.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  151.44 + */
  151.45 +package org.netbeans.modules.python.source;
  151.46 +
  151.47 +import java.util.ArrayList;
  151.48 +import java.util.Collections;
  151.49 +import java.util.HashMap;
  151.50 +import java.util.List;
  151.51 +import java.util.Map;
  151.52 +import javax.swing.text.BadLocationException;
  151.53 +import javax.swing.text.Document;
  151.54 +import javax.swing.text.JTextComponent;
  151.55 +import org.netbeans.api.editor.EditorRegistry;
  151.56 +import org.netbeans.api.lexer.TokenSequence;
  151.57 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  151.58 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
  151.59 +import org.netbeans.api.lexer.Token;
  151.60 +import org.netbeans.api.lexer.TokenId;
  151.61 +import org.netbeans.api.lexer.TokenUtilities;
  151.62 +import org.netbeans.editor.BaseDocument;
  151.63 +import org.netbeans.editor.Utilities;
  151.64 +import org.netbeans.modules.csl.api.EditList;
  151.65 +import org.netbeans.modules.csl.api.Formatter;
  151.66 +import org.netbeans.modules.csl.spi.GsfUtilities;
  151.67 +import org.netbeans.modules.csl.spi.ParserResult;
  151.68 +import org.netbeans.modules.editor.indent.api.IndentUtils;
  151.69 +import org.netbeans.modules.editor.indent.spi.Context;
  151.70 +import org.openide.util.Exceptions;
  151.71 +
  151.72 +/**
  151.73 + * Implement formatting for Python. Since there are no {}'s etc. to uniquely
  151.74 + * impose indentation on Python, this formatter really just tries to enforce
  151.75 + * spaces-versus-tabs, and indentation width. E.g. it uses the existing indentation
  151.76 + * to determine whether the next line should be idented more, same or less as the
  151.77 + * current line and then enforces the current space and indent size settings.
  151.78 + *
  151.79 + * @todo Implement pretty printing: inserting newlines, removing spaces inside
  151.80 + *  parentheses, etc. See the recommendations in
  151.81 + *   http://www.python.org/dev/peps/pep-0008/
  151.82 + *  Do import statement cleanup too.
  151.83 + * @todo Line up comment lines (# as a suffix, continued from a previous line)
  151.84 + * @todo Handle continuation lines with extra indentation
  151.85 + * @todo Line up list initializations better?
  151.86 + * 
  151.87 + * @author Tor Norbye
  151.88 + */
  151.89 +public class PythonFormatter implements Formatter {
  151.90 +    private int indentSize;
  151.91 +    private int continuationIndentSize;
  151.92 +    private CodeStyle codeStyle;
  151.93 +
  151.94 +    public PythonFormatter() {
  151.95 +    }
  151.96 +
  151.97 +    public PythonFormatter(CodeStyle codeStyle) {
  151.98 +        this.codeStyle = codeStyle;
  151.99 +    }
 151.100 +
 151.101 +    @Override
 151.102 +    public void reformat(Context context, ParserResult compilationInfo) {
 151.103 +
 151.104 +        // No AST pretty printing yet
 151.105 +        // I should offer to go and do space insert/removal around commas, parentheses, etc.
 151.106 +        //  as well as balancing long argument lists across lines
 151.107 +        Document document = context.document();
 151.108 +        int startOffset = context.startOffset();
 151.109 +        int endOffset = context.endOffset();
 151.110 +
 151.111 +        reformat(context, document, startOffset, endOffset, (PythonParserResult) compilationInfo);
 151.112 +    }
 151.113 +
 151.114 +    public void reformat(final Context context, Document document, int startOffset, int endOffset, PythonParserResult info) {
 151.115 +        if (codeStyle == null) {
 151.116 +            codeStyle = CodeStyle.getDefault(context.document());
 151.117 +        }
 151.118 +        if (info != null && codeStyle != null && codeStyle.formatImports() && !GsfUtilities.isCodeTemplateEditing(document) &&
 151.119 +                PythonAstUtils.getParseResult(info) != null) {
 151.120 +            new ImportManager(info, (BaseDocument)document, codeStyle).cleanup(null, startOffset, endOffset, false);
 151.121 +        }
 151.122 +
 151.123 +        if (codeStyle != null) {
 151.124 +            cleanup(document, info, startOffset, endOffset);
 151.125 +        }
 151.126 +
 151.127 +        reindent(context, document, startOffset, endOffset);
 151.128 +    }
 151.129 +
 151.130 +    @Override
 151.131 +    public boolean needsParserResult() {
 151.132 +//        if (SourceUtils.isScanInProgress()) {
 151.133 +//            return false;
 151.134 +//        }
 151.135 +
 151.136 +        // If we're going to format imports, then yes, we need the parser result
 151.137 +        JTextComponent target = EditorRegistry.lastFocusedComponent();
 151.138 +        if (target != null) {
 151.139 +            CodeStyle cs = CodeStyle.getDefault(target.getDocument());
 151.140 +            return cs != null ? cs.formatImports() : false;
 151.141 +        }
 151.142 +        return false;
 151.143 +    }
 151.144 +
 151.145 +    @Override
 151.146 +    public int indentSize() {
 151.147 +        // 4 spaces: See http://www.python.org/dev/peps/pep-0008/
 151.148 +        return 4;
 151.149 +    }
 151.150 +
 151.151 +    @Override
 151.152 +    public int hangingIndentSize() {
 151.153 +        return 4;
 151.154 +    }
 151.155 +
 151.156 +    // Challenge: Two inconsistently formatted
 151.157 +    // Idea: Given a list of offsets and indentation, produce a graph (or recurse) where I mark all
 151.158 +    // siblings the exact same level
 151.159 +
 151.160 +    // Algorithm:
 151.161 +    //   Find smallest indent: That's the top level
 151.162 +    //   Build a graph? Each indent line.
 151.163 +    //
 151.164 +    @Override
 151.165 +    public void reindent(final Context context) {
 151.166 +        Document document = context.document();
 151.167 +        int startOffset = context.startOffset();
 151.168 +        int endOffset = context.endOffset();
 151.169 +
 151.170 +        reindent(context, document, startOffset, endOffset);
 151.171 +    }
 151.172 +
 151.173 +    @SuppressWarnings("deprecation") // For doc.getFormatter()
 151.174 +    public void reindent(final Context context, Document document, int startOffset, int endOffset) {
 151.175 +        endOffset = Math.min(endOffset, document.getLength());
 151.176 +        startOffset = Math.min(startOffset, endOffset);
 151.177 +
 151.178 +        continuationIndentSize = indentSize = IndentUtils.indentLevelSize(document);
 151.179 +
 151.180 +
 151.181 +        final BaseDocument doc = (BaseDocument)document;
 151.182 +        try {
 151.183 +            // Plan: Go through the lines, one by one, and compute the indentation levels relative to each other,
 151.184 +            // then normalize them (except inside strings), then apply!!
 151.185 +            // Also track whether we are used for newline indentation and if so, do smart bracket stuff
 151.186 +
 151.187 +            // Current indentation for the given line. -1 means that it should be left alone (e.g.
 151.188 +            // we don't mess with multiline string literals.
 151.189 +            final List<Integer> offsets = new ArrayList<>();
 151.190 +
 151.191 +            // Current indentation for the given line. -1 means that it should be left alone (e.g.
 151.192 +            // we don't mess with multiline string literals. Other negative numbers are offsets
 151.193 +            // pointing at a particular left parenthesis that this line should be aligned with
 151.194 +            final List<Integer> indentation = new ArrayList<>();
 151.195 +            final List<Integer> lParenOffsets = new ArrayList<>();
 151.196 +
 151.197 +            try {
 151.198 +                doc.readLock(); // For token hierarchy usage
 151.199 +
 151.200 +                TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(doc, startOffset);
 151.201 +
 151.202 +                int currentOffset = Utilities.getRowStart(doc, startOffset);
 151.203 +                int balance = 0;
 151.204 +                while (currentOffset <= endOffset) {
 151.205 +                    if (!(Utilities.isRowEmpty(doc, currentOffset) || Utilities.isRowWhite(doc, currentOffset))) {
 151.206 +                        Token<? extends PythonTokenId> token = PythonLexerUtils.getToken(doc, currentOffset);
 151.207 +                        int indent = GsfUtilities.getLineIndent(doc, currentOffset);
 151.208 +                        if (token != null) {
 151.209 +                            if (token.id() == PythonTokenId.STRING_LITERAL || token.id() == PythonTokenId.STRING_END) {
 151.210 +                                indent = -1;
 151.211 +                            }
 151.212 +                        }
 151.213 +
 151.214 +                        if (indent != -1) {
 151.215 +                            if (balance <= 0) {
 151.216 +                                indentation.add(indent);
 151.217 +                                offsets.add(currentOffset);
 151.218 +                            } else {
 151.219 +                                assert balance <= lParenOffsets.size();
 151.220 +                                int parenOffset = lParenOffsets.get(lParenOffsets.size()-balance);
 151.221 +                                indentation.add(-parenOffset);
 151.222 +                                offsets.add(currentOffset);
 151.223 +                            }
 151.224 +                        }
 151.225 +                    }
 151.226 +
 151.227 +                    // TODO - look up the tokens to make sure we don't have a problem with literal nodes
 151.228 +
 151.229 +                    if (currentOffset > doc.getLength()) {
 151.230 +                        break;
 151.231 +                    }
 151.232 +
 151.233 +                    // Update the line balance
 151.234 +                    int begin = Utilities.getRowStart(doc, currentOffset);
 151.235 +                    int end = Utilities.getRowEnd(doc, currentOffset);
 151.236 +
 151.237 +                    ts.move(begin);
 151.238 +
 151.239 +                    if (ts.moveNext()) {
 151.240 +                        do {
 151.241 +                            Token<? extends PythonTokenId> token = ts.token();
 151.242 +                            TokenId id = token.id();
 151.243 +
 151.244 +                            if (id == PythonTokenId.LPAREN) {
 151.245 +                                balance++;
 151.246 +                                lParenOffsets.add(ts.offset());
 151.247 +                            } else if (id == PythonTokenId.RPAREN) {
 151.248 +                                balance--;
 151.249 +                                if (!lParenOffsets.isEmpty()) {
 151.250 +                                    lParenOffsets.remove(lParenOffsets.size()-1);
 151.251 +                                }
 151.252 +                            }
 151.253 +                        } while (ts.moveNext() && (ts.offset() <= end));
 151.254 +                    }
 151.255 +
 151.256 +                    currentOffset = Utilities.getRowEnd(doc, currentOffset) + 1;
 151.257 +                }
 151.258 +            } finally {
 151.259 +                doc.readUnlock();
 151.260 +            }
 151.261 +
 151.262 +            // Nothing to do
 151.263 +            if (offsets.size() == 0) {
 151.264 +                return;
 151.265 +            }
 151.266 +
 151.267 +            assert indentation.size() == offsets.size();
 151.268 +
 151.269 +            final Map<Integer, Integer> offsetToLevel = new HashMap<>();
 151.270 +            final Map<Integer,Integer> offsetToIndex = new HashMap<>();
 151.271 +            List<Integer> parentIndentations = new ArrayList<>();
 151.272 +            int currentParentIndent = -1;
 151.273 +            int currentLevel = -1;
 151.274 +
 151.275 +            int firstIndent = indentation.get(0);
 151.276 +            List<Integer> sorted = new ArrayList<>(indentation);
 151.277 +            Collections.sort(sorted);
 151.278 +            // Attempt to shift the computed indentation to fit the right indentation levels
 151.279 +            // that are currently in the file?
 151.280 +            int firstNonNeg = 0;
 151.281 +            for (; firstNonNeg < sorted.size(); firstNonNeg++) {
 151.282 +                if (sorted.get(firstNonNeg) >= 0) {
 151.283 +                    break;
 151.284 +                }
 151.285 +            }
 151.286 +            boolean shiftToCurrent = true;
 151.287 +            if (firstIndent > sorted.get(firstNonNeg)) {
 151.288 +                shiftToCurrent = false;
 151.289 +                // The start is not at the top level... e.g. we have something like
 151.290 +                //      foo
 151.291 +                //   else
 151.292 +                //      bar
 151.293 +                // (e.g. we are formatting a fragment of code which doesn't include
 151.294 +                // the top). Here we need to find the "true" top levels, so we
 151.295 +                // push levels on to the stack
 151.296 +                int prev = -1;
 151.297 +                for (int indent : sorted) {
 151.298 +                    if (prev == indent) {
 151.299 +                        continue;
 151.300 +                    }
 151.301 +                    prev = indent;
 151.302 +                    if (indent < firstIndent) {
 151.303 +                        parentIndentations.add(currentParentIndent);
 151.304 +                        currentParentIndent = indent;
 151.305 +                        currentLevel++;
 151.306 +                    } else {
 151.307 +                        break;
 151.308 +                    }
 151.309 +                }
 151.310 +            }
 151.311 +
 151.312 +
 151.313 +            // TODO: What if I start in the middle of an expression such that I outdent
 151.314 +            // more than I indent? I have to build up the index levels if necessary
 151.315 +            // Go count popping levels
 151.316 +
 151.317 +            for (int i = 0, n = offsets.size(); i < n; i++) {
 151.318 +                int offset = offsets.get(i);
 151.319 +                int indent = indentation.get(i);
 151.320 +                if (indent == -1) {
 151.321 +                    // Leave line alone
 151.322 +                    offsetToLevel.put(offset, -1);
 151.323 +                    continue;
 151.324 +                }
 151.325 +                offsetToIndex.put(offset, i);
 151.326 +
 151.327 +                if (indent < 0) {
 151.328 +                    // Want to keep everything the same as the prev, plus delta
 151.329 +                } else if (indent > currentParentIndent) {
 151.330 +                    // New level
 151.331 +                    currentLevel++;
 151.332 +                    parentIndentations.add(currentParentIndent);
 151.333 +                    currentParentIndent = indent;
 151.334 +                } else if (indent < currentParentIndent) {
 151.335 +                    while (currentParentIndent > indent) {
 151.336 +                        currentLevel--;
 151.337 +                        if (parentIndentations.size() > 0) {
 151.338 +                            currentParentIndent = parentIndentations.remove(parentIndentations.size() - 1);
 151.339 +                        } else {
 151.340 +                            currentParentIndent = indent;
 151.341 +                        }
 151.342 +                    }
 151.343 +                }
 151.344 +
 151.345 +                offsetToLevel.put(offset, currentLevel);
 151.346 +            }
 151.347 +
 151.348 +            // Compute relative shift
 151.349 +            int firstLineIndent = indentation.get(0);
 151.350 +            int firstLineLevel = offsetToLevel.get(offsets.get(0));
 151.351 +            int computedIndent = firstLineLevel * indentSize;
 151.352 +            final int relativeShift = shiftToCurrent ? computedIndent - firstLineIndent : 0;
 151.353 +
 151.354 +            doc.runAtomic(new Runnable() {
 151.355 +                @Override
 151.356 +                public void run() {
 151.357 +                    int[] computedIndents = new int[offsets.size()];
 151.358 +                    // Process backwards so I don't have to worry about updating offsets affected by
 151.359 +                    // indentation changes
 151.360 +                    for (int i = offsets.size() - 1; i >= 0; i--) {
 151.361 +                        int indent = indentation.get(i);
 151.362 +                        if (indent == -1) {
 151.363 +                            // Leave line alone
 151.364 +                            continue;
 151.365 +                        }
 151.366 +                        if (indent >= 0) {
 151.367 +                            int offset = offsets.get(i);
 151.368 +                            int level = offsetToLevel.get(offset);
 151.369 +                            int computedIndent = level * indentSize - relativeShift;
 151.370 +                            if (computedIndent < 0) {
 151.371 +                                computedIndent = 0;
 151.372 +                            }
 151.373 +                            computedIndents[i] =computedIndent;
 151.374 +                        } else {
 151.375 +                            computedIndents[i] = -1;
 151.376 +                        }
 151.377 +                    }
 151.378 +
 151.379 +                    for (int i = offsets.size() - 1; i >= 0; i--) {
 151.380 +                        int indent = indentation.get(i);
 151.381 +                        if (indent < -1) {
 151.382 +                            try {
 151.383 +                                // Negative offset pointing to a left parenthesis we should align with
 151.384 +                                int parenOffset = -indent;
 151.385 +                                int lineStart = Utilities.getRowStart(doc, parenOffset);
 151.386 +                                if (lineStart != -1) {
 151.387 +                                    int parenLineIndent = computedIndents[offsetToIndex.get(lineStart)];
 151.388 +                                    assert parenLineIndent >= 0;
 151.389 +                                    int textBegin = Utilities.getRowFirstNonWhite(doc, lineStart);
 151.390 +                                    assert textBegin != -1;
 151.391 +                                    // Indent to new indentation + text up to paren plus the paren itself
 151.392 +                                    int newIndent = parenLineIndent + (parenOffset-textBegin) + 1;
 151.393 +                                    computedIndents[i] = newIndent;
 151.394 +                                }
 151.395 +                            } catch (BadLocationException ble) {
 151.396 +                                Exceptions.printStackTrace(ble);
 151.397 +                            }
 151.398 +                        }
 151.399 +                    }
 151.400 +
 151.401 +                    // Process backwards so I don't have to worry about updating offsets affected by
 151.402 +                    // indentation changes
 151.403 +                    for (int i = offsets.size() - 1; i >= 0; i--) {
 151.404 +                        int indent = indentation.get(i);
 151.405 +                        if (indent == -1) {
 151.406 +                            // Leave line alone
 151.407 +                            continue;
 151.408 +                        }
 151.409 +                        int offset = offsets.get(i);
 151.410 +                        int computedIndent = computedIndents[i];
 151.411 +                        if (computedIndent < 0) {
 151.412 +                            computedIndent = 0;
 151.413 +                        }
 151.414 +
 151.415 +                        if (computedIndent != indent) {
 151.416 +                            try {
 151.417 +                                context.modifyIndent(offset, computedIndent);
 151.418 +                            } catch (BadLocationException ex) {
 151.419 +                                Exceptions.printStackTrace(ex);
 151.420 +                            }
 151.421 +                        }
 151.422 +                    }
 151.423 +                }
 151.424 +            });
 151.425 +        } catch (BadLocationException ble) {
 151.426 +            Exceptions.printStackTrace(ble);
 151.427 +        }
 151.428 +    }
 151.429 +
 151.430 +    private boolean isLinePrefix(BaseDocument doc, int offset) throws BadLocationException {
 151.431 +        return Utilities.getRowFirstNonWhite(doc, offset) == offset;
 151.432 +    }
 151.433 +
 151.434 +    private void cleanup(Document document, PythonParserResult info, int startOffset, int endOffset) {
 151.435 +        BaseDocument doc = (BaseDocument)document;
 151.436 +        final EditList edits = new EditList(doc);
 151.437 +        try {
 151.438 +            doc.readLock(); // For token hierarchy usage
 151.439 +
 151.440 +            TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(doc, startOffset);
 151.441 +            if (ts == null) {
 151.442 +                return;
 151.443 +            }
 151.444 +
 151.445 +            ts.move(startOffset);
 151.446 +
 151.447 +
 151.448 +
 151.449 +            // TODO:
 151.450 +            // Control whether I collapse spaces to a single space, or just ensure there is at least one
 151.451 +            // "None", "1", "At least 1", "Leave Alone"
 151.452 +
 151.453 +            // TODO: Insert and remove needed or unnecessary parentheses!
 151.454 +            // TODO: Alignment! Especially of trailing line comments on adjacent lines!
 151.455 +            // TODO: Collapse blank newlines!
 151.456 +            boolean addSpaceAroundOperators = true;
 151.457 +            boolean removeSpaceInsideParens = true; // also applies to braces and brackets
 151.458 +            boolean addSpaceAfterComma = true;
 151.459 +            //    boolean spaceArondParens = false;
 151.460 +            //    boolean spaceBeforeArgs = false; // before parentheses in a call
 151.461 +            boolean removeSpaceBeforeSep = true; // before comma, semicolon or colon
 151.462 +            //    boolean alignAssignments = false; // Only one space around assignments
 151.463 +            boolean removeSpaceInParamAssign = true; // Around assignment in parameter list, e.g.
 151.464 +            boolean collapseSpaces = true;
 151.465 +            //def complex(real, imag=0.0):
 151.466 +            //       return magic(r=real, i=imag)
 151.467 +            if (codeStyle != null) {
 151.468 +                addSpaceAroundOperators = codeStyle.addSpaceAroundOperators();
 151.469 +                removeSpaceInsideParens = codeStyle.removeSpaceInsideParens();
 151.470 +                addSpaceAfterComma = codeStyle.addSpaceAfterComma();
 151.471 +                removeSpaceBeforeSep = codeStyle.removeSpaceBeforeSep();
 151.472 +                removeSpaceInParamAssign = codeStyle.removeSpaceInParamAssign();
 151.473 +                collapseSpaces = codeStyle.collapseSpaces();
 151.474 +            }
 151.475 +
 151.476 +            // TODO - back up to the nearest function or class or beginning of the document to get the right
 151.477 +            // parenthesis balance.
 151.478 +            int parenBalance = 0;
 151.479 +
 151.480 +            Token<? extends PythonTokenId> prev = null;
 151.481 +            Token<? extends PythonTokenId> token = null;
 151.482 +            Token<? extends PythonTokenId> next = null;
 151.483 +            int tokenOffset = 0;
 151.484 +            int nextOffset = 0;
 151.485 +            int prevOffset = -1;
 151.486 +            if (ts.moveNext()) {
 151.487 +                token = ts.token();
 151.488 +                tokenOffset = ts.offset();
 151.489 +                if (ts.moveNext()) {
 151.490 +                    next = ts.token();
 151.491 +                    nextOffset = ts.offset();
 151.492 +                } else {
 151.493 +                    return;
 151.494 +                }
 151.495 +            }
 151.496 +            boolean prevRemoved = false;
 151.497 +            boolean tokenRemoved = false;
 151.498 +            boolean nextRemoved = false;
 151.499 +            while (token != null) {
 151.500 +                TokenId prevId = prev != null ? prev.id() : null;
 151.501 +                TokenId id = token.id();
 151.502 +                TokenId nextId = next != null ? next.id() : null;
 151.503 +
 151.504 +                if (id == PythonTokenId.LPAREN) {
 151.505 +                    parenBalance++;
 151.506 +                } else if (id == PythonTokenId.RPAREN) {
 151.507 +                    parenBalance--;
 151.508 +                }
 151.509 +
 151.510 +                if (removeSpaceInsideParens) {
 151.511 +                    if (id == PythonTokenId.LPAREN) {
 151.512 +                        if (nextId == PythonTokenId.WHITESPACE && !nextRemoved) {
 151.513 +                            edits.replace(nextOffset, next.length(), null, false, 0);
 151.514 +                            nextRemoved = true;
 151.515 +                        }
 151.516 +                    } else if (id == PythonTokenId.RPAREN) {
 151.517 +                        if (prevId == PythonTokenId.WHITESPACE && !prevRemoved && !isLinePrefix(doc, tokenOffset)) {
 151.518 +                            // I don't remove space in front of paren's at the beginning of the line; these might have
 151.519 +                            // been aligned with indented content above
 151.520 +                            edits.replace(prevOffset, prev.length(), null, false, 0);
 151.521 +                            prevRemoved = true;
 151.522 +                        }
 151.523 +                    } else if (id == PythonTokenId.LBRACKET) {
 151.524 +                        if (nextId == PythonTokenId.WHITESPACE && !nextRemoved) {
 151.525 +                            edits.replace(nextOffset, next.length(), null, false, 0);
 151.526 +                            nextRemoved = true;
 151.527 +                        }
 151.528 +                    } else if (id == PythonTokenId.RBRACKET) {
 151.529 +                        if (prevId == PythonTokenId.WHITESPACE && !prevRemoved && !isLinePrefix(doc, tokenOffset)) {
 151.530 +                            edits.replace(prevOffset, prev.length(), null, false, 0);
 151.531 +                            prevRemoved = true;
 151.532 +                        }
 151.533 +                    } else if (id == PythonTokenId.LBRACE) {
 151.534 +                        if (nextId == PythonTokenId.WHITESPACE && !nextRemoved) {
 151.535 +                            edits.replace(nextOffset, next.length(), null, false, 0);
 151.536 +                            nextRemoved = true;
 151.537 +                        }
 151.538 +                    } else if (id == PythonTokenId.RBRACE) {
 151.539 +                        if (prevId == PythonTokenId.WHITESPACE && !prevRemoved && !isLinePrefix(doc, tokenOffset)) {
 151.540 +                            edits.replace(prevOffset, prev.length(), null, false, 0);
 151.541 +                            prevRemoved = true;
 151.542 +                        }
 151.543 +                    }
 151.544 +                }
 151.545 +
 151.546 +                if (addSpaceAfterComma) {
 151.547 +                    if (id == PythonTokenId.COMMA) {
 151.548 +                        if (collapseSpaces && nextId == PythonTokenId.WHITESPACE && next.length() > 1) {
 151.549 +                            edits.replace(nextOffset, next.length() - 1, null, false, 1); // NOI18N
 151.550 +                        } else if (next == null ||
 151.551 +                                (nextId != PythonTokenId.WHITESPACE && nextId != PythonTokenId.NEWLINE)) {
 151.552 +                            edits.replace(nextOffset, 0, " ", false, 1); // NOI18N
 151.553 +                        }
 151.554 +                    }
 151.555 +                }
 151.556 +
 151.557 +                if (removeSpaceBeforeSep &&
 151.558 +                        (id == PythonTokenId.COMMA || id == PythonTokenId.COLON ||
 151.559 +                        (id == PythonTokenId.ANY_OPERATOR && TokenUtilities.equals(token.text(), ";"))) && // NOI18N
 151.560 +                        prevId == PythonTokenId.WHITESPACE && !prevRemoved && !isLinePrefix(doc, tokenOffset)) {
 151.561 +                    edits.replace(prevOffset, prev.length(), null, false, 2);
 151.562 +                    prevRemoved = true;
 151.563 +                }
 151.564 +
 151.565 +                if (addSpaceAroundOperators && id == PythonTokenId.ANY_OPERATOR) {
 151.566 +                    CharSequence seq = token.text();
 151.567 +
 151.568 +                    // These aren't binary, and ; isn't really an operator and has its own setting
 151.569 +                    if (!(TokenUtilities.equals(seq, "@") || // NOI18N
 151.570 +                            TokenUtilities.equals(seq, "`") || // NOI18N
 151.571 +                            TokenUtilities.equals(seq, ";"))) { // NOI18N
 151.572 +
 151.573 +                        boolean insertSpace = true;
 151.574 +                        if (removeSpaceInParamAssign && TokenUtilities.equals(seq, "=")) { // NOI18N
 151.575 +                            // Special handling: keyword arguments should typically NOT
 151.576 +                            // have space inserted
 151.577 +                            if (parenBalance > 0) {
 151.578 +                                insertSpace = false;
 151.579 +                                // Remove spaces around the =
 151.580 +                                if (prevId == PythonTokenId.WHITESPACE && !prevRemoved) {
 151.581 +                                    edits.replace(prevOffset, prev.length(), null, false, 5); // NOI18N
 151.582 +                                    prevRemoved = true;
 151.583 +                                }
 151.584 +                                if (nextId == PythonTokenId.WHITESPACE && !nextRemoved) {
 151.585 +                                    edits.replace(nextOffset, next.length(), null, false, 6); // NOI18N
 151.586 +                                    nextRemoved = true;
 151.587 +                                }
 151.588 +                            }
 151.589 +                        }
 151.590 +
 151.591 +                        if (insertSpace && TokenUtilities.equals(seq, "-")/* && (nextId == PythonTokenId.FLOAT_LITERAL || nextId == PythonTokenId.INT_LITERAL)*/) {
 151.592 +                            // Leave -'s alone for now. The code is a little unclear on the difference between
 151.593 +                            //  x-1 and =-1 etc. For numbers (floating and integer) the minus isn't part of the lexical token for the number;
 151.594 +                            // it's a separate operator. However, it's tricky to tell this apart from the binary subtraction, since it depends
 151.595 +                            // on what came before. For now play it safe an leave these alone.
 151.596 +                            // TODO - implement this properly.
 151.597 +                            insertSpace = false;
 151.598 +                        }
 151.599 +
 151.600 +                        if (insertSpace && TokenUtilities.equals(seq, "*")) { // NOI18N
 151.601 +                            // "*" in (*foo) doesn't mean multiplication; it's not a binary operator here,
 151.602 +                            // it's many args.
 151.603 +                            if (prevId == PythonTokenId.COMMA || prevId == PythonTokenId.LPAREN) {
 151.604 +                                insertSpace = false;
 151.605 +                            }
 151.606 +                        }
 151.607 +
 151.608 +                        if (insertSpace) {
 151.609 +                            // Ensure that we have space on both sides
 151.610 +                            if (collapseSpaces && prevId == PythonTokenId.WHITESPACE && next.length() > 1 &&
 151.611 +                                    !isLinePrefix(doc, tokenOffset)) {
 151.612 +                                edits.replace(prevOffset, prev.length() - 1, null, false, 1); // NOI18N
 151.613 +                            } else if (prevId != PythonTokenId.WHITESPACE) {
 151.614 +                                edits.replace(tokenOffset, 0, " ", false, 3); // NOI18N
 151.615 +                            }
 151.616 +
 151.617 +                            if (collapseSpaces && nextId == PythonTokenId.WHITESPACE && next.length() > 1) {
 151.618 +                                edits.replace(nextOffset, next.length() - 1, null, false, 1); // NOI18N
 151.619 +                            } else if (nextId != PythonTokenId.WHITESPACE && nextId != PythonTokenId.NEWLINE) {
 151.620 +                                edits.replace(nextOffset, 0, " ", false, 4); // NOI18N
 151.621 +                            }
 151.622 +                        }
 151.623 +                    }
 151.624 +                }
 151.625 +
 151.626 +                if (tokenOffset + token.length() >= endOffset) {
 151.627 +                    break;
 151.628 +                }
 151.629 +
 151.630 +                prevRemoved = tokenRemoved;
 151.631 +                tokenRemoved = nextRemoved;
 151.632 +                nextRemoved = false;
 151.633 +
 151.634 +                prev = token;
 151.635 +                token = next;
 151.636 +                prevOffset = tokenOffset;
 151.637 +                tokenOffset = nextOffset;
 151.638 +                if (ts.moveNext()) {
 151.639 +                    next = ts.token();
 151.640 +                    nextOffset = ts.offset();
 151.641 +                } else {
 151.642 +                    next = null;
 151.643 +                }
 151.644 +            }
 151.645 +        } catch (BadLocationException ble) {
 151.646 +            Exceptions.printStackTrace(ble);
 151.647 +        } finally {
 151.648 +            doc.readUnlock();
 151.649 +        }
 151.650 +
 151.651 +        doc.runAtomic(new Runnable() {
 151.652 +            @Override
 151.653 +            public void run() {
 151.654 +                edits.apply();
 151.655 +            }
 151.656 +        });
 151.657 +    }
 151.658 +}
   152.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   152.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonIndex.java	Sun Sep 13 11:47:42 2015 +0200
   152.3 @@ -0,0 +1,1470 @@
   152.4 +/*
   152.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   152.6 + *
   152.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   152.8 + *
   152.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  152.10 + * Other names may be trademarks of their respective owners.
  152.11 + *
  152.12 + * The contents of this file are subject to the terms of either the GNU
  152.13 + * General Public License Version 2 only ("GPL") or the Common
  152.14 + * Development and Distribution License("CDDL") (collectively, the
  152.15 + * "License"). You may not use this file except in compliance with the
  152.16 + * License. You can obtain a copy of the License at
  152.17 + * http://www.netbeans.org/cddl-gplv2.html
  152.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  152.19 + * specific language governing permissions and limitations under the
  152.20 + * License.  When distributing the software, include this License Header
  152.21 + * Notice in each file and include the License file at
  152.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  152.23 + * particular file as subject to the "Classpath" exception as provided
  152.24 + * by Oracle in the GPL Version 2 section of the License file that
  152.25 + * accompanied this code. If applicable, add the following below the
  152.26 + * License Header, with the fields enclosed by brackets [] replaced by
  152.27 + * your own identifying information:
  152.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  152.29 + *
  152.30 + * Contributor(s):
  152.31 + *
  152.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  152.33 + */
  152.34 +package org.netbeans.modules.python.source;
  152.35 +
  152.36 +import java.io.File;
  152.37 +import java.io.IOException;
  152.38 +import java.net.MalformedURLException;
  152.39 +import java.net.URL;
  152.40 +import java.util.ArrayList;
  152.41 +import java.util.Arrays;
  152.42 +import java.util.Collection;
  152.43 +import java.util.Collections;
  152.44 +import java.util.EnumSet;
  152.45 +import java.util.HashMap;
  152.46 +import java.util.HashSet;
  152.47 +import java.util.Iterator;
  152.48 +import java.util.List;
  152.49 +import java.util.Map;
  152.50 +import java.util.Set;
  152.51 +import java.util.WeakHashMap;
  152.52 +import java.util.logging.Level;
  152.53 +import java.util.logging.Logger;
  152.54 +import org.netbeans.api.project.Project;
  152.55 +import org.netbeans.modules.csl.api.ElementKind;
  152.56 +import org.netbeans.modules.parsing.spi.indexing.PathRecognizer;
  152.57 +import org.netbeans.modules.parsing.spi.indexing.support.IndexResult;
  152.58 +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
  152.59 +import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.CAMEL_CASE;
  152.60 +import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.CASE_INSENSITIVE_PREFIX;
  152.61 +import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.CASE_INSENSITIVE_REGEXP;
  152.62 +import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.PREFIX;
  152.63 +import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.REGEXP;
  152.64 +import org.netbeans.modules.python.source.elements.IndexedElement;
  152.65 +import org.netbeans.modules.python.api.PythonPlatform;
  152.66 +import org.netbeans.modules.python.api.PythonPlatformManager;
  152.67 +import org.netbeans.modules.python.source.impl.QuerySupportFactory;
  152.68 +import org.netbeans.modules.python.source.elements.IndexedPackage;
  152.69 +import org.openide.filesystems.FileObject;
  152.70 +import org.openide.filesystems.FileStateInvalidException;
  152.71 +import org.openide.filesystems.URLMapper;
  152.72 +import org.openide.modules.InstalledFileLocator;
  152.73 +import org.openide.util.Exceptions;
  152.74 +import org.openide.util.Lookup;
  152.75 +import org.python.antlr.ast.Import;
  152.76 +import org.python.antlr.ast.ImportFrom;
  152.77 +import org.python.antlr.ast.alias;
  152.78 +
  152.79 +/**
  152.80 + *
  152.81 + * @author alley
  152.82 + * @author Tor Norbye
  152.83 + */
  152.84 +public class PythonIndex {
  152.85 +//    public static final Set<SearchScope> ALL_SCOPE = EnumSet.allOf(SearchScope.class);
  152.86 +//    public static final Set<SearchScope> SOURCE_SCOPE = EnumSet.of(SearchScope.SOURCE);
  152.87 +    static final String CLUSTER_URL = "cluster:"; // NOI18N
  152.88 +    static final String PYTHONHOME_URL = "python:"; // NOI18N
  152.89 +    private static final String STUB_MISSING = "stub_missing"; // NOI18N
  152.90 +
  152.91 +    // The "functions" module is always imported by the interpreter, and ditto
  152.92 +    // for exceptions, constants, etc.
  152.93 +    public static Set<String> BUILTIN_MODULES = new HashSet<>();
  152.94 +
  152.95 +
  152.96 +    private static final Logger LOG = Logger.getLogger(PythonIndex.class.getName());
  152.97 +    public static final String OBJECT = "object"; // NOI18N
  152.98 +    static Map<String, Set<String>> wildcardImports = new HashMap<>();
  152.99 +    static Set<String> systemModules;
 152.100 +    // TODO - make weak?
 152.101 +    static Set<String> availableClasses;
 152.102 +    private static String clusterUrl = null;
 152.103 +    static {
 152.104 +        //BUILTIN_MODULES.add("objects"); // NOI18N -- just links to the others
 152.105 +        BUILTIN_MODULES.add("stdtypes"); // NOI18N
 152.106 +        //BUILTIN_MODULES.add("types"); // NOI18N
 152.107 +        BUILTIN_MODULES.add("exceptions"); // NOI18N
 152.108 +        BUILTIN_MODULES.add("functions"); // NOI18N
 152.109 +        BUILTIN_MODULES.add("constants"); // NOI18N
 152.110 +    }
 152.111 +
 152.112 +    public static PythonIndex get(Collection<FileObject> roots) {
 152.113 +        // XXX no cache - is it needed?
 152.114 +        LOG.log(Level.FINE, "PythonIndex for roots: {0}", roots); //NOI18N
 152.115 +        return new PythonIndex(QuerySupportFactory.getQuerySupport(roots), false);
 152.116 +    }
 152.117 +    
 152.118 +    public static PythonIndex get(Project project) {
 152.119 +        Set<String> sourceIds = new HashSet<>();
 152.120 +        Set<String> libraryIds = new HashSet<>();
 152.121 +        Collection<? extends PathRecognizer> lookupAll = Lookup.getDefault().lookupAll(PathRecognizer.class);
 152.122 +        for (PathRecognizer pathRecognizer : lookupAll) {
 152.123 +            Set<String> source = pathRecognizer.getSourcePathIds();
 152.124 +            if (source != null) {
 152.125 +                sourceIds.addAll(source);
 152.126 +            }
 152.127 +            Set<String> library = pathRecognizer.getLibraryPathIds();
 152.128 +            if (library != null) {
 152.129 +                libraryIds.addAll(library);
 152.130 +            }
 152.131 +        }
 152.132 +
 152.133 +        final Collection<FileObject> findRoots = QuerySupport.findRoots(project,
 152.134 +                sourceIds,
 152.135 +                libraryIds,
 152.136 +                Collections.<String>emptySet());
 152.137 +        return PythonIndex.get(findRoots);
 152.138 +    }
 152.139 +    
 152.140 +    private static final WeakHashMap<FileObject, PythonIndex> INDEX_CACHE = new WeakHashMap<>();
 152.141 +    public static PythonIndex get(FileObject fo) {
 152.142 +        PythonIndex index = INDEX_CACHE.get(fo);
 152.143 +        if (index == null) {
 152.144 +            LOG.log(Level.FINE, "Creating PythonIndex for FileObject: {0}", fo); //NOI18N
 152.145 +            index = new PythonIndex(QuerySupportFactory.getQuerySupport(fo), true);
 152.146 +            INDEX_CACHE.put(fo, index);
 152.147 +        }
 152.148 +        return index;
 152.149 +    }
 152.150 +
 152.151 +    public static boolean isBuiltinModule(String module) {
 152.152 +        return BUILTIN_MODULES.contains(module) || STUB_MISSING.equals(module);
 152.153 +    }
 152.154 +
 152.155 +    // For testing only
 152.156 +    public static void setClusterUrl(String url) {
 152.157 +        clusterUrl = url;
 152.158 +    }
 152.159 +
 152.160 +    static String getPreindexUrl(String url) {
 152.161 +        // TODO - look up the correct platform to use!
 152.162 +        final PythonPlatformManager manager = PythonPlatformManager.getInstance();
 152.163 +        final String platformName = manager.getDefaultPlatform();
 152.164 +        PythonPlatform platform = manager.getPlatform(platformName);
 152.165 +        if (platform != null) {
 152.166 +            String s = platform.getHomeUrl();
 152.167 +            if (s != null) {
 152.168 +                if (url.startsWith(s)) {
 152.169 +                    url = PYTHONHOME_URL + url.substring(s.length());
 152.170 +                    return url;
 152.171 +                }
 152.172 +            }
 152.173 +        }
 152.174 +        
 152.175 +        String s = getClusterUrl();
 152.176 +        
 152.177 +        if (url.startsWith(s)) {
 152.178 +            return CLUSTER_URL + url.substring(s.length());
 152.179 +        }
 152.180 +        
 152.181 +        if (url.startsWith("jar:file:")) { // NOI18N
 152.182 +            String sub = url.substring(4);
 152.183 +            if (sub.startsWith(s)) {
 152.184 +                return CLUSTER_URL + sub.substring(s.length());
 152.185 +            }
 152.186 +        }
 152.187 +        
 152.188 +        return url;
 152.189 +    }
 152.190 +
 152.191 +/** Get the FileObject corresponding to a URL returned from the index */
 152.192 +    public static FileObject getFileObject(String url) {
 152.193 +        return getFileObject(url, null);
 152.194 +    }
 152.195 +
 152.196 +    public static FileObject getFileObject(String url, FileObject context) {
 152.197 +        try {
 152.198 +            if (url.startsWith(PYTHONHOME_URL)) {
 152.199 +                Iterator<String> it = null;
 152.200 +                
 152.201 +                // TODO - look up the right platform for the given project
 152.202 +                //if (context != null) {
 152.203 +                //    Project project = FileOwnerQuery.getOwner(context);
 152.204 +                //    if (project != null) {
 152.205 +                //        PythonPlatform platform = PythonPlatform.platformFor(project);
 152.206 +                //        if (platform != null) {
 152.207 +                //            it = Collections.singleton(platform).iterator();
 152.208 +                //        }
 152.209 +                //    }
 152.210 +                //}
 152.211 +                
 152.212 +                PythonPlatformManager manager = PythonPlatformManager.getInstance();
 152.213 +                if (it == null) {
 152.214 +                    it = manager.getPlatformList().iterator();
 152.215 +                }
 152.216 +                while (it.hasNext()) {
 152.217 +                    String name = it.next();
 152.218 +                    PythonPlatform platform = manager.getPlatform(name);
 152.219 +                    if (platform != null) {
 152.220 +                        String u = platform.getHomeUrl();
 152.221 +                        if (u != null) {
 152.222 +                            try {
 152.223 +                                u = u + url.substring(PYTHONHOME_URL.length());
 152.224 +                                FileObject fo = URLMapper.findFileObject(new URL(u));
 152.225 +                                if (fo != null) {
 152.226 +                                    return fo;
 152.227 +                                }
 152.228 +                            } catch (MalformedURLException mue) {
 152.229 +                                Exceptions.printStackTrace(mue);
 152.230 +                            }
 152.231 +                        }
 152.232 +                    }
 152.233 +                }
 152.234 +                
 152.235 +                return null;
 152.236 +            } else if (url.startsWith(CLUSTER_URL)) {
 152.237 +                url = getClusterUrl() + url.substring(CLUSTER_URL.length()); // NOI18N
 152.238 +                if (url.contains(".egg!/")) { // NOI18N
 152.239 +                    url = "jar:" + url; // NOI18N
 152.240 +                }
 152.241 +            }
 152.242 +            
 152.243 +            return URLMapper.findFileObject(new URL(url));
 152.244 +        } catch (MalformedURLException ex) {
 152.245 +            Exceptions.printStackTrace(ex);
 152.246 +        }
 152.247 +        
 152.248 +        return null;
 152.249 +    }
 152.250 +    
 152.251 +    static String getClusterUrl() {
 152.252 +        if (clusterUrl == null) {
 152.253 +            File f =
 152.254 +                    InstalledFileLocator.getDefault().locate("modules/org-netbeans-modules-python-editor.jar", null, false); // NOI18N
 152.255 +            
 152.256 +            if (f == null) {
 152.257 +                throw new RuntimeException("Can't find cluster");
 152.258 +            }
 152.259 +            
 152.260 +            f = new File(f.getParentFile().getParentFile().getAbsolutePath());
 152.261 +            
 152.262 +            try {
 152.263 +                f = f.getCanonicalFile();
 152.264 +                clusterUrl = f.toURI().toURL().toExternalForm();
 152.265 +            } catch (IOException ioe) {
 152.266 +                Exceptions.printStackTrace(ioe);
 152.267 +            }
 152.268 +        }
 152.269 +
 152.270 +        return clusterUrl;
 152.271 +    }
 152.272 +
 152.273 +    private final QuerySupport index;
 152.274 +    private final boolean updateCache;
 152.275 +    
 152.276 +    /** Creates a new instance of PythonIndex */
 152.277 +    private PythonIndex(QuerySupport index, boolean updateCache) {
 152.278 +        this.index = index;
 152.279 +        this.updateCache = updateCache;
 152.280 +    }
 152.281 +    
 152.282 +    private boolean search(String fieldName, String fieldValue, QuerySupport.Kind kind, Set<? super IndexResult> result, final String... fieldsToLoad) {
 152.283 +        try {
 152.284 +            result.addAll(index.query(fieldName, fieldValue, kind, fieldsToLoad));
 152.285 +            return true;
 152.286 +        } catch (IOException ioe) {
 152.287 +            Exceptions.printStackTrace(ioe);
 152.288 +
 152.289 +            return false;
 152.290 +        } catch (UnsupportedOperationException iuoe) {
 152.291 +            return false;
 152.292 +        }
 152.293 +    }
 152.294 +
 152.295 +    public Set<IndexedElement> getModules(String name, final QuerySupport.Kind kind) {
 152.296 +        final Set<IndexResult> result = new HashSet<>();
 152.297 +
 152.298 +        //        if (!isValid()) {
 152.299 +        //            LOGGER.fine(String.format("LuceneIndex[%s] is invalid!\n", this.toString()));
 152.300 +        //            return;
 152.301 +        //        }
 152.302 +
 152.303 +        // TODO - handle case insensitive searches etc?
 152.304 +        String field = PythonIndexer.FIELD_MODULE_NAME;
 152.305 +
 152.306 +        search(field, name, kind, result, PythonIndexer.FIELD_MODULE_ATTR_NAME, PythonIndexer.FIELD_MODULE_NAME);
 152.307 +
 152.308 +        final Set<IndexedElement> modules = new HashSet<>();
 152.309 +
 152.310 +        for (IndexResult map : result) {
 152.311 +            URL url = map.getUrl();
 152.312 +            if (url == null) {
 152.313 +                continue;
 152.314 +            }
 152.315 +            String path = url.toExternalForm();
 152.316 +            String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
 152.317 +            if (STUB_MISSING.equals(module)) {
 152.318 +                continue;
 152.319 +            }
 152.320 +
 152.321 +            IndexedElement element = new IndexedElement(module, ElementKind.MODULE, path, null, null, null);
 152.322 +
 152.323 +            String attrs = map.getValue(PythonIndexer.FIELD_MODULE_ATTR_NAME);
 152.324 +            if (attrs != null && attrs.indexOf('D') != -1) {
 152.325 +                element.setFlags(IndexedElement.DEPRECATED);
 152.326 +            }
 152.327 +
 152.328 +            String rhs = path.substring(path.lastIndexOf('/') + 1);
 152.329 +            element.setRhs(rhs);
 152.330 +            modules.add(element);
 152.331 +        }
 152.332 +
 152.333 +        return modules;
 152.334 +    }
 152.335 +
 152.336 +    public Set<IndexedPackage> getPackages(String name, final QuerySupport.Kind kind) {
 152.337 +        final Set<IndexResult> result = new HashSet<>();
 152.338 +
 152.339 +        String field = PythonIndexer.FIELD_MODULE_NAME;
 152.340 +        search(field, name, kind, result, PythonIndexer.FIELD_MODULE_NAME);
 152.341 +
 152.342 +        final Set<IndexedPackage> packages = new HashSet<>();
 152.343 +
 152.344 +        for (IndexResult map : result) {
 152.345 +            String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
 152.346 +
 152.347 +            String pkgName = null;
 152.348 +            String pkg = null;
 152.349 +
 152.350 +            int nextNextDot = -1;
 152.351 +            int lastDot = module.lastIndexOf('.');
 152.352 +            int nameLength = name.length();
 152.353 +            if (nameLength < lastDot) {
 152.354 +                int nextDot = module.indexOf('.', nameLength);
 152.355 +                if (nextDot != -1) {
 152.356 +                    pkg = module.substring(0, nextDot);
 152.357 +                    nextNextDot = module.indexOf('.', nextDot + 1);
 152.358 +                    int start = module.lastIndexOf('.', name.length());
 152.359 +                    if (start == -1) {
 152.360 +                        start = 0;
 152.361 +                    } else {
 152.362 +                        start++;
 152.363 +                    }
 152.364 +                    pkgName = module.substring(start, nextDot);
 152.365 +                }
 152.366 +            } else if (lastDot != -1) {
 152.367 +                pkgName = module.substring(lastDot + 1);
 152.368 +                pkg = module;
 152.369 +            }
 152.370 +
 152.371 +            if (pkgName != null) {
 152.372 +                String url = map.getUrl().toExternalForm();
 152.373 +                IndexedPackage element = new IndexedPackage(pkgName, pkg, url, nextNextDot != -1);
 152.374 +                element.setRhs("");
 152.375 +                packages.add(element);
 152.376 +            }
 152.377 +        }
 152.378 +
 152.379 +        return packages;
 152.380 +    }
 152.381 +    
 152.382 +    public Set<IndexedElement> getClasses(String name, final QuerySupport.Kind kind, PythonParserResult context, boolean includeDuplicates) {
 152.383 +        final Set<IndexResult> result = new HashSet<>();
 152.384 +
 152.385 +        //        if (!isValid()) {
 152.386 +        //            LOGGER.fine(String.format("LuceneIndex[%s] is invalid!\n", this.toString()));
 152.387 +        //            return;
 152.388 +        //        }
 152.389 +        String field;
 152.390 +
 152.391 +        switch (kind) {
 152.392 +            case EXACT:
 152.393 +            case PREFIX:
 152.394 +            case CAMEL_CASE:
 152.395 +            case REGEXP:
 152.396 +                field = PythonIndexer.FIELD_CLASS_NAME;
 152.397 +                
 152.398 +                break;
 152.399 +                
 152.400 +            case CASE_INSENSITIVE_PREFIX:
 152.401 +            case CASE_INSENSITIVE_REGEXP:
 152.402 +            case CASE_INSENSITIVE_CAMEL_CASE:
 152.403 +                field = PythonIndexer.FIELD_CASE_INSENSITIVE_CLASS_NAME;
 152.404 +                
 152.405 +                break;
 152.406 +                
 152.407 +            default:
 152.408 +                throw new UnsupportedOperationException(kind.toString());
 152.409 +        }
 152.410 +
 152.411 +        search(field, name, kind, result, PythonIndexer.FIELD_IN, PythonIndexer.FIELD_CLASS_ATTR_NAME, PythonIndexer.FIELD_CLASS_NAME);
 152.412 +
 152.413 +        Set<String> uniqueClasses = includeDuplicates ? null : new HashSet<String>();
 152.414 +
 152.415 +        final Set<IndexedElement> classes = new HashSet<>();
 152.416 +
 152.417 +        for (IndexResult map : result) {
 152.418 +            String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
 152.419 +            if (clz == null) {
 152.420 +                // A module without classes
 152.421 +                continue;
 152.422 +            }
 152.423 +            String url = map.getUrl().toExternalForm();
 152.424 +            String module = map.getValue(PythonIndexer.FIELD_IN);
 152.425 +            boolean isBuiltin = isBuiltinModule(module);
 152.426 +
 152.427 +            String fqn = clz; // No further namespaces in Python, right?
 152.428 +            if (!includeDuplicates) {
 152.429 +                if (!uniqueClasses.contains(fqn)) { // use a map to point right to the class
 152.430 +                    uniqueClasses.add(fqn);
 152.431 +                    IndexedElement element = new IndexedElement(clz, ElementKind.CLASS, url, module, null, null);
 152.432 +                    if (isBuiltin) {
 152.433 +                        element.setRhs("<i>builtin</i>");
 152.434 +                    }
 152.435 +                    String attrs = map.getValue(PythonIndexer.FIELD_CLASS_ATTR_NAME);
 152.436 +                    if (attrs != null) {
 152.437 +                        int flags = IndexedElement.decode(attrs, 0, 0);
 152.438 +                        element.setFlags(flags);
 152.439 +                    }
 152.440 +                    element.setInherited(true);
 152.441 +
 152.442 +                    classes.add(element);
 152.443 +                } // else: Possibly pick the best version... based on which items have documentation attributes etc.
 152.444 +            } else {
 152.445 +                IndexedElement element = new IndexedElement(clz, ElementKind.CLASS, url, module, null, null);
 152.446 +                classes.add(element);
 152.447 +            }
 152.448 +        }
 152.449 +
 152.450 +        return classes;
 152.451 +    }
 152.452 +
 152.453 +//    /** Return the most distant method in the hierarchy that is overriding the given method, or null
 152.454 +//     * @todo Make this method actually compute most distant ancestor
 152.455 +//     * @todo Use arglist arity comparison to reject methods that are not overrides...
 152.456 +//     */
 152.457 +//    public IndexedMethod getOverridingMethod(String className, String methodName) {
 152.458 +//        Set<IndexedElement> methods = getInheritedElements(className, methodName, QuerySupport.Kind.EXACT);
 152.459 +//
 152.460 +//        // TODO - this is only returning ONE match, not the most distant one. I really need to
 152.461 +//        // produce a PythonIndex method for this which can walk in there and do a decent job!
 152.462 +//
 152.463 +//        for (IndexedElement method : methods) {
 152.464 +//            if (method.getKind() == ElementKind.METHOD || method.getKind() == ElementKind.CONSTRUCTOR) {
 152.465 +//                // getInheritedMethods may return methods ON fqn itself
 152.466 +//                if (!method.getIn().equals(className)) {
 152.467 +//                    return (IndexedMethod)method;
 152.468 +//                }
 152.469 +//            }
 152.470 +//        }
 152.471 +//
 152.472 +//        return null;
 152.473 +//    }
 152.474 +    /** Get the super implementation of the given method */
 152.475 +    public Set<IndexedElement> getOverridingMethods(String className, String function) {
 152.476 +        Set<IndexedElement> methods = getInheritedElements(className, function, QuerySupport.Kind.EXACT, true);
 152.477 +
 152.478 +        // TODO - remove all methods that are in the same file
 152.479 +        if (methods.size() > 0) {
 152.480 +            Set<IndexedElement> result = new HashSet<>(methods.size());
 152.481 +            for (IndexedElement element : methods) {
 152.482 +                if (!className.equals(element.getClz())) {
 152.483 +                    result.add(element);
 152.484 +                }
 152.485 +            }
 152.486 +            methods = result;
 152.487 +        }
 152.488 +
 152.489 +        return methods;
 152.490 +//        // TODO - this is only returning ONE match, not the most distant one. I really need to
 152.491 +//        // produce a PythonIndex method for this which can walk in there and do a decent job!
 152.492 +//
 152.493 +//        for (IndexedElement method : methods) {
 152.494 +//            if (method.getKind() == ElementKind.METHOD || method.getKind() == ElementKind.CONSTRUCTOR) {
 152.495 +//                // getInheritedMethods may return methods ON fqn itself
 152.496 +//                if (!method.getIn().equals(className)) {
 152.497 +//                    return (IndexedMethod)method;
 152.498 +//                }
 152.499 +//            }
 152.500 +//        }
 152.501 +//
 152.502 +//        return null;
 152.503 +    }
 152.504 +
 152.505 +    /** Get the super class of the given class */
 152.506 +    public Set<IndexedElement> getSuperClasses(String className) {
 152.507 +        final Set<IndexResult> result = new HashSet<>();
 152.508 +
 152.509 +        search(PythonIndexer.FIELD_CLASS_NAME, className, QuerySupport.Kind.EXACT, result, PythonIndexer.FIELD_EXTENDS_NAME, PythonIndexer.FIELD_CLASS_NAME);
 152.510 +
 152.511 +        Set<String> classNames = new HashSet<>();
 152.512 +        for (IndexResult map : result) {
 152.513 +            String[] extendsClasses = map.getValues(PythonIndexer.FIELD_EXTENDS_NAME);
 152.514 +            if (extendsClasses != null && extendsClasses.length > 0) {
 152.515 +                for (String clzName : extendsClasses) {
 152.516 +                    classNames.add(clzName);
 152.517 +                }
 152.518 +            }
 152.519 +        }
 152.520 +
 152.521 +        String[] terms = { PythonIndexer.FIELD_IN, PythonIndexer.FIELD_CLASS_NAME };
 152.522 +
 152.523 +        Set<IndexedElement> superClasses = new HashSet<>();
 152.524 +
 152.525 +        for (String superClz : classNames) {
 152.526 +            result.clear();
 152.527 +            search(PythonIndexer.FIELD_CLASS_NAME, superClz, QuerySupport.Kind.EXACT, result, terms);
 152.528 +            for (IndexResult map : result) {
 152.529 +                assert superClz.equals(map.getValue(PythonIndexer.FIELD_CLASS_NAME));
 152.530 +                String url = map.getUrl().toExternalForm();
 152.531 +                String module = map.getValue(PythonIndexer.FIELD_IN);
 152.532 +                IndexedElement clz = new IndexedElement(superClz, ElementKind.CLASS, url, module, null, null);
 152.533 +                superClasses.add(clz);
 152.534 +            }
 152.535 +        }
 152.536 +
 152.537 +        return superClasses;
 152.538 +    }
 152.539 +
 152.540 +    /**
 152.541 +     * Get the set of inherited (through super classes and mixins) for the given fully qualified class name.
 152.542 +     * @param classFqn FQN: module1::module2::moduleN::class
 152.543 +     * @param prefix If kind is QuerySupport.Kind.PREFIX/CASE_INSENSITIVE_PREFIX, a prefix to filter methods by. Else,
 152.544 +     *    if kind is QuerySupport.Kind.EXACT filter methods by the exact name.
 152.545 +     * @param kind Whether the prefix field should be taken as a prefix or a whole name
 152.546 +     */
 152.547 +    public Set<IndexedElement> getInheritedElements(String classFqn, String prefix, QuerySupport.Kind kind) {
 152.548 +        return getInheritedElements(classFqn, prefix, kind, false);
 152.549 +    }
 152.550 +
 152.551 +    public Set<IndexedElement> getInheritedElements(String classFqn, String prefix, QuerySupport.Kind kind, boolean includeOverrides) {
 152.552 +        boolean haveRedirected = false;
 152.553 +
 152.554 +        if (classFqn == null) {
 152.555 +            classFqn = OBJECT;
 152.556 +            haveRedirected = true;
 152.557 +        }
 152.558 +
 152.559 +        //String field = PythonIndexer.FIELD_FQN_NAME;
 152.560 +        Set<IndexedElement> elements = new HashSet<>();
 152.561 +        Set<String> scannedClasses = new HashSet<>();
 152.562 +        Set<String> seenSignatures = new HashSet<>();
 152.563 +
 152.564 +        if (prefix == null) {
 152.565 +            prefix = "";
 152.566 +        }
 152.567 +
 152.568 +//        String searchUrl = null;
 152.569 +//        if (context != null) {
 152.570 +//            try {
 152.571 +//                searchUrl = context.getFile().getFileObject().getURL().toExternalForm();
 152.572 +//            } catch (FileStateInvalidException ex) {
 152.573 +//                Exceptions.printStackTrace(ex);
 152.574 +//            }
 152.575 +//        }
 152.576 +
 152.577 +        addMethodsFromClass(prefix, kind, classFqn, elements, seenSignatures, scannedClasses,
 152.578 +                haveRedirected, false, includeOverrides, 0);
 152.579 +
 152.580 +        return elements;
 152.581 +    }
 152.582 +
 152.583 +    /** Return whether the specific class referenced (classFqn) was found or not. This is
 152.584 +     * not the same as returning whether any classes were added since it may add
 152.585 +     * additional methods from parents (Object/Class).
 152.586 +     */
 152.587 +    private boolean addMethodsFromClass(String prefix, QuerySupport.Kind kind, String classFqn, Set<IndexedElement> elements, Set<String> seenSignatures, Set<String> scannedClasses, boolean haveRedirected, boolean inheriting, boolean includeOverrides, int depth) {
 152.588 +        // Prevent problems with circular includes or redundant includes
 152.589 +        if (scannedClasses.contains(classFqn)) {
 152.590 +            return false;
 152.591 +        }
 152.592 +
 152.593 +        scannedClasses.add(classFqn);
 152.594 +
 152.595 +        String searchField = PythonIndexer.FIELD_CLASS_NAME;
 152.596 +
 152.597 +        Set<IndexResult> result = new HashSet<>();
 152.598 +
 152.599 +        String[] terms = {PythonIndexer.FIELD_IN,
 152.600 +                          PythonIndexer.FIELD_EXTENDS_NAME,
 152.601 +                          PythonIndexer.FIELD_MEMBER,
 152.602 +                          PythonIndexer.FIELD_CLASS_NAME};
 152.603 +        
 152.604 +        
 152.605 +        search(searchField, classFqn, QuerySupport.Kind.EXACT, result, terms);
 152.606 +
 152.607 +        boolean foundIt = result.size() > 0;
 152.608 +
 152.609 +        // If this is a bogus class entry (no search rsults) don't continue
 152.610 +        if (!foundIt) {
 152.611 +            return foundIt;
 152.612 +        }
 152.613 +
 152.614 +        List<String> extendsClasses = null;
 152.615 +
 152.616 +        String classIn = null;
 152.617 +        int fqnIndex = classFqn.lastIndexOf("::"); // NOI18N
 152.618 +
 152.619 +        if (fqnIndex != -1) {
 152.620 +            classIn = classFqn.substring(0, fqnIndex);
 152.621 +        }
 152.622 +        int prefixLength = prefix.length();
 152.623 +
 152.624 +        for (IndexResult map : result) {
 152.625 +            assert map != null;
 152.626 +
 152.627 +            String url = map.getUrl().toExternalForm();
 152.628 +            String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
 152.629 +            String module = map.getValue(PythonIndexer.FIELD_IN);
 152.630 +
 152.631 +            if (extendsClasses == null) {
 152.632 +                String[] ext = map.getValues(PythonIndexer.FIELD_EXTENDS_NAME);
 152.633 +                if (ext != null && ext.length > 0) {
 152.634 +                    if (extendsClasses == null) {
 152.635 +                        extendsClasses = Arrays.asList(ext);
 152.636 +                    } else {
 152.637 +                        extendsClasses = new ArrayList<>(extendsClasses);
 152.638 +                        extendsClasses.addAll(Arrays.asList(ext));
 152.639 +                    }
 152.640 +                }
 152.641 +            }
 152.642 +
 152.643 +            String[] members = map.getValues(PythonIndexer.FIELD_MEMBER);
 152.644 +
 152.645 +            if (members != null) {
 152.646 +                for (String signature : members) {
 152.647 +                    // Prevent duplicates when method is redefined
 152.648 +                    if (includeOverrides || !seenSignatures.contains(signature)) {
 152.649 +                        if (signature.startsWith(prefix)) {
 152.650 +                            if (kind == QuerySupport.Kind.EXACT) {
 152.651 +                                if (signature.charAt(prefixLength) != ';') {
 152.652 +                                    continue;
 152.653 +                                }
 152.654 +                            } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !signature.regionMatches(true, 0, prefix, 0, prefix.length())) {
 152.655 +                                continue;
 152.656 +                            } else {
 152.657 +                                // REGEXP, CAMELCASE filtering etc. not supported here
 152.658 +                                assert (kind == QuerySupport.Kind.PREFIX) ||
 152.659 +                                        (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
 152.660 +                            }
 152.661 +
 152.662 +                            if (!includeOverrides) {
 152.663 +                                seenSignatures.add(signature);
 152.664 +                            }
 152.665 +                            IndexedElement element = IndexedElement.create(signature, module, url, clz);
 152.666 +                            // TODO - filter out private? Or let code completer do that? Probably should, in case
 152.667 +                            // we have more rights when inheriting
 152.668 +                            element.setSmart(!haveRedirected);
 152.669 +                            element.setInherited(inheriting);
 152.670 +                            if (includeOverrides) {
 152.671 +                                element.setOrder(depth);
 152.672 +                            }
 152.673 +                            elements.add(element);
 152.674 +                        }
 152.675 +                    }
 152.676 +                }
 152.677 +            }
 152.678 +        }
 152.679 +
 152.680 +        if (classFqn.equals(OBJECT)) {
 152.681 +            return foundIt;
 152.682 +        }
 152.683 +
 152.684 +        if (extendsClasses == null || extendsClasses.size() == 0) {
 152.685 +            addMethodsFromClass(prefix, kind, OBJECT, elements, seenSignatures, scannedClasses,
 152.686 +                    true, true, includeOverrides, depth + 1);
 152.687 +        } else {
 152.688 +            // We're not sure we have a fully qualified path, so try some different candidates
 152.689 +            for (String extendsClass : extendsClasses) {
 152.690 +                if (!addMethodsFromClass(prefix, kind, extendsClass, elements, seenSignatures,
 152.691 +                        scannedClasses, haveRedirected, true, includeOverrides, depth + 1)) {
 152.692 +                    // Search by classIn
 152.693 +                    String fqn = classIn;
 152.694 +
 152.695 +                    while (fqn != null) {
 152.696 +                        if (addMethodsFromClass(prefix, kind, fqn + "::" + extendsClass, elements,
 152.697 +                                seenSignatures, scannedClasses, haveRedirected, true, includeOverrides, depth + 1)) {
 152.698 +                            break;
 152.699 +                        }
 152.700 +
 152.701 +                        int f = fqn.lastIndexOf("::"); // NOI18N
 152.702 +
 152.703 +                        if (f == -1) {
 152.704 +                            break;
 152.705 +                        } else {
 152.706 +                            fqn = fqn.substring(0, f);
 152.707 +                        }
 152.708 +                    }
 152.709 +                }
 152.710 +            }
 152.711 +        }
 152.712 +
 152.713 +        return foundIt;
 152.714 +    }
 152.715 +    
 152.716 +    
 152.717 +    public Set<IndexedElement> getAllMembers(String name, QuerySupport.Kind kind, PythonParserResult context, boolean includeDuplicates) {
 152.718 +        final Set<IndexResult> result = new HashSet<>();
 152.719 +        // TODO - handle case sensitivity better...
 152.720 +        String field = PythonIndexer.FIELD_MEMBER;
 152.721 +        QuerySupport.Kind originalKind = kind;
 152.722 +        if (kind == QuerySupport.Kind.EXACT) {
 152.723 +            // I can't do exact searches on methods because the method
 152.724 +            // entries include signatures etc. So turn this into a prefix
 152.725 +            // search and then compare chopped off signatures with the name
 152.726 +            kind = QuerySupport.Kind.PREFIX;
 152.727 +        }
 152.728 +
 152.729 +        String searchUrl = null;
 152.730 +        if (context != null) {
 152.731 +            searchUrl = context.getSnapshot().getSource().getFileObject().toURL().toExternalForm();
 152.732 +        }
 152.733 +
 152.734 +        String[] terms = {PythonIndexer.FIELD_IN,
 152.735 +                          PythonIndexer.FIELD_EXTENDS_NAME,
 152.736 +                          PythonIndexer.FIELD_MEMBER,
 152.737 +                          PythonIndexer.FIELD_CLASS_NAME};
 152.738 +
 152.739 +        search(field, name, kind, result, terms);
 152.740 +
 152.741 +//        Set<String> uniqueClasses = null;
 152.742 +//        if (includeDuplicates) {
 152.743 +//            uniqueClasses = null;
 152.744 +//        } else if (uniqueClasses == null) {
 152.745 +//            uniqueClasses = new HashSet<String>();
 152.746 +//        }
 152.747 +
 152.748 +        final Set<IndexedElement> members = new HashSet<>();
 152.749 +        int nameLength = name.length();
 152.750 +
 152.751 +        for (IndexResult map : result) {
 152.752 +            String[] signatures = map.getValues(PythonIndexer.FIELD_MEMBER);
 152.753 +            if (signatures != null && signatures.length > 0) {
 152.754 +                String url = map.getUrl().toExternalForm();
 152.755 +                String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
 152.756 +                String module = map.getValue(PythonIndexer.FIELD_IN);
 152.757 +                boolean inherited = searchUrl == null || !searchUrl.equals(url);
 152.758 +
 152.759 +                for (String signature : signatures) {
 152.760 +                    if (originalKind == QuerySupport.Kind.EXACT) {
 152.761 +                        if (signature.charAt(nameLength) != ';') {
 152.762 +                            continue;
 152.763 +                        }
 152.764 +                    } else if (originalKind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !signature.regionMatches(true, 0, name, 0, name.length())) {
 152.765 +                        continue;
 152.766 +                    } else {
 152.767 +                        // REGEXP, CAMELCASE filtering etc. not supported here
 152.768 +                        assert (originalKind == QuerySupport.Kind.PREFIX) ||
 152.769 +                                (originalKind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
 152.770 +                    }
 152.771 +
 152.772 +                    IndexedElement element = IndexedElement.create(signature, module, url, clz);
 152.773 +                    element.setInherited(inherited);
 152.774 +                    members.add(element);
 152.775 +                }
 152.776 +            }
 152.777 +        }
 152.778 +
 152.779 +        return members;
 152.780 +    }
 152.781 +    
 152.782 +    public Set<IndexedElement> getAllElements(String name, QuerySupport.Kind kind, PythonParserResult context, boolean includeDuplicates) {
 152.783 +        final Set<IndexResult> result = new HashSet<>();
 152.784 +        // TODO - handle case sensitivity better...
 152.785 +        String field = PythonIndexer.FIELD_ITEM;
 152.786 +        QuerySupport.Kind originalKind = kind;
 152.787 +        if (kind == QuerySupport.Kind.EXACT) {
 152.788 +            // I can't do exact searches on methods because the method
 152.789 +            // entries include signatures etc. So turn this into a prefix
 152.790 +            // search and then compare chopped off signatures with the name
 152.791 +            kind = QuerySupport.Kind.PREFIX;
 152.792 +        }
 152.793 +
 152.794 +        String searchUrl = null;
 152.795 +        if (context != null) {
 152.796 +            searchUrl = context.getSnapshot().getSource().getFileObject().toURL().toExternalForm();
 152.797 +        }
 152.798 +
 152.799 +        String[] terms = { PythonIndexer.FIELD_ITEM,
 152.800 +                           PythonIndexer.FIELD_MODULE_NAME };
 152.801 +
 152.802 +        search(field, name, kind, result, terms);
 152.803 +
 152.804 +        final Set<IndexedElement> elements = new HashSet<>();
 152.805 +        int nameLength = name.length();
 152.806 +
 152.807 +        for (IndexResult map : result) {
 152.808 +            String[] signatures = map.getValues(PythonIndexer.FIELD_ITEM);
 152.809 +            if (signatures != null && signatures.length > 0) {
 152.810 +                String url = map.getUrl().toExternalForm();
 152.811 +                String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
 152.812 +                boolean inherited = searchUrl == null || !searchUrl.equals(url);
 152.813 +
 152.814 +                for (String signature : signatures) {
 152.815 +                    if (originalKind == QuerySupport.Kind.EXACT) {
 152.816 +                        if (signature.charAt(nameLength) != ';') {
 152.817 +                            continue;
 152.818 +                        }
 152.819 +                    } else if (originalKind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !signature.regionMatches(true, 0, name, 0, name.length())) {
 152.820 +                        continue;
 152.821 +                    } else {
 152.822 +                        // REGEXP, CAMELCASE filtering etc. not supported here
 152.823 +                        assert (originalKind == QuerySupport.Kind.PREFIX) ||
 152.824 +                                (originalKind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
 152.825 +                    }
 152.826 +
 152.827 +                    IndexedElement element = IndexedElement.create(signature, module, url, null);
 152.828 +                    if (element.isPrivate() && !url.equals(searchUrl)) {
 152.829 +                        continue;
 152.830 +                    }
 152.831 +                    element.setInherited(inherited);
 152.832 +                    elements.add(element);
 152.833 +                }
 152.834 +            }
 152.835 +        }
 152.836 +
 152.837 +        return elements;
 152.838 +    }
 152.839 +
 152.840 +    public Set<String> getBuiltinSymbols() {
 152.841 +        Set<String> modules = new HashSet<>();
 152.842 +
 152.843 +        // The "functions" module is always imported by the interpreter, and ditto
 152.844 +        // for exceptions, constants, etc.
 152.845 +        //modules.add("objects"); // NOI18N -- just links to the others
 152.846 +        modules.addAll(BUILTIN_MODULES);
 152.847 +
 152.848 +        Set<String> symbols = new HashSet<>(250);
 152.849 +
 152.850 +        String[] terms = { PythonIndexer.FIELD_MODULE_NAME,
 152.851 +                           PythonIndexer.FIELD_ITEM };
 152.852 +
 152.853 +        // Look up all symbols
 152.854 +        for (String module : modules) {
 152.855 +            final Set<IndexResult> result = new HashSet<>();
 152.856 +            // TODO - handle case sensitivity better...
 152.857 +            String field = PythonIndexer.FIELD_MODULE_NAME;
 152.858 +            QuerySupport.Kind kind = QuerySupport.Kind.EXACT;
 152.859 +
 152.860 +            search(field, module, kind, result, terms);
 152.861 +
 152.862 +            for (IndexResult map : result) {
 152.863 +                String[] signatures = map.getValues(PythonIndexer.FIELD_ITEM);
 152.864 +                if (signatures != null) {
 152.865 +                    for (String signature : signatures) {
 152.866 +                        int semi = signature.indexOf(';');
 152.867 +                        assert semi != -1;
 152.868 +                        int flags = IndexedElement.decode(signature, semi + 3, 0);
 152.869 +                        if ((flags & IndexedElement.PRIVATE) != 0) {
 152.870 +                            // Skip private symbols - can't import those
 152.871 +                            continue;
 152.872 +                        }
 152.873 +                        String name = signature.substring(0, semi);
 152.874 +                        symbols.add(name);
 152.875 +                    }
 152.876 +                }
 152.877 +            }
 152.878 +        }
 152.879 +
 152.880 +        // Computed as described below
 152.881 +        String[] MISSING = {
 152.882 +            "Ellipsis", "False", "IndentationError", "None", "NotImplemented", "TabError", // NOI18N
 152.883 +            "True", "__debug__", "__doc__", "__name__", "copyright", "credits", "exit", "license", // NOI18N
 152.884 +            "quit" // NOI18N
 152.885 +        };
 152.886 +        for (String s : MISSING) {
 152.887 +            symbols.add(s);
 152.888 +        }
 152.889 +        symbols.add("__builtins__"); // NOI18N
 152.890 +        symbols.add("__file__"); // NOI18N
 152.891 +
 152.892 +        //// COMPUTING MISSING SYMBOLS:
 152.893 +        //// My builtin .rst files don't seem to define all the builtin symbols that the Python
 152.894 +        //// interpreter is configured with.  I generated these pretty trivially; run
 152.895 +        //// python and type "dir(__builtins__)" and you end up a list like the below:
 152.896 +        ////String[] EXTRA_BUILTINS = {"ArithmeticError", "AssertionError", "AttributeError", "BaseException",
 152.897 +        //    "DeprecationWarning", "EOFError", "Ellipsis", "EnvironmentError", "Exception", "False",
 152.898 +        //    "FloatingPointError", "FutureWarning", "GeneratorExit", "IOError", "ImportError",
 152.899 +        //    "ImportWarning", "IndentationError", "IndexError", "KeyError", "KeyboardInterrupt",
 152.900 +        //    "LookupError", "MemoryError", "NameError", "None", "NotImplemented", "NotImplementedError",
 152.901 +        //    "OSError", "OverflowError", "PendingDeprecationWarning", "ReferenceError", "RuntimeError",
 152.902 +        //    "RuntimeWarning", "StandardError", "StopIteration", "SyntaxError", "SyntaxWarning", "SystemError",
 152.903 +        //    "SystemExit", "TabError", "True", "TypeError", "UnboundLocalError", "UnicodeDecodeError",
 152.904 +        //    "UnicodeEncodeError", "UnicodeError", "UnicodeTranslateError", "UnicodeWarning", "UserWarning",
 152.905 +        //    "ValueError", "Warning", "ZeroDivisionError", "__debug__", "__doc__", "__import__", "__name__",
 152.906 +        //    "abs", "all", "any", "apply", "basestring", "bool", "buffer", "callable", "chr", "classmethod",
 152.907 +        //    "cmp", "coerce", "compile", "complex", "copyright", "credits", "delattr", "dict", "dir", "divmod",
 152.908 +        //    "enumerate", "eval", "execfile", "exit", "file", "filter", "float", "frozenset", "getattr",
 152.909 +        //    "globals", "hasattr", "hash", "help", "hex", "id", "input", "int", "intern", "isinstance",
 152.910 +        //    "issubclass", "iter", "len", "license", "list", "locals", "long", "map", "max", "min", "object",
 152.911 +        //    "oct", "open", "ord", "pow", "property", "quit", "range", "raw_input", "reduce", "reload",
 152.912 +        //    "repr", "reversed", "round", "set", "setattr", "slice", "sorted", "staticmethod", "str", "sum",
 152.913 +        //    "super", "tuple", "type", "unichr", "unicode", "vars", "xrange", "zip"};
 152.914 +        //// Most of these will be defined by my index search. However, for the missing ones, let's add them
 152.915 +        //// in. The following code computes the delta and produces a source-like string for it.
 152.916 +        //// It also counts the total symbol map size so we can pick a reasonable default:
 152.917 +        //List<String> asList = Arrays.asList(EXTRA_BUILTINS);
 152.918 +        //Set<String> asSet = new HashSet<String>(asList);
 152.919 +        //asSet.removeAll(symbols);
 152.920 +        //List<String> missing = new ArrayList<String>(asSet);
 152.921 +        //Collections.sort(missing);
 152.922 +        //int width = 0;
 152.923 +        //StringBuilder sb = new StringBuilder();
 152.924 +        //for (String s : missing) {
 152.925 +        //    sb.append('"');
 152.926 +        //    sb.append(s);
 152.927 +        //    sb.append('"');
 152.928 +        //    sb.append(',');
 152.929 +        //    sb.append(' ');
 152.930 +        //    width += s.length()+4;
 152.931 +        //    if (width > 70) {
 152.932 +        //        sb.append("\n");
 152.933 +        //        width = 0;
 152.934 +        //    }
 152.935 +        //}
 152.936 +        //String missingCode = "String[] MISSING = {\n" + sb.toString() + "\n};\n";
 152.937 +        //symbols.addAll(asList);
 152.938 +        //int requiredSetSize = symbols.size();
 152.939 +
 152.940 +        return symbols;
 152.941 +    }
 152.942 +
 152.943 +    @SuppressWarnings("unchecked")
 152.944 +    public Set<String> getImportsFor(String ident, boolean includeSymbol) {
 152.945 +        Set<String> modules = new HashSet<>(10);
 152.946 +
 152.947 +        final Set<IndexResult> result = new HashSet<>();
 152.948 +        search(PythonIndexer.FIELD_MODULE_NAME, ident, QuerySupport.Kind.EXACT, result, PythonIndexer.FIELD_MODULE_NAME);
 152.949 +        for (IndexResult map : result) {
 152.950 +            String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
 152.951 +            if (module != null) {
 152.952 +                // TODO - record more information about this, such as the FQN
 152.953 +                // so it's easier for the user to disambiguate
 152.954 +                modules.add(module);
 152.955 +            }
 152.956 +        }
 152.957 +
 152.958 +        // TODO - handle case sensitivity better...
 152.959 +        String field = PythonIndexer.FIELD_ITEM;
 152.960 +        QuerySupport.Kind kind = QuerySupport.Kind.PREFIX; // We're storing encoded signatures so not exact matches
 152.961 +
 152.962 +        String[] terms = { PythonIndexer.FIELD_ITEM,
 152.963 +                           PythonIndexer.FIELD_MODULE_NAME };
 152.964 +
 152.965 +        result.clear();
 152.966 +        search(field, ident, kind, result, terms);
 152.967 +        String match = ident + ";";
 152.968 +
 152.969 +        MapSearch:
 152.970 +        for (IndexResult map : result) {
 152.971 +            String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
 152.972 +            if (module == null) {
 152.973 +                continue;
 152.974 +            }
 152.975 +
 152.976 +            if (module.indexOf('-') != -1) {
 152.977 +                // Don't include modules with -; these aren't real module
 152.978 +                // names (usually python scripts in directories containing a dash
 152.979 +                // that I incorrectly compute a module name for
 152.980 +                continue;
 152.981 +            }
 152.982 +
 152.983 +            String[] members = map.getValues(PythonIndexer.FIELD_ITEM);
 152.984 +            if (members == null || members.length == 0) {
 152.985 +                continue;
 152.986 +            }
 152.987 +
 152.988 +            int semi = match.length() - 1;
 152.989 +
 152.990 +            for (String signature : members) {
 152.991 +                if (signature.startsWith(match)) {
 152.992 +                    if (includeSymbol) {
 152.993 +                        int flags = IndexedElement.decode(signature, semi + 3, 0);
 152.994 +                        if ((flags & IndexedElement.PRIVATE) != 0) {
 152.995 +                            // Skip private symbols - can't import those
 152.996 +                            continue;
 152.997 +                        }
 152.998 +                        String sig = ident;
 152.999 +                        char type = signature.charAt(semi + 1);
152.1000 +                        if (type == 'F') {
152.1001 +                            int sigStart = signature.indexOf(';', semi + 3) + 1;
152.1002 +                            int sigEnd = signature.indexOf(';', sigStart);
152.1003 +                            sig = ident + "(" + signature.substring(sigStart, sigEnd) + ")"; // NOI18N
152.1004 +                        } else if (type == 'I') {
152.1005 +                            // Don't provide modules that just -import- the symbol
152.1006 +                            continue;
152.1007 +                        }
152.1008 +                        if (!sig.equals(module)) {
152.1009 +                            modules.add(module + ": " + sig); // NOI18N
152.1010 +                        } else {
152.1011 +                            modules.add(module);
152.1012 +                        }
152.1013 +                    } else {
152.1014 +                        modules.add(module);
152.1015 +                    }
152.1016 +                    continue MapSearch;
152.1017 +                }
152.1018 +            }
152.1019 +        }
152.1020 +
152.1021 +        return modules;
152.1022 +    }
152.1023 +    
152.1024 +    public Set<IndexedElement> getImportedElements(String prefix, QuerySupport.Kind kind, PythonParserResult context, List<Import> imports, List<ImportFrom> importsFrom) {
152.1025 +        // TODO - separate methods from variables?? E.g. if you have method Foo() and class Foo
152.1026 +        // coming from different places
152.1027 +        
152.1028 +        
152.1029 +//        Set<String> imported = new HashSet<String>();
152.1030 +//
152.1031 +        Set<IndexedElement> elements = new HashSet<>();
152.1032 +
152.1033 +        // Look up the imports and compute all the symbols we get from the import
152.1034 +        Set<String> modules = new HashSet<>();
152.1035 +
152.1036 +        // ImportsFrom require no index lookup
152.1037 +        for (ImportFrom from : importsFrom) {
152.1038 +            if (ImportManager.isFutureImport(from)) {
152.1039 +                continue;
152.1040 +            }
152.1041 +            List<alias> names = from.getInternalNames();
152.1042 +            if (names != null) {
152.1043 +                for (alias at : names) {
152.1044 +                    if ("*".equals(at.getInternalName())) { // NOI18N
152.1045 +                        modules.add(from.getInternalModule());
152.1046 +//                    } else {
152.1047 +//                        String name = at.getInternalAsname() != null ? at.getInternalAsname() : at.getInternalName();
152.1048 +//                        assert name.length() > 0;
152.1049 +//                        imported.add(name);
152.1050 +                    }
152.1051 +                }
152.1052 +            }
152.1053 +        }
152.1054 +
152.1055 +//        for (Import imp : imports) {
152.1056 +//            if (imp.names != null) {
152.1057 +//                for (alias at : imp.getInternalNames()) {
152.1058 +//                    if (at.getInternalAsname() != null) {
152.1059 +//                        String name = at.getInternalAsname();
152.1060 +//                        assert name.length() > 0;
152.1061 +//                        imported.add(name);
152.1062 +//                    } else {
152.1063 +//                        imported.add(at.getInternalName());
152.1064 +//                    }
152.1065 +//                }
152.1066 +//            }
152.1067 +//        }
152.1068 +//
152.1069 +//
152.1070 +//        // Create variable items for the locally imported symbols
152.1071 +//        for (String name : imported) {
152.1072 +//            if (name.startsWith(prefix)) {
152.1073 +//                if (kind == QuerySupport.Kind.EXACT) {
152.1074 +//                    // Ensure that the method is not longer than the prefix
152.1075 +//                    if ((name.length() > prefix.length()) &&
152.1076 +//                            (name.charAt(prefix.length()) != '(') &&
152.1077 +//                            (name.charAt(prefix.length()) != ';')) {
152.1078 +//                        continue;
152.1079 +//                    }
152.1080 +//                } else {
152.1081 +//                    // REGEXP, CAMELCASE filtering etc. not supported here
152.1082 +//                    assert (kind == QuerySupport.Kind.PREFIX) ||
152.1083 +//                    (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
152.1084 +//                }
152.1085 +//    String url = null;
152.1086 +//                ElementKind elementKind = ElementKind.VARIABLE;
152.1087 +//                if (Character.isUpperCase(name.charAt(0))) {
152.1088 +//                    // Class?
152.1089 +//                    elementKind = ElementKind.CLASS;
152.1090 +//                }
152.1091 +//                IndexedElement element = new IndexedElement(name, elementKind, url, null);
152.1092 +//                element.setSmart(true);
152.1093 +//                elements.add(element);
152.1094 +//                // TODO - imported class symbls should be shown as classes!
152.1095 +//            }
152.1096 +//        }
152.1097 +
152.1098 +        // Always include the current file as imported
152.1099 +        String moduleName = null;
152.1100 +        if (context != null) {
152.1101 +            moduleName = PythonUtils.getModuleName(context.getSnapshot().getSource().getFileObject());
152.1102 +            modules.add(moduleName);
152.1103 +        }
152.1104 +
152.1105 +        modules.addAll(BUILTIN_MODULES);
152.1106 +
152.1107 +        addImportedElements(prefix, kind, modules, elements, null);
152.1108 +
152.1109 +        return elements;
152.1110 +    }
152.1111 +    public Set<String> getImportedFromWildcards(List<ImportFrom> importsFrom) {
152.1112 +        Set<String> symbols = new HashSet<>(100);
152.1113 +
152.1114 +        // Look up the imports and compute all the symbols we get from the import
152.1115 +        Set<String> modules = new HashSet<>();
152.1116 +
152.1117 +        // ImportsFrom require no index lookup
152.1118 +        for (ImportFrom from : importsFrom) {
152.1119 +            List<alias> names = from.getInternalNames();
152.1120 +            if (names != null) {
152.1121 +                for (alias at : names) {
152.1122 +                    if ("*".equals(at.getInternalName())) { // NOI18N
152.1123 +                        modules.add(from.getInternalModule());
152.1124 +                    }
152.1125 +                }
152.1126 +            }
152.1127 +        }
152.1128 +
152.1129 +        String[] terms = { PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MODULE_NAME };
152.1130 +
152.1131 +        // Look up all symbols
152.1132 +        for (String module : modules) {
152.1133 +            // TODO - cache builtins?
152.1134 +            Set<String> moduleSymbols = symbols;
152.1135 +            boolean isSystem = isSystemModule(module);
152.1136 +            if (isSystem) {
152.1137 +                Set<String> s = wildcardImports.get(module);
152.1138 +                if (s != null) {
152.1139 +                    symbols.addAll(s);
152.1140 +                    continue;
152.1141 +                } else {
152.1142 +                    moduleSymbols = new HashSet<>(100);
152.1143 +                }
152.1144 +            }
152.1145 +
152.1146 +
152.1147 +            final Set<IndexResult> result = new HashSet<>();
152.1148 +            // TODO - handle case sensitivity better...
152.1149 +
152.1150 +            search(PythonIndexer.FIELD_MODULE_NAME, module, QuerySupport.Kind.EXACT, result, terms);
152.1151 +
152.1152 +            for (IndexResult map : result) {
152.1153 +                String[] items = map.getValues(PythonIndexer.FIELD_ITEM);
152.1154 +                if (items != null) {
152.1155 +                    for (String signature : items) {
152.1156 +                        int semi = signature.indexOf(';');
152.1157 +                        assert semi != -1;
152.1158 +                        int flags = IndexedElement.decode(signature, semi + 3, 0);
152.1159 +                        if ((flags & IndexedElement.PRIVATE) != 0) {
152.1160 +                            // Skip private symbols - can't import those
152.1161 +                            continue;
152.1162 +                        }
152.1163 +
152.1164 +                        String name = signature.substring(0, semi);
152.1165 +                        moduleSymbols.add(name);
152.1166 +                    }
152.1167 +                }
152.1168 +            }
152.1169 +
152.1170 +            if (isSystem) {
152.1171 +                assert moduleSymbols != symbols;
152.1172 +                symbols.addAll(moduleSymbols);
152.1173 +                wildcardImports.put(module, moduleSymbols);
152.1174 +            }
152.1175 +        }
152.1176 +
152.1177 +        return symbols;
152.1178 +    }
152.1179 +    
152.1180 +    public Set<IndexedElement> getImportedElements(String prefix, QuerySupport.Kind kind, Set<String> modules, Set<String> systemModuleHolder) {
152.1181 +        Set<IndexedElement> elements = new HashSet<>();
152.1182 +
152.1183 +        addImportedElements(prefix, kind, modules, elements, systemModuleHolder);
152.1184 +
152.1185 +        return elements;
152.1186 +    }
152.1187 +
152.1188 +    public boolean isSystemModule(String module) {
152.1189 +        if (systemModules == null) {
152.1190 +            systemModules = new HashSet<>(800); // measured: 623
152.1191 +            String[] terms = { PythonIndexer.FIELD_MODULE_ATTR_NAME,
152.1192 +                               PythonIndexer.FIELD_MODULE_NAME };
152.1193 +            final Set<IndexResult> result = new HashSet<>();
152.1194 +
152.1195 +            // This doesn't work because the attrs field isn't searchable:
152.1196 +            //search(PythonIndexer.FIELD_MODULE_ATTR_NAME, "S", QuerySupport.Kind.PREFIX, result, ALL_SCOPE, terms);
152.1197 +            //for (IndexResult map : result) {
152.1198 +            //    assert map.getValue(PythonIndexer.FIELD_MODULE_ATTR_NAME).indexOf("S") != -1;
152.1199 +            //    systemModules.add(map.getValue(PythonIndexer.FIELD_MODULE_NAME));
152.1200 +            //}
152.1201 +
152.1202 +            search(PythonIndexer.FIELD_MODULE_NAME, "", QuerySupport.Kind.PREFIX, result, terms);
152.1203 +
152.1204 +            for (IndexResult map : result) {
152.1205 +                String attrs = map.getValue(PythonIndexer.FIELD_MODULE_ATTR_NAME);
152.1206 +                if (attrs != null && attrs.indexOf('S') != -1) {
152.1207 +                    String mod = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
152.1208 +                    systemModules.add(mod);
152.1209 +                }
152.1210 +            }
152.1211 +        }
152.1212 +
152.1213 +        return systemModules.contains(module);
152.1214 +    }
152.1215 +
152.1216 +    public boolean isLowercaseClassName(String clz) {
152.1217 +        if (availableClasses == null) {
152.1218 +            availableClasses = new HashSet<>(300); // measured: 193
152.1219 +            final Set<IndexResult> result = new HashSet<>();
152.1220 +
152.1221 +            search(PythonIndexer.FIELD_CLASS_NAME, "", QuerySupport.Kind.PREFIX, result, PythonIndexer.FIELD_CLASS_NAME);
152.1222 +
152.1223 +            for (IndexResult map : result) {
152.1224 +                String c = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
152.1225 +                if (c != null && !Character.isUpperCase(c.charAt(0))) {
152.1226 +                    availableClasses.add(c);
152.1227 +                }
152.1228 +            }
152.1229 +        }
152.1230 +
152.1231 +        return availableClasses.contains(clz);
152.1232 +    }
152.1233 +    
152.1234 +    public void addImportedElements(String prefix, QuerySupport.Kind kind, Set<String> modules, Set<IndexedElement> elements, Set<String> systemModuleHolder) {
152.1235 +        
152.1236 +        String[] terms = { PythonIndexer.FIELD_ITEM,
152.1237 +                           PythonIndexer.FIELD_MODULE_ATTR_NAME,
152.1238 +                           PythonIndexer.FIELD_MODULE_NAME };
152.1239 +
152.1240 +        // Look up all symbols
152.1241 +        for (String module : modules) {
152.1242 +            boolean isBuiltin = isBuiltinModule(module);
152.1243 +            boolean isSystem = isBuiltin;
152.1244 +
152.1245 +            final Set<IndexResult> result = new HashSet<>();
152.1246 +            // TODO - handle case sensitivity better...
152.1247 +
152.1248 +            search(PythonIndexer.FIELD_MODULE_NAME, module, QuerySupport.Kind.EXACT, result, terms);
152.1249 +            int prefixLength = prefix.length();
152.1250 +
152.1251 +            for (IndexResult map : result) {
152.1252 +                String url = map.getUrl().toExternalForm();
152.1253 +                String[] items = map.getValues(PythonIndexer.FIELD_ITEM);
152.1254 +                if (items != null) {
152.1255 +                    String attrs = map.getValue(PythonIndexer.FIELD_MODULE_ATTR_NAME);
152.1256 +                    if (attrs != null && attrs.indexOf('S') != -1) {
152.1257 +                        isSystem = true;
152.1258 +                    }
152.1259 +                    for (String signature : items) {
152.1260 +                        if (signature.startsWith(prefix)) {
152.1261 +                            if (kind == QuerySupport.Kind.EXACT) {
152.1262 +                                if (signature.charAt(prefixLength) != ';') {
152.1263 +                                    continue;
152.1264 +                                }
152.1265 +                            } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !signature.regionMatches(true, 0, prefix, 0, prefix.length())) {
152.1266 +                                continue;
152.1267 +                            } else {
152.1268 +                                // REGEXP, CAMELCASE filtering etc. not supported here
152.1269 +                                assert (kind == QuerySupport.Kind.PREFIX) ||
152.1270 +                                        (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
152.1271 +                            }
152.1272 +
152.1273 +                            IndexedElement element = IndexedElement.create(signature, module, url, null);
152.1274 +                            if (element.isPrivate()) {
152.1275 +                                continue;
152.1276 +                            }
152.1277 +                            if (isBuiltin) {
152.1278 +                                element.setRhs("<i>builtin</i>");
152.1279 +                            } else {
152.1280 +                                element.setSmart(true);
152.1281 +                            }
152.1282 +                            element.setInherited(true);
152.1283 +                            elements.add(element);
152.1284 +                        }
152.1285 +                    }
152.1286 +                }
152.1287 +            }
152.1288 +
152.1289 +            if (systemModuleHolder != null && isSystem) {
152.1290 +                systemModuleHolder.add(module);
152.1291 +            }
152.1292 +        }
152.1293 +    }
152.1294 +
152.1295 +    public Set<IndexedElement> getExceptions(String prefix, QuerySupport.Kind kind) {
152.1296 +        final Set<IndexResult> result = new HashSet<>();
152.1297 +        String[] terms = { PythonIndexer.FIELD_EXTENDS_NAME,
152.1298 +                              PythonIndexer.FIELD_CLASS_NAME,
152.1299 +                              PythonIndexer.FIELD_CLASS_ATTR_NAME,
152.1300 +                              PythonIndexer.FIELD_IN };
152.1301 +        search(PythonIndexer.FIELD_EXTENDS_NAME, "", QuerySupport.Kind.PREFIX, result, terms); // NOI18N
152.1302 +        Map<String, String> extendsMap = new HashMap<>(100);
152.1303 +        // First iteration: Compute inheritance hierarchy
152.1304 +        for (IndexResult map : result) {
152.1305 +
152.1306 +            String superClass = map.getValue(PythonIndexer.FIELD_EXTENDS_NAME);
152.1307 +            if (superClass != null) {
152.1308 +                String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
152.1309 +                if (clz != null) {
152.1310 +                    extendsMap.put(clz, superClass);
152.1311 +                }
152.1312 +            }
152.1313 +        }
152.1314 +
152.1315 +        // Compute set of classes that extend Exception
152.1316 +
152.1317 +        Set<String> exceptionClasses = new HashSet<>();
152.1318 +        Set<String> notExceptionClasses = new HashSet<>();
152.1319 +        exceptionClasses.add("Exception"); // NOI18N
152.1320 +        Outer:
152.1321 +        for (String cls : extendsMap.keySet()) {
152.1322 +            if (notExceptionClasses.contains(cls)) {
152.1323 +                continue;
152.1324 +            } else if (!exceptionClasses.contains(cls)) {
152.1325 +                // See if this extends exception:
152.1326 +                String c = cls;
152.1327 +                int depth = 0;
152.1328 +                while (c != null) {
152.1329 +                    c = extendsMap.get(c);
152.1330 +                    String prev = null;
152.1331 +                    if (c != null) {
152.1332 +                        if (exceptionClasses.contains(c)) {
152.1333 +                            exceptionClasses.add(cls);
152.1334 +                            continue Outer;
152.1335 +                        }
152.1336 +                        depth++;
152.1337 +                        if (depth == 15) {
152.1338 +                            // we're probably going in circles, perhaps a extends b extends a.
152.1339 +                            // This doesn't really happen in Python, but can happen when there
152.1340 +                            // are unrelated classes with the same name getting treated as one here -
152.1341 +                            // class a in library X, and class a in library Y,
152.1342 +                            break;
152.1343 +                        }
152.1344 +                    } else if (prev != null) {
152.1345 +                        notExceptionClasses.add(prev);
152.1346 +                        break;
152.1347 +                    }
152.1348 +                }
152.1349 +                notExceptionClasses.add(cls);
152.1350 +            }
152.1351 +        }
152.1352 +
152.1353 +        // Next add elements for all the exceptions
152.1354 +        final Set<IndexedElement> classes = new HashSet<>();
152.1355 +        for (IndexResult map : result) {
152.1356 +            String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
152.1357 +            if (clz == null || !exceptionClasses.contains(clz)) {
152.1358 +                continue;
152.1359 +            }
152.1360 +
152.1361 +            if ((kind == QuerySupport.Kind.PREFIX) && !clz.startsWith(prefix)) {
152.1362 +                continue;
152.1363 +            } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !clz.regionMatches(true, 0, prefix, 0, prefix.length())) {
152.1364 +                continue;
152.1365 +            } else if (kind == QuerySupport.Kind.EXACT && !clz.equals(prefix)) {
152.1366 +                continue;
152.1367 +            }
152.1368 +
152.1369 +            String url = map.getUrl().toExternalForm();
152.1370 +            String module = map.getValue(PythonIndexer.FIELD_IN);
152.1371 +            IndexedElement element = new IndexedElement(clz, ElementKind.CLASS, url, module, null, null);
152.1372 +            String attrs = map.getValue(PythonIndexer.FIELD_CLASS_ATTR_NAME);
152.1373 +            if (attrs != null) {
152.1374 +                int flags = IndexedElement.decode(attrs, 0, 0);
152.1375 +                element.setFlags(flags);
152.1376 +            }
152.1377 +            classes.add(element);
152.1378 +        }
152.1379 +
152.1380 +        return classes;
152.1381 +    }
152.1382 +
152.1383 +    /** Find the subclasses of the given class name, with the POSSIBLE fqn from the
152.1384 +     * context of the usage. */
152.1385 +    public Set<IndexedElement> getSubClasses(String fqn, String possibleFqn, String name, boolean directOnly) {
152.1386 +        //String field = PythonIndexer.FIELD_FQN_NAME;
152.1387 +        Set<IndexedElement> classes = new HashSet<>();
152.1388 +        Set<String> scannedClasses = new HashSet<>();
152.1389 +        Set<String> seenClasses = new HashSet<>();
152.1390 +
152.1391 +        if (fqn != null) {
152.1392 +            addSubclasses(fqn, classes, seenClasses, scannedClasses, directOnly);
152.1393 +        } else {
152.1394 +            fqn = possibleFqn;
152.1395 +            if (name.equals(possibleFqn)) {
152.1396 +                fqn = null;
152.1397 +            }
152.1398 +
152.1399 +            // Try looking at the libraries too
152.1400 +            while ((classes.size() == 0) && (fqn != null && fqn.length() > 0)) {
152.1401 +                // TODO - use the boolvalue from addclasses instead!
152.1402 +                boolean found = addSubclasses(fqn + "::" + name, classes, seenClasses, scannedClasses, directOnly);
152.1403 +                if (found) {
152.1404 +                    return classes;
152.1405 +                }
152.1406 +
152.1407 +                int f = fqn.lastIndexOf("::");
152.1408 +
152.1409 +                if (f == -1) {
152.1410 +                    break;
152.1411 +                } else {
152.1412 +                    fqn = fqn.substring(0, f);
152.1413 +                }
152.1414 +            }
152.1415 +
152.1416 +            if (classes.size() == 0) {
152.1417 +                addSubclasses(name, classes, seenClasses, scannedClasses, directOnly);
152.1418 +            }
152.1419 +        }
152.1420 +
152.1421 +        return classes;
152.1422 +    }
152.1423 +    
152.1424 +    private boolean addSubclasses(String classFqn, Set<IndexedElement> classes, Set<String> seenClasses, Set<String> scannedClasses, boolean directOnly) {
152.1425 +        // Prevent problems with circular includes or redundant includes
152.1426 +        if (scannedClasses.contains(classFqn)) {
152.1427 +            return false;
152.1428 +        }
152.1429 +
152.1430 +        scannedClasses.add(classFqn);
152.1431 +
152.1432 +        String searchField = PythonIndexer.FIELD_EXTENDS_NAME;
152.1433 +
152.1434 +        Set<IndexResult> result = new HashSet<>();
152.1435 +
152.1436 +        String[] terms = { PythonIndexer.FIELD_IN,
152.1437 +                              PythonIndexer.FIELD_EXTENDS_NAME,
152.1438 +                              PythonIndexer.FIELD_CLASS_ATTR_NAME,
152.1439 +                              PythonIndexer.FIELD_CLASS_NAME };
152.1440 +
152.1441 +        search(searchField, classFqn, QuerySupport.Kind.EXACT, result, terms);
152.1442 +
152.1443 +        boolean foundIt = result.size() > 0;
152.1444 +
152.1445 +        // If this is a bogus class entry (no search rsults) don't continue
152.1446 +        if (!foundIt) {
152.1447 +            return foundIt;
152.1448 +        }
152.1449 +
152.1450 +        for (IndexResult map : result) {
152.1451 +            String className = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
152.1452 +            if (className != null && !seenClasses.contains(className)) {
152.1453 +                String url = map.getUrl().toExternalForm();
152.1454 +                String module = map.getValue(PythonIndexer.FIELD_IN);
152.1455 +                IndexedElement clz = new IndexedElement(className, ElementKind.CLASS, url, module, null, null);
152.1456 +                String attrs = map.getValue(PythonIndexer.FIELD_CLASS_ATTR_NAME);
152.1457 +                if (attrs != null) {
152.1458 +                    int flags = IndexedElement.decode(attrs, 0, 0);
152.1459 +                    clz.setFlags(flags);
152.1460 +                }
152.1461 +                classes.add(clz);
152.1462 +
152.1463 +                seenClasses.add(className);
152.1464 +
152.1465 +                if (!directOnly) {
152.1466 +                    addSubclasses(className, classes, seenClasses, scannedClasses, directOnly);
152.1467 +                }
152.1468 +            }
152.1469 +        }
152.1470 +
152.1471 +        return foundIt;
152.1472 +    }
152.1473 +}
   153.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   153.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonIndexSearcher.java	Sun Sep 13 11:47:42 2015 +0200
   153.3 @@ -0,0 +1,252 @@
   153.4 +/*
   153.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   153.6 + *
   153.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   153.8 + *
   153.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  153.10 + * Other names may be trademarks of their respective owners.
  153.11 + *
  153.12 + * The contents of this file are subject to the terms of either the GNU
  153.13 + * General Public License Version 2 only ("GPL") or the Common
  153.14 + * Development and Distribution License("CDDL") (collectively, the
  153.15 + * "License"). You may not use this file except in compliance with the
  153.16 + * License. You can obtain a copy of the License at
  153.17 + * http://www.netbeans.org/cddl-gplv2.html
  153.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  153.19 + * specific language governing permissions and limitations under the
  153.20 + * License.  When distributing the software, include this License Header
  153.21 + * Notice in each file and include the License file at
  153.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  153.23 + * particular file as subject to the "Classpath" exception as provided
  153.24 + * by Oracle in the GPL Version 2 section of the License file that
  153.25 + * accompanied this code. If applicable, add the following below the
  153.26 + * License Header, with the fields enclosed by brackets [] replaced by
  153.27 + * your own identifying information:
  153.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  153.29 + *
  153.30 + * Contributor(s):
  153.31 + *
  153.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  153.33 + */
  153.34 +package org.netbeans.modules.python.source;
  153.35 +
  153.36 +import java.awt.Toolkit;
  153.37 +import java.util.HashSet;
  153.38 +import java.util.Set;
  153.39 +import java.util.logging.Logger;
  153.40 +import javax.swing.Icon;
  153.41 +import org.netbeans.modules.python.source.elements.IndexedElement;
  153.42 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  153.43 +import org.netbeans.api.project.FileOwnerQuery;
  153.44 +import org.netbeans.api.project.Project;
  153.45 +import org.netbeans.api.project.ProjectInformation;
  153.46 +import org.netbeans.api.project.ProjectUtils;
  153.47 +import org.netbeans.modules.csl.api.ElementHandle;
  153.48 +import org.netbeans.modules.csl.api.IndexSearcher;
  153.49 +import org.netbeans.modules.csl.api.IndexSearcher.Descriptor;
  153.50 +import org.netbeans.modules.csl.api.IndexSearcher.Helper;
  153.51 +import org.netbeans.modules.csl.spi.GsfUtilities;
  153.52 +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
  153.53 +import org.openide.filesystems.FileObject;
  153.54 +import org.openide.util.ImageUtilities;
  153.55 +import org.python.antlr.PythonTree;
  153.56 +
  153.57 +/**
  153.58 + *
  153.59 + * @author Tor Norbye
  153.60 + */
  153.61 +public class PythonIndexSearcher implements IndexSearcher {
  153.62 +
  153.63 +    @Override
  153.64 +    public Set<? extends Descriptor> getTypes(Project prjct, String textForQuery, QuerySupport.Kind kind, Helper helper) {
  153.65 +        PythonIndex index = PythonIndex.get(prjct);
  153.66 +        Set<PythonSymbol> result = new HashSet<>();
  153.67 +        Set<? extends IndexedElement> elements;
  153.68 +
  153.69 +        // TODO - do some filtering if you use ./#
  153.70 +        //        int dot = textForQuery.lastIndexOf('.');
  153.71 +        //        if (dot != -1 && (kind == QuerySupport.Kind.PREFIX || kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX)) {
  153.72 +        //            String prefix = textForQuery.substring(dot+1);
  153.73 +        //            String in = textForQuery.substring(0, dot);
  153.74 +
  153.75 +        elements = index.getClasses(textForQuery, kind, null, true);
  153.76 +        for (IndexedElement element : elements) {
  153.77 +            result.add(new PythonSymbol(element, helper));
  153.78 +        }
  153.79 +
  153.80 +        return result;
  153.81 +    }
  153.82 +
  153.83 +    @Override
  153.84 +    public Set<? extends Descriptor> getSymbols(Project prjct, String textForQuery, QuerySupport.Kind kind, Helper helper) {
  153.85 +        PythonIndex index = PythonIndex.get(prjct);
  153.86 +        Set<PythonSymbol> result = new HashSet<>();
  153.87 +        Set<? extends IndexedElement> elements;
  153.88 +
  153.89 +        // TODO - do some filtering if you use ./#
  153.90 +        //        int dot = textForQuery.lastIndexOf('.');
  153.91 +        //        if (dot != -1 && (kind == QuerySupport.Kind.PREFIX || kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX)) {
  153.92 +        //            String prefix = textForQuery.substring(dot+1);
  153.93 +        //            String in = textForQuery.substring(0, dot);
  153.94 +
  153.95 +        elements = index.getAllMembers(textForQuery, kind, null, true);
  153.96 +        for (IndexedElement element : elements) {
  153.97 +            result.add(new PythonSymbol(element, helper));
  153.98 +        }
  153.99 +        elements = index.getClasses(textForQuery, kind, null, true);
 153.100 +        for (IndexedElement element : elements) {
 153.101 +            result.add(new PythonSymbol(element, helper));
 153.102 +        }
 153.103 +        elements = index.getModules(textForQuery, kind);
 153.104 +        for (IndexedElement element : elements) {
 153.105 +            result.add(new PythonSymbol(element, helper));
 153.106 +        }
 153.107 +
 153.108 +        return result;
 153.109 +    }
 153.110 +
 153.111 +    private class PythonSymbol extends Descriptor {
 153.112 +        private final IndexedElement element;
 153.113 +        private String projectName;
 153.114 +        private Icon projectIcon;
 153.115 +        private final Helper helper;
 153.116 +        private boolean isLibrary;
 153.117 +        private static final String ICON_PATH = "org/netbeans/modules/python/editor/resources/pyc_16.png"; //NOI18N
 153.118 +
 153.119 +        public PythonSymbol(IndexedElement element, Helper helper) {
 153.120 +            this.element = element;
 153.121 +            this.helper = helper;
 153.122 +        }
 153.123 +
 153.124 +        @Override
 153.125 +        public Icon getIcon() {
 153.126 +            if (projectName == null) {
 153.127 +                initProjectInfo();
 153.128 +            }
 153.129 +            //if (isLibrary) {
 153.130 +            //    return new ImageIcon(org.openide.util.ImageUtilities.loadImage(PYTHON_KEYWORD));
 153.131 +            //}
 153.132 +            return helper.getIcon(element);
 153.133 +        }
 153.134 +
 153.135 +        @Override
 153.136 +        public String getTypeName() {
 153.137 +            return element.getName();
 153.138 +        }
 153.139 +
 153.140 +        @Override
 153.141 +        public String getProjectName() {
 153.142 +            if (projectName == null) {
 153.143 +                initProjectInfo();
 153.144 +            }
 153.145 +            return projectName;
 153.146 +        }
 153.147 +
 153.148 +        private void initProjectInfo() {
 153.149 +            FileObject fo = element.getFileObject();
 153.150 +            if (fo != null) {
 153.151 +//                File f = FileUtil.toFile(fo);
 153.152 +                Project p = FileOwnerQuery.getOwner(fo);
 153.153 +                if (p != null) {
 153.154 +//                    JsPlatform platform = JsPlatform.platformFor(p);
 153.155 +//                    if (platform != null) {
 153.156 +//                        String lib = platform.getLib();
 153.157 +//                        if (lib != null && f.getPath().startsWith(lib)) {
 153.158 +//                            projectName = "Js Library";
 153.159 +//                            isLibrary = true;
 153.160 +//                        }
 153.161 +//                    } else {
 153.162 +                    ProjectInformation pi = ProjectUtils.getInformation(p);
 153.163 +                    projectName = pi.getDisplayName();
 153.164 +                    projectIcon = pi.getIcon();
 153.165 +//                    }
 153.166 +                }
 153.167 +            } else {
 153.168 +                isLibrary = true;
 153.169 +                Logger.getLogger(PythonIndexSearcher.class.getName()).fine("No fileobject for " + element.toString() + " with fileurl=" + element.getFilenameUrl());
 153.170 +            }
 153.171 +            if (projectName == null) {
 153.172 +                projectName = "";
 153.173 +            }
 153.174 +        }
 153.175 +
 153.176 +        @Override
 153.177 +        public Icon getProjectIcon() {
 153.178 +            if (projectName == null) {
 153.179 +                initProjectInfo();
 153.180 +            }
 153.181 +            if (isLibrary) {
 153.182 +                return ImageUtilities.loadImageIcon(ICON_PATH, false);
 153.183 +            }
 153.184 +            return projectIcon;
 153.185 +        }
 153.186 +
 153.187 +        @Override
 153.188 +        public FileObject getFileObject() {
 153.189 +            return element.getFileObject();
 153.190 +        }
 153.191 +
 153.192 +        @Override
 153.193 +        public void open() {
 153.194 +            PythonParserResult[] parserResultRet = new PythonParserResult[1];
 153.195 +            PythonTree node = PythonAstUtils.getForeignNode(element, parserResultRet);
 153.196 +
 153.197 +            if (node != null) {
 153.198 +                int astOffset = PythonAstUtils.getRange(node).getStart();
 153.199 +                int lexOffset = PythonLexerUtils.getLexerOffset(parserResultRet[0], astOffset);
 153.200 +                if (lexOffset == -1) {
 153.201 +                    lexOffset = 0;
 153.202 +                }
 153.203 +                GsfUtilities.open(element.getFileObject(), lexOffset, element.getName());
 153.204 +                return;
 153.205 +            }
 153.206 +
 153.207 +            FileObject fileObject = element.getFileObject();
 153.208 +            if (fileObject == null) {
 153.209 +                // This should no longer be needed - we perform auto deletion in GSF
 153.210 +                Toolkit.getDefaultToolkit().beep();
 153.211 +                return;
 153.212 +            }
 153.213 +
 153.214 +            helper.open(fileObject, element);
 153.215 +        }
 153.216 +
 153.217 +        @Override
 153.218 +        public String getContextName() {
 153.219 +            // XXX This is lame - move formatting logic to the goto action!
 153.220 +//            StringBuilder sb = new StringBuilder();
 153.221 +//            String require = element.getRequire();
 153.222 +//            String fqn = element.getFqn();
 153.223 +            String fqn = element.getIn() != null ? element.getIn() + "." + element.getName() : element.getName();
 153.224 +            if (element.getName().equals(fqn)) {
 153.225 +                fqn = null;
 153.226 +                String url = element.getFilenameUrl();
 153.227 +                if (url != null) {
 153.228 +                    return url.substring(url.lastIndexOf('/') + 1);
 153.229 +                }
 153.230 +            }
 153.231 +
 153.232 +            return fqn;
 153.233 +        }
 153.234 +
 153.235 +        @Override
 153.236 +        public ElementHandle getElement() {
 153.237 +            return element;
 153.238 +        }
 153.239 +
 153.240 +        @Override
 153.241 +        public int getOffset() {
 153.242 +            throw new UnsupportedOperationException("Not supported yet.");
 153.243 +        }
 153.244 +
 153.245 +        @Override
 153.246 +        public String getSimpleName() {
 153.247 +            return element.getName();
 153.248 +        }
 153.249 +
 153.250 +        @Override
 153.251 +        public String getOuterName() {
 153.252 +            return null;
 153.253 +        }
 153.254 +    }
 153.255 +}
   154.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   154.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonIndexer.java	Sun Sep 13 11:47:42 2015 +0200
   154.3 @@ -0,0 +1,1399 @@
   154.4 +/*
   154.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   154.6 + *
   154.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   154.8 + *
   154.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  154.10 + * Other names may be trademarks of their respective owners.
  154.11 + *
  154.12 + * The contents of this file are subject to the terms of either the GNU
  154.13 + * General Public License Version 2 only ("GPL") or the Common
  154.14 + * Development and Distribution License("CDDL") (collectively, the
  154.15 + * "License"). You may not use this file except in compliance with the
  154.16 + * License. You can obtain a copy of the License at
  154.17 + * http://www.netbeans.org/cddl-gplv2.html
  154.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  154.19 + * specific language governing permissions and limitations under the
  154.20 + * License.  When distributing the software, include this License Header
  154.21 + * Notice in each file and include the License file at
  154.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  154.23 + * particular file as subject to the "Classpath" exception as provided
  154.24 + * by Oracle in the GPL Version 2 section of the License file that
  154.25 + * accompanied this code. If applicable, add the following below the
  154.26 + * License Header, with the fields enclosed by brackets [] replaced by
  154.27 + * your own identifying information:
  154.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  154.29 + *
  154.30 + * Contributor(s):
  154.31 + *
  154.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  154.33 + */
  154.34 +package org.netbeans.modules.python.source;
  154.35 +
  154.36 +import java.io.File;
  154.37 +import java.io.IOException;
  154.38 +import java.net.MalformedURLException;
  154.39 +import java.net.URL;
  154.40 +import java.util.ArrayList;
  154.41 +import java.util.Collections;
  154.42 +import java.util.HashMap;
  154.43 +import java.util.List;
  154.44 +import java.util.Map;
  154.45 +import java.util.logging.Level;
  154.46 +import java.util.logging.Logger;
  154.47 +import java.util.regex.Matcher;
  154.48 +import java.util.regex.Pattern;
  154.49 +import javax.swing.text.BadLocationException;
  154.50 +import org.netbeans.editor.BaseDocument;
  154.51 +import org.netbeans.modules.csl.spi.GsfUtilities;
  154.52 +import org.netbeans.modules.csl.spi.ParserResult;
  154.53 +import org.netbeans.modules.parsing.api.Snapshot;
  154.54 +import org.netbeans.modules.parsing.spi.Parser;
  154.55 +import org.netbeans.modules.parsing.spi.indexing.Context;
  154.56 +import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexer;
  154.57 +import org.netbeans.modules.parsing.spi.indexing.Indexable;
  154.58 +import org.netbeans.modules.parsing.spi.indexing.support.IndexDocument;
  154.59 +import org.netbeans.modules.parsing.spi.indexing.support.IndexingSupport;
  154.60 +import org.netbeans.modules.python.api.PythonPlatform;
  154.61 +import org.netbeans.modules.python.api.PythonPlatformManager;
  154.62 +import org.netbeans.modules.python.source.elements.IndexedElement;
  154.63 +import org.netbeans.modules.python.source.scopes.ScopeConstants;
  154.64 +import org.netbeans.modules.python.source.scopes.ScopeInfo;
  154.65 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  154.66 +import org.netbeans.modules.python.source.scopes.SymInfo;
  154.67 +import org.netbeans.modules.python.source.queries.DeprecationQuery;
  154.68 +import org.openide.filesystems.FileObject;
  154.69 +import org.openide.filesystems.FileUtil;
  154.70 +import org.openide.filesystems.URLMapper;
  154.71 +import org.openide.util.Exceptions;
  154.72 +import org.python.antlr.PythonTree;
  154.73 +import org.python.antlr.ast.ClassDef;
  154.74 +import org.python.antlr.ast.FunctionDef;
  154.75 +import org.python.antlr.ast.Module;
  154.76 +import org.python.antlr.ast.Name;
  154.77 +import org.python.antlr.base.expr;
  154.78 +
  154.79 +/**
  154.80 + *
  154.81 + * @todo Store information about all symbols exported by a module.
  154.82 + *  I can use that to provide "unused import" help.
  154.83 + * @todo Clean this stuff up: store data, functions, etc.
  154.84 + * @todo Improve detection of builtins. Perhaps run from within Python,
  154.85 + *   something like this:
  154.86 +>>> dir(__builtins__)
  154.87 +['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__', '__name__', 'abs', 'all', 'any', 'apply', 'basestring', 'bool', 'buffer', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter', 'float', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'min', 'object', 'oct', 'open', 'ord', 'pow', 'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
  154.88 + *
  154.89 + * My code for scanning for functions has to be smarter:
  154.90 +.. function:: ljust(s, width)
  154.91 +rjust(s, width)
  154.92 +center(s, width)
  154.93 + * Here I need to pick up all 3 signatures!
  154.94 + * @author Tor Norbye
  154.95 + */
  154.96 +public class PythonIndexer extends EmbeddingIndexer {
  154.97 +    public static final String NAME = "PythonIndexer";
  154.98 +    public static final int VERSION = 1;
  154.99 +    public static boolean PREINDEXING = Boolean.getBoolean("gsf.preindexing"); // NOI18N
 154.100 +    public static final String FIELD_MEMBER = "member"; //NOI18N
 154.101 +    public static final String FIELD_MODULE_NAME = "module"; //NOI18N
 154.102 +    public static final String FIELD_MODULE_ATTR_NAME = "modattrs"; //NOI18N
 154.103 +    public static final String FIELD_CLASS_ATTR_NAME = "clzattrs"; //NOI18N
 154.104 +    public static final String FIELD_EXTENDS_NAME = "extends"; //NOI18N
 154.105 +    public static final String FIELD_ITEM = "item"; //NOI18N
 154.106 +    public static final String FIELD_IN = "in"; //NOI18N
 154.107 +    public static final String FIELD_CLASS_NAME = "class"; //NOI18N
 154.108 +    public static final String FIELD_CASE_INSENSITIVE_CLASS_NAME = "class-ig"; //NOI18N
 154.109 +    private FileObject prevParent;
 154.110 +    private boolean prevResult;
 154.111 +
 154.112 +    public static boolean isIndexable(Indexable indexable, Snapshot snapshot) {
 154.113 +        FileObject fo = snapshot.getSource().getFileObject();
 154.114 +        String extension = fo.getExt();
 154.115 +        if ("py".equals(extension)) { // NOI18N
 154.116 +            return true;
 154.117 +        }
 154.118 +
 154.119 +        if ("rst".equals(extension)) { // NOI18N
 154.120 +            // Index restructured text if it looks like it contains Python library
 154.121 +            // definitions
 154.122 +            return true;
 154.123 +        }
 154.124 +
 154.125 +        if ("egg".equals(extension)) { // NOI18N
 154.126 +            return true;
 154.127 +        }
 154.128 +
 154.129 +        return false;
 154.130 +    }
 154.131 +
 154.132 +    
 154.133 +    public boolean isIndexable(Snapshot file) {
 154.134 +        FileObject fo = file.getSource().getFileObject();
 154.135 +        String extension = fo.getExt();
 154.136 +        if ("py".equals(extension)) { // NOI18N
 154.137 +
 154.138 +            // Skip "test" folders under lib... Lots of weird files there
 154.139 +            // and we don't want to pollute the index with them
 154.140 +            FileObject parent = fo.getParent();
 154.141 +
 154.142 +            if (parent != null && parent.getName().equals("test")) { // NOI18N
 154.143 +                // Make sure it's really a lib folder, we want to include the
 154.144 +                // user's files
 154.145 +
 154.146 +                // Avoid double-indexing files that have multiple versions - e.g. foo.js and foo-min.js
 154.147 +                // or foo.uncompressed
 154.148 +                FileObject parentFo = fo.getParent();
 154.149 +                if (prevParent == parentFo) {
 154.150 +                    return prevResult;
 154.151 +                }
 154.152 +                prevResult = true;
 154.153 +                prevParent = parentFo;
 154.154 +                PythonPlatformManager manager = PythonPlatformManager.getInstance();
 154.155 +                Platforms:
 154.156 +                for (String name : manager.getPlatformList()) {
 154.157 +                    PythonPlatform platform = manager.getPlatform(name);
 154.158 +                    if (platform != null) {
 154.159 +                        for (FileObject root : platform.getLibraryRoots()) {
 154.160 +                            if (FileUtil.isParentOf(root, parentFo)) {
 154.161 +                                prevResult = false;
 154.162 +                                break Platforms;
 154.163 +                            }
 154.164 +                        }
 154.165 +                    }
 154.166 +                }
 154.167 +            }
 154.168 +
 154.169 +            return true;
 154.170 +        }
 154.171 +
 154.172 +        if ("rst".equals(extension)) { // NOI18N
 154.173 +            // Index restructured text if it looks like it contains Python library
 154.174 +            // definitions
 154.175 +            return true;
 154.176 +        }
 154.177 +
 154.178 +        if ("egg".equals(extension)) { // NOI18N
 154.179 +            return true;
 154.180 +        }
 154.181 +
 154.182 +        return false;
 154.183 +    }
 154.184 +
 154.185 +    @Override
 154.186 +    protected void index(Indexable indexable, Parser.Result result, Context context) {
 154.187 +        PythonParserResult parseResult = (PythonParserResult)result;
 154.188 +        if (parseResult == null) {
 154.189 +            return;
 154.190 +        }
 154.191 +        
 154.192 +        IndexingSupport support;
 154.193 +        try {
 154.194 +            support = IndexingSupport.getInstance(context);
 154.195 +        } catch (IOException ioe) {
 154.196 +            LOG.log(Level.WARNING, null, ioe);
 154.197 +            return;
 154.198 +        }
 154.199 +        
 154.200 +        support.removeDocuments(indexable);
 154.201 +        
 154.202 +        FileObject fileObject = result.getSnapshot().getSource().getFileObject();
 154.203 +        String extension = fileObject.getNameExt();
 154.204 +
 154.205 +        if (extension.endsWith(".rst")) { // NOI18N
 154.206 +            scanRst(fileObject, indexable, support, null);
 154.207 +        } else if (extension.endsWith(".egg")) { // NOI18N
 154.208 +            scanEgg(fileObject, indexable, parseResult, support);
 154.209 +        } else {
 154.210 +            // Normal python file
 154.211 +            new IndexTask(parseResult, support).scan();
 154.212 +        }
 154.213 +    }
 154.214 +    private static final Logger LOG = Logger.getLogger(PythonIndexer.class.getName());
 154.215 +
 154.216 +    public boolean acceptQueryPath(String url) {
 154.217 +        return !url.contains("jsstubs"); // NOI18N
 154.218 +    }
 154.219 +
 154.220 +    public String getPersistentUrl(File file) {
 154.221 +        String url;
 154.222 +        try {
 154.223 +            url = file.toURI().toURL().toExternalForm();
 154.224 +
 154.225 +            // Make relative URLs for urls in the libraries
 154.226 +            return PythonIndex.getPreindexUrl(url);
 154.227 +        } catch (MalformedURLException ex) {
 154.228 +            Exceptions.printStackTrace(ex);
 154.229 +            return file.getPath();
 154.230 +        }
 154.231 +    }
 154.232 +
 154.233 +    public String getIndexVersion() {
 154.234 +        return "0.123"; // NOI18N
 154.235 +    }
 154.236 +
 154.237 +    public String getIndexerName() {
 154.238 +        return "python"; // NOI18N
 154.239 +    }
 154.240 +
 154.241 +    public FileObject getPreindexedDb() {
 154.242 +        return null;
 154.243 +    }
 154.244 +
 154.245 +    private static void appendFlags(StringBuilder sb, char c, SymInfo sym, int flags) {
 154.246 +        sb.append(';');
 154.247 +        sb.append(c);
 154.248 +        sb.append(';');
 154.249 +
 154.250 +        if (sym.isPrivate()) {
 154.251 +            flags |= IndexedElement.PRIVATE;
 154.252 +        }
 154.253 +        if (c == 'c') {
 154.254 +            flags |= IndexedElement.CONSTRUCTOR;
 154.255 +        }
 154.256 +
 154.257 +        sb.append(IndexedElement.encode(flags));
 154.258 +        sb.append(';');
 154.259 +    }
 154.260 +    private static final int DEFAULT_DOC_SIZE = 40; // TODO Measure
 154.261 +
 154.262 +    private static class IndexTask {
 154.263 +        private PythonParserResult result;
 154.264 +        private FileObject file;
 154.265 +        private IndexingSupport support;
 154.266 +        private List<IndexDocument> documents = new ArrayList<>();
 154.267 +        private String url;
 154.268 +        private String module;
 154.269 +        private SymbolTable symbolTable;
 154.270 +        private String overrideUrl;
 154.271 +
 154.272 +        private IndexTask(PythonParserResult result, IndexingSupport support) {
 154.273 +            this.result = result;
 154.274 +            this.file = result.getSnapshot().getSource().getFileObject();
 154.275 +            this.support = support;
 154.276 +
 154.277 +            module = PythonUtils.getModuleName(file);
 154.278 +            //PythonTree root = PythonAstUtils.getRoot(result);
 154.279 +            //if (root instanceof Module) {
 154.280 +            //    Str moduleDoc = PythonAstUtils.getDocumentationNode(root);
 154.281 +            //    if (moduleDoc != null) {
 154.282 +            //        moduleAttributes = "d(" + moduleDoc.getCharStartIndex() + ")";
 154.283 +            //    }
 154.284 +            //}
 154.285 +        }
 154.286 +
 154.287 +        private IndexTask(PythonParserResult result, IndexingSupport support, String overrideUrl) {
 154.288 +            this(result, support);
 154.289 +            this.overrideUrl = overrideUrl;
 154.290 +        }
 154.291 +
 154.292 +        public List<IndexDocument> scan() {
 154.293 +            url = file.toURL().toExternalForm();
 154.294 +            // Make relative URLs for urls in the libraries
 154.295 +            url = PythonIndex.getPreindexUrl(url);
 154.296 +
 154.297 +            IndexDocument doc = createDocument();
 154.298 +            doc.addPair(FIELD_MODULE_NAME, module, true, true);
 154.299 +
 154.300 +            String moduleAttrs = null;
 154.301 +            if (url.startsWith(PythonIndex.CLUSTER_URL) || url.startsWith(PythonIndex.PYTHONHOME_URL)) {
 154.302 +                moduleAttrs = "S"; // NOI18N
 154.303 +            } else if (PREINDEXING) {
 154.304 +                String prj = System.getProperty("gsf.preindexing.projectpath");
 154.305 +                if (prj != null && !url.contains(prj)) {
 154.306 +                    System.err.println("WARNING -- not marking url " + url + " from " + file + " as a system library!");
 154.307 +                }
 154.308 +            }
 154.309 +            if (DeprecationQuery.isDeprecatedModule(module)) {
 154.310 +                if (moduleAttrs == null) {
 154.311 +                    moduleAttrs = "D"; // NOI18N
 154.312 +                } else {
 154.313 +                    moduleAttrs += "D"; // NOI18N
 154.314 +                }
 154.315 +            }
 154.316 +            if (moduleAttrs != null) {
 154.317 +                doc.addPair(FIELD_MODULE_ATTR_NAME, moduleAttrs, false, true);
 154.318 +            }
 154.319 +
 154.320 +            PythonTree root = PythonAstUtils.getRoot(result);
 154.321 +            if (root == null) {
 154.322 +                return documents;
 154.323 +            }
 154.324 +            if (!(root instanceof Module)) {
 154.325 +                // Unexpected... http://netbeans.org/bugzilla/show_bug.cgi?id=165756
 154.326 +                // Maybe some kind of top level error node?
 154.327 +                System.err.println("WARNING - top level AST node type was " + root + " of type " + root.getClass().getName());
 154.328 +                return documents;
 154.329 +            }
 154.330 +            symbolTable = result.getSymbolTable();
 154.331 +            ScopeInfo scopeInfo = symbolTable.getScopeInfo(root);
 154.332 +            for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 154.333 +                String name = entry.getKey();
 154.334 +                SymInfo sym = entry.getValue();
 154.335 +
 154.336 +                if (sym.isClass()) {
 154.337 +                    StringBuilder sig = new StringBuilder();
 154.338 +                    sig.append(name);
 154.339 +                    appendFlags(sig, 'C', sym, 0);
 154.340 +                    doc.addPair(FIELD_ITEM, sig.toString(), true, true);
 154.341 +
 154.342 +                    if (sym.node instanceof ClassDef) {
 154.343 +                        assert sym.node instanceof ClassDef : sym.node;
 154.344 +                        indexClass(name, sym, (ClassDef)sym.node);
 154.345 +                    } else {
 154.346 +                        // Could be a symbol defined both as a class and a function
 154.347 +                        // (conditionally) such as _Environ in minicompat.py,
 154.348 +                        // and another trigger in socket.py.
 154.349 +                    }
 154.350 +                } else if (sym.isFunction()) {
 154.351 +                    if (sym.node instanceof Name) {
 154.352 +                        assert false : "Unexpected non-function node, " + ((Name)sym.node).getInternalId() + " - from symbol " + name + " in " + file + " with sym=" + sym;
 154.353 +                    }
 154.354 +                    assert sym.node instanceof FunctionDef : sym.node;
 154.355 +                    FunctionDef def = (FunctionDef)sym.node;
 154.356 +                    String sig = computeFunctionSig(name, def, sym);
 154.357 +                    doc.addPair(FIELD_ITEM, sig, true, true);
 154.358 +                } else if (sym.isImported()) {
 154.359 +                    if (!"*".equals(name)) { // NOI18N
 154.360 +                        StringBuilder sig = new StringBuilder();
 154.361 +                        sig.append(name);
 154.362 +                        appendFlags(sig, 'I', sym, 0);
 154.363 +                        doc.addPair(FIELD_ITEM, sig.toString(), true, true);
 154.364 +                    }
 154.365 +                } else if (sym.isGeneratorExp()) {
 154.366 +                    StringBuilder sig = new StringBuilder();
 154.367 +                    sig.append(name);
 154.368 +                    appendFlags(sig, 'G', sym, 0);
 154.369 +                    doc.addPair(FIELD_ITEM, sig.toString(), true, true);
 154.370 +                } else if (sym.isData()) {
 154.371 +                    StringBuilder sig = new StringBuilder();
 154.372 +                    sig.append(name);
 154.373 +                    appendFlags(sig, 'D', sym, 0);
 154.374 +                    doc.addPair(FIELD_ITEM, sig.toString(), true, true);
 154.375 +                } else {
 154.376 +                    // XXX what the heck is this??
 154.377 +                }
 154.378 +            }
 154.379 +
 154.380 +            return documents;
 154.381 +        }
 154.382 +
 154.383 +        private void indexClass(String className, SymInfo classSym, ClassDef clz) {
 154.384 +            IndexDocument classDocument = createDocument();
 154.385 +            classDocument.addPair(FIELD_IN, module, true, true);
 154.386 +
 154.387 +            // Superclass
 154.388 +            List<expr> bases = clz.getInternalBases();
 154.389 +            if (bases != null) {
 154.390 +                for (expr base : bases) {
 154.391 +                    String extendsName = PythonAstUtils.getExprName(base);
 154.392 +                    if (extendsName != null) {
 154.393 +                        classDocument.addPair(FIELD_EXTENDS_NAME, extendsName, true, true);
 154.394 +                    }
 154.395 +                }
 154.396 +            }
 154.397 +
 154.398 +            classDocument.addPair(FIELD_CLASS_NAME, className, true, true);
 154.399 +
 154.400 +            if (classSym.isPrivate()) {
 154.401 +                // TODO - store Documented, Deprecated, DocOnly, etc.
 154.402 +                classDocument.addPair(FIELD_CLASS_ATTR_NAME, IndexedElement.encode(IndexedElement.PRIVATE), false, true);
 154.403 +            }
 154.404 +            classDocument.addPair(FIELD_CASE_INSENSITIVE_CLASS_NAME, className.toLowerCase(), true, true);
 154.405 +
 154.406 +            //Str doc = PythonAstUtils.getDocumentationNode(clz);
 154.407 +            //if (doc != null) {
 154.408 +            //    StringBuilder sb = new StringBuilder();
 154.409 +            //    sb.append("d("); // NOI18N
 154.410 +            //    sb.append(doc.getCharStartIndex());
 154.411 +            //    sb.append(")"); // NOI18N
 154.412 +            //    classDocument.addPair(FIELD_CLASS_ATTRS, sb.toString(), false);
 154.413 +            //}
 154.414 +
 154.415 +            ScopeInfo scopeInfo = symbolTable.getScopeInfo(clz);
 154.416 +            for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 154.417 +                String name = entry.getKey();
 154.418 +                SymInfo sym = entry.getValue();
 154.419 +
 154.420 +//                int flags = sym.flags;
 154.421 +//                assert !sym.isClass() : "found a class " + name + " of type " + sym.dumpFlags(scopeInfo) + " within class " + className + " in module " + module;
 154.422 +//                if (!(sym.isFunction() || sym.isMember() || sym.isData())) {
 154.423 +//                }
 154.424 +//                assert sym.isFunction() || sym.isMember() || sym.isData() : name + ";" + sym.toString();
 154.425 +
 154.426 +                if (sym.isClass()) {
 154.427 +                    // Triggers in httplib _socket_close inside FakeSocket
 154.428 +                    StringBuilder sig = new StringBuilder();
 154.429 +                    sig.append(name);
 154.430 +                    appendFlags(sig, 'C', sym, 0);
 154.431 +                    classDocument.addPair(FIELD_ITEM, sig.toString(), true, true);
 154.432 +
 154.433 +                } else if (sym.isFunction() && sym.node instanceof FunctionDef) {
 154.434 +                    if (sym.node instanceof Name) {
 154.435 +                        assert false : "Unexpected non-function node, " + ((Name)sym.node).getInternalId() + " - from symbol " + name + " in " + file + " with sym=" + sym;
 154.436 +                    }
 154.437 +                    FunctionDef def = (FunctionDef)sym.node;
 154.438 +                    String sig = computeFunctionSig(name, def, sym);
 154.439 +                    classDocument.addPair(FIELD_MEMBER, sig, true, true);
 154.440 +                } else if (sym.isData()) {
 154.441 +                    StringBuilder sig = new StringBuilder();
 154.442 +                    sig.append(name);
 154.443 +                    appendFlags(sig, 'D', sym, 0);
 154.444 +                    classDocument.addPair(FIELD_MEMBER, sig.toString(), true, true);
 154.445 +                } else if (sym.isMember()) {
 154.446 +                    StringBuilder sig = new StringBuilder();
 154.447 +                    sig.append(name);
 154.448 +                    appendFlags(sig, 'A', sym, 0);
 154.449 +                    classDocument.addPair(FIELD_MEMBER, sig.toString(), true, true);
 154.450 +                } else if (!sym.isBound()) {
 154.451 +                    continue;
 154.452 +                } else {
 154.453 +                    // XXX what the heck is this??
 154.454 +                    assert false : className + "::" + name + " : " + sym.dumpFlags(scopeInfo);
 154.455 +                }
 154.456 +            }
 154.457 +
 154.458 +            if (scopeInfo.attributes.size() > 0) {
 154.459 +                for (Map.Entry<String, SymInfo> entry : scopeInfo.attributes.entrySet()) {
 154.460 +                    String name = entry.getKey();
 154.461 +                    SymInfo sym = entry.getValue();
 154.462 +
 154.463 +                    if (sym.isClass()) {
 154.464 +                        // Triggers in httplib _socket_close inside FakeSocket
 154.465 +                        StringBuilder sig = new StringBuilder();
 154.466 +                        sig.append(name);
 154.467 +                        appendFlags(sig, 'C', sym, 0);
 154.468 +                        classDocument.addPair(FIELD_ITEM, sig.toString(), true, true);
 154.469 +
 154.470 +                    } else if (sym.isFunction() && sym.node instanceof FunctionDef) {
 154.471 +                        if (sym.node instanceof Name) {
 154.472 +                            assert false : "Unexpected non-function node, " + ((Name)sym.node).getInternalId() + " - from symbol " + name + " in " + file + " with sym=" + sym;
 154.473 +                        }
 154.474 +                        FunctionDef def = (FunctionDef)sym.node;
 154.475 +                        String sig = computeFunctionSig(name, def, sym);
 154.476 +                        classDocument.addPair(FIELD_MEMBER, sig, true, true);
 154.477 +                    } else if (sym.isData()) {
 154.478 +                        StringBuilder sig = new StringBuilder();
 154.479 +                        sig.append(name);
 154.480 +                        appendFlags(sig, 'D', sym, 0);
 154.481 +                        classDocument.addPair(FIELD_MEMBER, sig.toString(), true, true);
 154.482 +                    } else if (sym.isMember()) {
 154.483 +                        StringBuilder sig = new StringBuilder();
 154.484 +                        sig.append(name);
 154.485 +                        appendFlags(sig, 'A', sym, 0);
 154.486 +                        classDocument.addPair(FIELD_MEMBER, sig.toString(), true, true);
 154.487 +                    } else if (!sym.isBound()) {
 154.488 +                        continue;
 154.489 +                    } else {
 154.490 +                        // XXX what the heck is this??
 154.491 +                        assert false : className + "::" + name + " : " + sym.dumpFlags(scopeInfo);
 154.492 +                    }
 154.493 +                }
 154.494 +            }
 154.495 +        }
 154.496 +
 154.497 +
 154.498 +// TODO - what about nested functions?
 154.499 +        private IndexDocument createDocument() {
 154.500 +            IndexDocument doc = support.createDocument(file);
 154.501 +            documents.add(doc);
 154.502 +
 154.503 +            return doc;
 154.504 +        }
 154.505 +    }
 154.506 +
 154.507 +    public static String computeClassSig(ClassDef def, SymInfo sym) {
 154.508 +        StringBuilder sig = new StringBuilder();
 154.509 +        sig.append(def.getInternalName());
 154.510 +        appendFlags(sig, 'C', sym, 0);
 154.511 +
 154.512 +        return sig.toString();
 154.513 +    }
 154.514 +
 154.515 +    public static String computeFunctionSig(String name, FunctionDef def, SymInfo sym) {
 154.516 +        StringBuilder sb = new StringBuilder();
 154.517 +        sb.append(name);
 154.518 +        char type;
 154.519 +        int flags = 0;
 154.520 +        if ("__init__".equals(name)) { // NOI18N
 154.521 +            type = 'c';
 154.522 +        } else {
 154.523 +            type = 'F';
 154.524 +
 154.525 +            List<expr> decorators = def.getInternalDecorator_list();
 154.526 +            if (decorators != null && decorators.size() > 0) {
 154.527 +                for (expr decorator : decorators) {
 154.528 +                    String decoratorName = PythonAstUtils.getExprName(decorator);
 154.529 +                    if ("property".equals(decoratorName)) { // NOI18N
 154.530 +                        type = 'A';
 154.531 +                    } else if ("classmethod".equals(decoratorName)) { // NOI18N
 154.532 +                        // Classmethods seem to be used mostly for constructors/inherited factories
 154.533 +                        type = 'c';
 154.534 +                        flags |= IndexedElement.CONSTRUCTOR | IndexedElement.STATIC;
 154.535 +                    } else if ("staticmethod".equals(decoratorName)) { // NOI18N
 154.536 +                        flags |= IndexedElement.STATIC;
 154.537 +                    }
 154.538 +                }
 154.539 +            }
 154.540 +        }
 154.541 +        appendFlags(sb, type, sym, flags);
 154.542 +
 154.543 +        List<String> params = PythonAstUtils.getParameters(def);
 154.544 +        boolean first = true;
 154.545 +        for (String param : params) {
 154.546 +            if (first) {
 154.547 +                first = false;
 154.548 +            } else {
 154.549 +                sb.append(',');
 154.550 +            }
 154.551 +            sb.append(param);
 154.552 +        }
 154.553 +        sb.append(';');
 154.554 +        String sig = sb.toString();
 154.555 +        return sig;
 154.556 +    }
 154.557 +
 154.558 +    private String cleanupSignature(String signature) {
 154.559 +        // Clean up signatures - remove [optional] areas, deal
 154.560 +        //   with arg=Default.Value parameters,
 154.561 +        //   or "literal" or (lit,er,al) default values.
 154.562 +        // See unit tests for details.
 154.563 +        boolean lastWasComma = false;
 154.564 +        StringBuilder sb = new StringBuilder();
 154.565 +        Loop:
 154.566 +        for (int i = 0, n = signature.length(); i < n; i++) {
 154.567 +            char c = signature.charAt(i);
 154.568 +            switch (c) {
 154.569 +            case ' ':
 154.570 +            case '[':
 154.571 +            case ']':
 154.572 +            case '\'':
 154.573 +            case '"':
 154.574 +            case '.':
 154.575 +                continue Loop;
 154.576 +            case '=': {
 154.577 +                int level = 0;
 154.578 +                for (i++; i < n; i++) {
 154.579 +                    c = signature.charAt(i);
 154.580 +                    if (c == '(') {
 154.581 +                        level++;
 154.582 +                    } else if (c == ')') {
 154.583 +                        if (level == 0) {
 154.584 +                            break;
 154.585 +                        }
 154.586 +                        level--;
 154.587 +                    }
 154.588 +                    if (c == ',' && level == 0) {
 154.589 +                        break;
 154.590 +                    }
 154.591 +                }
 154.592 +                i--; // compensate for loop-increment
 154.593 +                continue Loop;
 154.594 +            }
 154.595 +            case ')':
 154.596 +                if (lastWasComma) {
 154.597 +                    sb.setLength(sb.length() - 1);
 154.598 +                    lastWasComma = false;
 154.599 +                }
 154.600 +                break;
 154.601 +            case ',':
 154.602 +                if (lastWasComma) {
 154.603 +                    continue Loop;
 154.604 +                }
 154.605 +                lastWasComma = true;
 154.606 +                break;
 154.607 +            default:
 154.608 +                lastWasComma = false;
 154.609 +            }
 154.610 +            sb.append(c);
 154.611 +        }
 154.612 +
 154.613 +        return sb.toString();
 154.614 +    }
 154.615 +
 154.616 +    /**
 154.617 +     * Determine if the definition beginning on lines[lineno] is deprecated.
 154.618 +     */
 154.619 +    private boolean isDeprecated(String[] lines, int lineno) {
 154.620 +        int firstIndent = RstFormatter.getIndentation(lines[lineno], 0);
 154.621 +        for (int i = lineno + 1; i < lines.length; i++) {
 154.622 +            String line = lines[i];
 154.623 +            int indent = RstFormatter.getIndentation(line, 0);
 154.624 +            if (indent == -1) { // empty line
 154.625 +                continue;
 154.626 +            }
 154.627 +            if (line.contains(":deprecated:") || line.contains(".. deprecated::")) { // NOI18N
 154.628 +                return true;
 154.629 +            }
 154.630 +            // Note - we checked for ::deprecated BEFORE bailing on the next
 154.631 +            // same-indent line, because in some cases, these appear on the same
 154.632 +            // level as the deprecated element (for exampe, modules)
 154.633 +            if (indent <= firstIndent) {
 154.634 +                return false;
 154.635 +            }
 154.636 +
 154.637 +            // For classes we can have embedded definitions of functions/data/methods --
 154.638 +            // a deprecated note for these should not be considered a deprecation of
 154.639 +            // the whole class! See the unit test for bz2.zip for example.
 154.640 +            if (line.startsWith(".. attribute::", indent) || // NOI18N
 154.641 +                    line.startsWith(".. data::", indent) || // NOI18N
 154.642 +                    line.startsWith(".. function::", indent) || // NOI18N
 154.643 +                    line.startsWith(".. method::", indent)) { // NOI18N
 154.644 +                return false;
 154.645 +            }
 154.646 +        }
 154.647 +
 154.648 +        return false;
 154.649 +    }
 154.650 +
 154.651 +    private static class CachedIndexDocument {
 154.652 +        private List<CachedIndexDocumentEntry> entries = new ArrayList<>(DEFAULT_DOC_SIZE);
 154.653 +
 154.654 +        private void addPair(String key, String value, boolean index) {
 154.655 +            entries.add(new CachedIndexDocumentEntry(key, value, index));
 154.656 +        }
 154.657 +    }
 154.658 +
 154.659 +    private static class CachedIndexDocumentEntry {
 154.660 +        private String key;
 154.661 +        private String value;
 154.662 +        private boolean index;
 154.663 +
 154.664 +        public CachedIndexDocumentEntry(String key, String value, boolean index) {
 154.665 +            this.key = key;
 154.666 +            this.value = value;
 154.667 +            this.index = index;
 154.668 +        }
 154.669 +    }
 154.670 +
 154.671 +    private List<IndexDocument> scanRst(FileObject fo, Indexable indexable, IndexingSupport support, String overrideUrl) {
 154.672 +        List<CachedIndexDocument> documents = new ArrayList<>();
 154.673 +
 154.674 +        List<IndexDocument> docs = new ArrayList<>();
 154.675 +        
 154.676 +        if (fo != null) {
 154.677 +            String module = fo.getNameExt();
 154.678 +            assert module.endsWith(".rst"); // NOI18N
 154.679 +            module = module.substring(0, module.length() - 4);
 154.680 +
 154.681 +            // Skip files that are already in the standard Python libraries (as .py files).
 154.682 +            // For these, normal scanning applies
 154.683 +            // (I should consider checking that they are consistent with the official
 154.684 +            // documentation, at least during preindexing)
 154.685 +            if (PREINDEXING) {
 154.686 +                // XXX This doesn't work right for anything but the builtin Jython interpreter....
 154.687 +                // OTOH that's the only thing we're preindexing at this point
 154.688 +                FileObject lib = getLibDir();
 154.689 +                if (lib != null) {
 154.690 +                    String path = module.replace('.', '/');
 154.691 +                    FileObject py = lib.getFileObject(path); // Look for package dir
 154.692 +                    if (py == null) {
 154.693 +                        py = lib.getFileObject(path + ".py"); // NOI18N
 154.694 +                    }
 154.695 +                    if (py != null) {
 154.696 +                        System.err.println("DELETE " + FileUtil.getFileDisplayName(fo) + " because there is a corresponding " + FileUtil.getFileDisplayName(py)); // NOI18N
 154.697 +                        // No - it's in a zip archive now
 154.698 +                        //try {
 154.699 +                        //    // Delete it!
 154.700 +                        //    fo.delete();
 154.701 +                        //} catch (IOException ex) {
 154.702 +                        //    Exceptions.printStackTrace(ex);
 154.703 +                        //}
 154.704 +                        return Collections.emptyList();
 154.705 +                    }
 154.706 +                }
 154.707 +            }
 154.708 +
 154.709 +            String name = fo.getName();
 154.710 +
 154.711 +            // Skip some really obsolete libraries -- IRIX only etc
 154.712 +            if (name.equals("gl") || name.equals("cd") || // NOI18N
 154.713 +                    name.equals("al") || name.equals("fm") ||
 154.714 +                    name.equals("fl") || name.equals("imgfile") || // NOI18N
 154.715 +                    name.equals("jpeg") || // NOI18N
 154.716 +                    name.equals("sunau") || name.equals("sunaudio")) { // NOI!8N
 154.717 +                return Collections.emptyList();
 154.718 +            }
 154.719 +
 154.720 +            Pattern PATTERN = Pattern.compile("\\s*\\.\\.\\s+(.*)::\\s*(.+)\\s*"); // NOI18N
 154.721 +
 154.722 +            BaseDocument doc = GsfUtilities.getDocument(fo, true);
 154.723 +            if (doc != null) {
 154.724 +                Map<String, CachedIndexDocument> classDocs = new HashMap<>();
 154.725 +                CachedIndexDocument document = null;
 154.726 +                try {
 154.727 +                    String text = doc.getText(0, doc.getLength());
 154.728 +                    String[] lines = text.split("\n");
 154.729 +                    String currentClass = null;
 154.730 +
 154.731 +                    for (int lineno = 0, maxLines = lines.length; lineno < maxLines; lineno++) {
 154.732 +                        String line = lines[lineno];
 154.733 +                        if (!line.startsWith(".. ") && !line.contains(" .. ")) { // NOI18N
 154.734 +                            continue;
 154.735 +                        }
 154.736 +
 154.737 +                        Matcher m = PATTERN.matcher(line);
 154.738 +                        if (m.matches()) {
 154.739 +                            String key = m.group(1);
 154.740 +
 154.741 +                            if (key.equals("attribute") || // NOI18N
 154.742 +                                    key.equals("currentmodule") || // NOI18N
 154.743 +                                    key.equals("class") || // NOI18N
 154.744 +                                    key.equals("exception") || // NOI18N
 154.745 +                                    key.equals("function") || // NOI18N
 154.746 +                                    key.equals("method") || // NOI18N
 154.747 +                                    key.equals("data") || // NOI18N
 154.748 +                                    key.equals("module")) {  // NOI18N
 154.749 +
 154.750 +
 154.751 +                                if (key.equals("module") || key.equals("currentmodule")) {  // NOI18N
 154.752 +                                    // TODO - determine package name
 154.753 +                                    module = m.group(2);
 154.754 +                                    document = new CachedIndexDocument();
 154.755 +                                    documents.add(document);
 154.756 +                                    document.addPair(FIELD_MODULE_NAME, module, true);
 154.757 +                                    String moduleAttrs = "S";
 154.758 +                                    if (isDeprecated(lines, lineno)) {
 154.759 +                                        moduleAttrs = "SD";
 154.760 +                                    }
 154.761 +                                    document.addPair(FIELD_MODULE_ATTR_NAME, moduleAttrs, false); // NOI18N
 154.762 +                                } else {
 154.763 +                                    // Methods described in an rst without an actual module definition...
 154.764 +                                    if (document == null) {
 154.765 +                                        document = new CachedIndexDocument();
 154.766 +                                        documents.add(document);
 154.767 +                                        document.addPair(FIELD_MODULE_NAME, module, true);
 154.768 +                                        document.addPair(FIELD_MODULE_ATTR_NAME, "S", false); // NOI18N
 154.769 +                                    }
 154.770 +                                    if (key.equals("method") || key.equals("attribute")) { // NOI18N) { // NOI18N
 154.771 +                                        String signature = m.group(2);
 154.772 +
 154.773 +                                        if ("string.template".equals(signature)) { // NOI18N
 154.774 +                                            // Wrong - ignore this one (ends up on the String class)
 154.775 +                                            continue;
 154.776 +                                        }
 154.777 +                                        if (signature.startsWith("somenamedtuple.")) {
 154.778 +                                            // Ditto
 154.779 +                                            continue;
 154.780 +                                        }
 154.781 +                                        // Error in mailbox.rst - Python 2.6
 154.782 +                                        if (".et_folder(folder)".equals(signature)) {
 154.783 +                                            signature = "get_folder(folder)";
 154.784 +                                        }
 154.785 +
 154.786 +                                        int dot = signature.indexOf('.');
 154.787 +                                        if (dot != -1) {
 154.788 +                                            int paren = signature.indexOf('(');
 154.789 +                                            if (paren == -1 || paren > dot) {
 154.790 +                                                assert signature.matches("\\w+\\.\\w+.*") : signature;
 154.791 +                                                String dottedName = signature.substring(0, dot);
 154.792 +                                                CachedIndexDocument dottedDoc = classDocs.get(dottedName);
 154.793 +                                                if (dottedDoc != null) {
 154.794 +                                                    currentClass = dottedName;
 154.795 +                                                } else /*if (currentClass == null)*/ {
 154.796 +                                                    currentClass = dottedName;
 154.797 +                                                    // New class without class:: declaration first.
 154.798 +                                                    CachedIndexDocument classDocument = new CachedIndexDocument();
 154.799 +                                                    documents.add(classDocument);
 154.800 +                                                    classDocs.put(currentClass, classDocument);
 154.801 +                                                    classDocument.addPair(FIELD_IN, module, true);
 154.802 +
 154.803 +                                                    classDocument.addPair(FIELD_CLASS_NAME, currentClass, true);
 154.804 +                                                    classDocument.addPair(FIELD_CASE_INSENSITIVE_CLASS_NAME, currentClass.toLowerCase(), true);
 154.805 +                                                }
 154.806 +                                                signature = signature.substring(dot + 1);
 154.807 +                                            }
 154.808 +                                        }
 154.809 +
 154.810 +
 154.811 +                                        CachedIndexDocument classDocument = classDocs.get(currentClass);
 154.812 +                                        assert classDocs != null;
 154.813 +
 154.814 +                                        if (key.equals("method")) {
 154.815 +                                            signature = cleanupSignature(signature);
 154.816 +                                            if (signature.indexOf('(') == -1) {
 154.817 +                                                signature = signature + "()";
 154.818 +                                            }
 154.819 +
 154.820 +                                            assert signature.indexOf('(') != -1 && signature.indexOf(')') != -1 &&
 154.821 +                                                    signature.indexOf(')') > signature.indexOf('(') : signature;
 154.822 +                                            int lparen = signature.indexOf('(');
 154.823 +                                            int rparen = signature.indexOf(')', lparen + 1);
 154.824 +                                            if (lparen != -1 && rparen != -1) {
 154.825 +                                                String methodName = signature.substring(0, lparen);
 154.826 +                                                String args = signature.substring(lparen + 1, rparen);
 154.827 +                                                char type;
 154.828 +                                                if (methodName.equals("__init__")) { // NOI18N
 154.829 +                                                    type = 'c';
 154.830 +                                                } else {
 154.831 +                                                    type = 'F';
 154.832 +                                                }
 154.833 +                                                StringBuilder sig = new StringBuilder();
 154.834 +                                                sig.append(methodName);
 154.835 +
 154.836 +                                                int symFlags = 0;
 154.837 +                                                if (NameStyle.isPrivateName(methodName)) {
 154.838 +                                                    symFlags |= ScopeConstants.PRIVATE;
 154.839 +                                                }
 154.840 +                                                // TODO - look up deprecated etc.
 154.841 +                                                SymInfo fakeSym = new SymInfo(symFlags);
 154.842 +
 154.843 +                                                int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
 154.844 +                                                if (isDeprecated(lines, lineno)) {
 154.845 +                                                    flags |= IndexedElement.DEPRECATED;
 154.846 +                                                }
 154.847 +
 154.848 +                                                appendFlags(sig, type, fakeSym, flags);
 154.849 +                                                sig.append(args);
 154.850 +                                                sig.append(';');
 154.851 +
 154.852 +                                                classDocument.addPair(FIELD_MEMBER, sig.toString(), true);
 154.853 +                                            }
 154.854 +                                        } else {
 154.855 +                                            assert key.equals("attribute");
 154.856 +
 154.857 +                                            StringBuilder sig = new StringBuilder();
 154.858 +                                            sig.append(signature);
 154.859 +                                            int symFlags = 0;
 154.860 +                                            if (NameStyle.isPrivateName(signature)) {
 154.861 +                                                symFlags |= ScopeConstants.PRIVATE;
 154.862 +                                            }
 154.863 +                                            // TODO - look up deprecated etc.
 154.864 +                                            SymInfo fakeSym = new SymInfo(symFlags);
 154.865 +
 154.866 +                                            int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
 154.867 +                                            if (isDeprecated(lines, lineno)) {
 154.868 +                                                flags |= IndexedElement.DEPRECATED;
 154.869 +                                            }
 154.870 +
 154.871 +
 154.872 +                                            appendFlags(sig, 'A', fakeSym, flags);
 154.873 +                                            classDocument.addPair(FIELD_MEMBER, sig.toString(), true);
 154.874 +                                        }
 154.875 +                                    } else if (key.equals("class") || key.equals("exception")) { // NOI18N
 154.876 +                                        assert module != null;
 154.877 +                                        String cls = m.group(2);
 154.878 +
 154.879 +                                        int paren = cls.indexOf('(');
 154.880 +                                        String constructor = null;
 154.881 +                                        if (paren != -1) {
 154.882 +                                            // Some documents specify a constructor here
 154.883 +                                            constructor = cleanupSignature(cls);
 154.884 +                                            cls = cls.substring(0, paren);
 154.885 +                                        }
 154.886 +                                        currentClass = cls;
 154.887 +
 154.888 +                                        CachedIndexDocument classDocument = new CachedIndexDocument();
 154.889 +                                        classDocs.put(currentClass, classDocument);
 154.890 +                                        documents.add(classDocument);
 154.891 +                                        classDocument.addPair(FIELD_IN, module, true);
 154.892 +
 154.893 +                                        if (key.equals("exception") && !"Exception".equals(cls)) { // NOI18N
 154.894 +                                            classDocument.addPair(FIELD_EXTENDS_NAME, "Exception", true); // NOI18N
 154.895 +                                        }
 154.896 +
 154.897 +                                        classDocument.addPair(FIELD_CLASS_NAME, cls, true);
 154.898 +                                        int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY | IndexedElement.CONSTRUCTOR;
 154.899 +                                        if (isDeprecated(lines, lineno)) {
 154.900 +                                            flags |= IndexedElement.DEPRECATED;
 154.901 +                                        }
 154.902 +                                        if (flags != 0) {
 154.903 +                                            // TODO - store Documented, Deprecated, DocOnly, etc.
 154.904 +                                            classDocument.addPair(FIELD_CLASS_ATTR_NAME, IndexedElement.encode(flags), false);
 154.905 +                                        }
 154.906 +                                        classDocument.addPair(FIELD_CASE_INSENSITIVE_CLASS_NAME, cls.toLowerCase(), true);
 154.907 +
 154.908 +                                        // TODO - determine extends
 154.909 +                                        //document.addPair(FIELD_EXTENDS_NAME, superClass, true);
 154.910 +
 154.911 +                                        if (constructor != null) {
 154.912 +                                            assert constructor.indexOf('(') != -1 && constructor.indexOf(')') != -1 &&
 154.913 +                                                    constructor.indexOf(')') > constructor.indexOf('(') : constructor;
 154.914 +
 154.915 +                                            String signature = constructor;
 154.916 +                                            int lparen = signature.indexOf('(');
 154.917 +                                            int rparen = signature.indexOf(')', lparen + 1);
 154.918 +                                            if (lparen != -1 && rparen != -1) {
 154.919 +                                                //String methodName = signature.substring(0, lparen);
 154.920 +                                                String methodName = "__init__"; // The constructor is always __init__ !
 154.921 +                                                String args = signature.substring(lparen + 1, rparen);
 154.922 +                                                StringBuilder sig = new StringBuilder();
 154.923 +                                                sig.append(methodName);
 154.924 +                                                int symFlags = 0;
 154.925 +                                                if (NameStyle.isPrivateName(methodName)) {
 154.926 +                                                    symFlags |= ScopeConstants.PRIVATE;
 154.927 +                                                }
 154.928 +                                                // TODO - look up deprecated etc.
 154.929 +                                                SymInfo fakeSym = new SymInfo(symFlags);
 154.930 +
 154.931 +                                                flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY | IndexedElement.CONSTRUCTOR;
 154.932 +                                                if (isDeprecated(lines, lineno)) {
 154.933 +                                                    flags |= IndexedElement.DEPRECATED;
 154.934 +                                                }
 154.935 +
 154.936 +                                                appendFlags(sig, 'c', fakeSym, flags);
 154.937 +                                                sig.append(args);
 154.938 +                                                sig.append(';');
 154.939 +
 154.940 +                                                classDocument.addPair(FIELD_MEMBER, sig.toString(), true);
 154.941 +                                            }
 154.942 +
 154.943 +                                        }
 154.944 +                                    } else if (key.equals("function") || (key.equals("data") && m.group(2).contains("("))) { // NOI18N
 154.945 +                                        // constants.rst for example registers a data item for "quit" which is really a function
 154.946 +
 154.947 +                                        String signature = m.group(2);
 154.948 +                                        indexRstFunction(signature, lines, lineno, document);
 154.949 +
 154.950 +                                        // See if we have any additional lines with signatures
 154.951 +                                        for (int lookahead = lineno + 1; lookahead < maxLines; lookahead++) {
 154.952 +                                            String l = lines[lookahead];
 154.953 +                                            String trimmed = l.trim();
 154.954 +                                            if (trimmed.length() == 0 || trimmed.startsWith(":")) { // NOI18N
 154.955 +                                                break;
 154.956 +                                            }
 154.957 +                                            lineno++;
 154.958 +
 154.959 +                                            indexRstFunction(trimmed, lines, lookahead, document);
 154.960 +                                        }
 154.961 +
 154.962 +                                    } else if (key.equals("data")) { // NOI18N
 154.963 +                                        String data = m.group(2);
 154.964 +
 154.965 +                                        StringBuilder sig = new StringBuilder();
 154.966 +                                        sig.append(data);
 154.967 +                                        int symFlags = 0;
 154.968 +                                        if (NameStyle.isPrivateName(data)) {
 154.969 +                                            symFlags |= ScopeConstants.PRIVATE;
 154.970 +                                        }
 154.971 +                                        // TODO - look up deprecated etc.
 154.972 +                                        SymInfo fakeSym = new SymInfo(symFlags);
 154.973 +
 154.974 +                                        int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
 154.975 +                                        if (isDeprecated(lines, lineno)) {
 154.976 +                                            flags |= IndexedElement.DEPRECATED;
 154.977 +                                        }
 154.978 +
 154.979 +                                        appendFlags(sig, 'D', fakeSym, flags);
 154.980 +
 154.981 +                                        document.addPair(FIELD_ITEM, sig.toString(), true);
 154.982 +                                    } else {
 154.983 +                                        // TODO Handle deprecated attribute!
 154.984 +
 154.985 +                                        //    currentmodule::
 154.986 +                                        //    deprecated::
 154.987 +                                        //    doctest::
 154.988 +                                        //    envvar::
 154.989 +                                        //    epigraph::
 154.990 +                                        //    highlight::
 154.991 +                                        //    highlightlang::
 154.992 +                                        //    index::
 154.993 +                                        //    literalinclude::
 154.994 +                                        //    moduleauthor::
 154.995 +                                        //    note::
 154.996 +                                        //    opcode::
 154.997 +                                        //    productionlist::
 154.998 +                                        //    rubric::
 154.999 +                                        //    sectionauthor::
154.1000 +                                        //    seealso::
154.1001 +                                        //    testcode::
154.1002 +                                        //    testsetup::
154.1003 +                                        //    toctree::
154.1004 +                                        //    versionadded::
154.1005 +                                        //    versionchanged::
154.1006 +                                        //    warning::
154.1007 +                                    }
154.1008 +                                }
154.1009 +                            }
154.1010 +                        } else if (line.startsWith(".. _bltin-file-objects:") || line.startsWith(".. _string-methods:")) { // NOI18N
154.1011 +                            if (currentClass != null) {
154.1012 +                                currentClass = null;
154.1013 +                            }
154.1014 +                        }
154.1015 +                    }
154.1016 +
154.1017 +                    for (String clz : classDocs.keySet()) {
154.1018 +                        StringBuilder sig = new StringBuilder();
154.1019 +                        sig.append(clz);
154.1020 +                        int symFlags = 0;
154.1021 +                        if (NameStyle.isPrivateName(clz)) {
154.1022 +                            symFlags |= ScopeConstants.PRIVATE;
154.1023 +                        }
154.1024 +                        // TODO - look up deprecated etc.
154.1025 +                        SymInfo fakeSym = new SymInfo(symFlags);
154.1026 +                        appendFlags(sig, 'C', fakeSym, IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY);
154.1027 +
154.1028 +                        document.addPair(FIELD_ITEM, sig.toString(), true);
154.1029 +                    }
154.1030 +
154.1031 +                } catch (BadLocationException ex) {
154.1032 +                    Exceptions.printStackTrace(ex);
154.1033 +                }
154.1034 +
154.1035 +                // Post processing: Add missing attributes not found in the .rst files
154.1036 +                // but introspected using dir() in a python console
154.1037 +                if (document != null) {
154.1038 +                    if ("operator".equals(module)) { // Fill in missing operators!
154.1039 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1040 +                                new String[] { "__abs__", "__add__", "__and__", "__div__", "__floordiv__", "__index__", "__invert__", "__lshift__", "__mod__", "__mul__", "__neg__", "__or__", "__pos__", "__pow__", "__rshift__", "__sub__", "__truediv__", "__xor__" },
154.1041 +                                document, classDocs, "int", documents, module, false, true);
154.1042 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1043 +                                new String[] { "__abs__", "__add__", "__and__", "__div__", "__floordiv__", "__index__", "__invert__", "__lshift__", "__mod__", "__mul__", "__neg__", "__or__", "__pos__", "__pow__", "__rshift__", "__sub__", "__truediv__", "__xor__" },
154.1044 +                                document, classDocs, "long", documents, module, false, true);
154.1045 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1046 +                                new String[] { "__abs__", "__add__", "__div__", "__eq__", "__floordiv__", "__ge__", "__gt__", "__le__", "__lt__", "__mod__", "__mul__", "__ne__", "__neg__", "__pos__", "__pow__", "__sub__", "__truediv__" },
154.1047 +                                document, classDocs, "float", documents, module, false, true);
154.1048 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1049 +                                new String[] { "__abs__", "__add__", "__div__", "__eq__", "__floordiv__", "__ge__", "__gt__", "__le__", "__lt__", "__mod__", "__mul__", "__ne__", "__neg__", "__pos__", "__pow__", "__sub__", "__truediv__" },
154.1050 +                                document, classDocs, "complex", documents, module, false, true);
154.1051 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1052 +                                new String[] { "__abs__", "__add__", "__and__", "__div__", "__floordiv__", "__index__", "__invert__", "__lshift__", "__mod__", "__mul__", "__neg__", "__or__", "__pos__", "__pow__", "__rshift__", "__sub__", "__truediv__", "__xor__" },
154.1053 +                                document, classDocs, "bool", documents, module, false, true);
154.1054 +
154.1055 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1056 +                                new String[] { "__add__", "__contains__", "__eq__", "__ge__", "__getitem__", "__getslice__", "__gt__", "__le__", "__lt__", "__mod__", "__mul__", "__ne__", "index" },
154.1057 +                                document, classDocs, "str", documents, module, false, true);
154.1058 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1059 +                                new String[] { "__add__", "__contains__", "__delitem__", "__delslice__", "__eq__", "__ge__", "__getitem__", "__getslice__", "__gt__", "__iadd__", "__imul__", "__le__", "__lt__", "__mul__", "__ne__", "__setitem__", "__setslice__", "index" },
154.1060 +                                document, classDocs, "list", documents, module, false, true);
154.1061 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1062 +                                new String[] { "__contains__", "__delitem__", "__eq__", "__ge__", "__getitem__", "__gt__", "__le__", "__lt__", "__ne__", "__setitem__" },
154.1063 +                                document, classDocs, "dict", documents, module, false, true);
154.1064 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1065 +                                new String[] { "__add__", "__contains__", "__eq__", "__ge__", "__getitem__", "__getslice__", "__gt__", "__le__", "__lt__", "__mul__", "__ne__", "index" },
154.1066 +                                document, classDocs, "tuple", documents, module, false, true);
154.1067 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1068 +                                new String[] { "__add__", "__contains__", "__eq__", "__ge__", "__getitem__", "__getslice__", "__gt__", "__le__", "__lt__", "__mod__", "__mul__", "__ne__", "index" },
154.1069 +                                document, classDocs, "unicode", documents, module, false, true);
154.1070 +//                    } else if ("stdtypes".equals(module)) {
154.1071 +//                        // Found no definitions for these puppies
154.1072 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1073 +//                              new String[] { "__class__", "__cmp__", "__coerce__", "__delattr__", "__divmod__", "__doc__", "__float__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__hex__", "__init__", "__int__", "__long__", "__new__", "__nonzero__", "__oct__", "__radd__", "__rand__", "__rdiv__", "__rdivmod__", "__reduce__", "__reduce_ex__", "__repr__", "__rfloordiv__", "__rlshift__", "__rmod__", "__rmul__", "__ror__", "__rpow__", "__rrshift__", "__rsub__", "__rtruediv__", "__rxor__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "__trunc__", "conjugate", "denominator", "imag", "numerator", "real" },
154.1074 +//                                document, classDocs, "int", documents, module, true, false);
154.1075 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1076 +//                              new String[] { "__class__", "__cmp__", "__coerce__", "__delattr__", "__divmod__", "__doc__", "__float__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__hex__", "__init__", "__int__", "__long__", "__new__", "__nonzero__", "__oct__", "__radd__", "__rand__", "__rdiv__", "__rdivmod__", "__reduce__", "__reduce_ex__", "__repr__", "__rfloordiv__", "__rlshift__", "__rmod__", "__rmul__", "__ror__", "__rpow__", "__rrshift__", "__rsub__", "__rtruediv__", "__rxor__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "__trunc__", "conjugate", "denominator", "imag", "numerator", "real" },
154.1077 +//                                document, classDocs, "long", documents, module, true, false);
154.1078 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1079 +//                              new String[] { "__class__", "__coerce__", "__delattr__", "__divmod__", "__doc__", "__float__", "__format__", "__getattribute__", "__getformat__", "__getnewargs__", "__hash__", "__init__", "__int__", "__long__", "__new__", "__nonzero__", "__radd__", "__rdiv__", "__rdivmod__", "__reduce__", "__reduce_ex__", "__repr__", "__rfloordiv__", "__rmod__", "__rmul__", "__rpow__", "__rsub__", "__rtruediv__", "__setattr__", "__setformat__", "__sizeof__", "__str__", "__subclasshook__", "__trunc__", "conjugate", "imag", "is_integer", "real" },
154.1080 +//                                document, classDocs, "float", documents, module, true, false);
154.1081 +//
154.1082 +//
154.1083 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1084 +//                              new String[] { "__class__", "__coerce__", "__delattr__", "__divmod__", "__doc__", "__float__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__init__", "__int__", "__long__", "__new__", "__nonzero__", "__radd__", "__rdiv__", "__rdivmod__", "__reduce__", "__reduce_ex__", "__repr__", "__rfloordiv__", "__rmod__", "__rmul__", "__rpow__", "__rsub__", "__rtruediv__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "conjugate", "imag", "real" },
154.1085 +//                                document, classDocs, "complex", documents, module, true, false);
154.1086 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1087 +//                              new String[] { "__class__", "__cmp__", "__coerce__", "__delattr__", "__divmod__", "__doc__", "__float__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__hex__", "__init__", "__int__", "__long__", "__new__", "__nonzero__", "__oct__", "__radd__", "__rand__", "__rdiv__", "__rdivmod__", "__reduce__", "__reduce_ex__", "__repr__", "__rfloordiv__", "__rlshift__", "__rmod__", "__rmul__", "__ror__", "__rpow__", "__rrshift__", "__rsub__", "__rtruediv__", "__rxor__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "__trunc__", "conjugate", "denominator", "imag", "numerator", "real" },
154.1088 +//                                document, classDocs, "bool", documents, module, true, false);
154.1089 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1090 +//                              new String[] { "__class__", "__delattr__", "__doc__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__init__", "__len__", "__new__", "__repr__", "__rmod__", "__rmul__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "_formatter_field_name_split", "_formatter_parser" },
154.1091 +//                                document, classDocs, "str", documents, module, true, false);
154.1092 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1093 +//                              new String[] { "__class__", "__delattr__", "__doc__", "__format__", "__getattribute__", "__hash__", "__init__", "__iter__", "__len__", "__new__", "__repr__", "__reversed__", "__rmul__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "append", "count", "extend", "insert", "pop", "remove", "reverse", "sort" },
154.1094 +//                                document, classDocs, "list", documents, module, true, false);
154.1095 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1096 +//                              new String[] { "__class__", "__cmp__", "__delattr__", "__doc__", "__format__", "__getattribute__", "__hash__", "__iter__", "__len__", "__new__", "__repr__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__" },
154.1097 +//                                document, classDocs, "dict", documents, module, true, false);
154.1098 +//
154.1099 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1100 +//                              new String[] { "__class__", "__delattr__", "__doc__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__init__", "__iter__", "__len__", "__new__", "__reduce__", "__reduce_ex__", "__repr__", "__rmul__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "count" },
154.1101 +//                                document, classDocs, "tuple", documents, module, true, false);
154.1102 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
154.1103 +//                              new String[] { "__class__", "__delattr__", "__doc__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__init__", "__len__", "__new__", "__reduce__", "__reduce_ex__", "__repr__", "__rmod__", "__rmul__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "_formatter_field_name_split", "_formatter_parser", "capitalize", "center", "count", "decode", "encode", "endswith", "expandtabs", "find", "format", "isalnum", "isalpha", "isdecimal", "isdigit", "islower", "isnumeric", "isspace", "istitle", "isupper", "join", "ljust", "lower", "lstrip", "partition", "replace", "rfind", "rindex", "rjust", "rpartition", "rsplit", "rstrip", "split", "splitlines", "startswith", "strip", "swapcase", "title", "translate", "upper", "zfill" },
154.1104 +//                                document, classDocs, "unicode", documents, module, true, false);
154.1105 +//
154.1106 +                    }
154.1107 +                }
154.1108 +
154.1109 +                // And convert to a proper GSF search document. I didn't do this directly
154.1110 +                // because I want to modify the documents after adding documents and pairs.
154.1111 +                for (CachedIndexDocument cid : documents) {
154.1112 +                    List<CachedIndexDocumentEntry> entries = cid.entries;
154.1113 +                    IndexDocument indexedDoc = support.createDocument(indexable);
154.1114 +//                    IndexDocument indexedDoc = support.createDocument(entries.size(), overrideUrl);
154.1115 +                    docs.add(indexedDoc);
154.1116 +                    for (CachedIndexDocumentEntry entry : entries) {
154.1117 +                        indexedDoc.addPair(entry.key, entry.value, true, true); // XXX indexable and stored ???
154.1118 +                    }
154.1119 +                }
154.1120 +            }
154.1121 +        }
154.1122 +
154.1123 +        return docs;
154.1124 +    }
154.1125 +
154.1126 +    /** Add the given list of names, found in the given document with a given key, and add it
154.1127 +     * to the specified class (possibly found in the classDocs list - if not, add one to the
154.1128 +     * documents list)
154.1129 +     */
154.1130 +    private void addMissing(String key, String newKey, String[] names, CachedIndexDocument doc,
154.1131 +            Map<String, CachedIndexDocument> classDocs, String clz, List<CachedIndexDocument> documents, String module,
154.1132 +            boolean addUnknown, boolean search) {
154.1133 +
154.1134 +        CachedIndexDocument classDocument = classDocs.get(clz);
154.1135 +        if (classDocument == null) {
154.1136 +            // New class without class:: declaration first.
154.1137 +            classDocument = new CachedIndexDocument();
154.1138 +            documents.add(classDocument);
154.1139 +            classDocs.put(clz, classDocument);
154.1140 +            classDocument.addPair(FIELD_IN, module, true);
154.1141 +
154.1142 +            classDocument.addPair(FIELD_CLASS_NAME, clz, true);
154.1143 +            classDocument.addPair(FIELD_CASE_INSENSITIVE_CLASS_NAME, clz.toLowerCase(), true);
154.1144 +        }
154.1145 +
154.1146 +        assert classDocument != doc;
154.1147 +
154.1148 +        List<String> namesFound = new ArrayList<>();
154.1149 +        List<String> namesMissing = new ArrayList<>();
154.1150 +        boolean noneFound = true;
154.1151 +
154.1152 +        // Look for each of the given functions
154.1153 +        Search:
154.1154 +        for (String name : names) {
154.1155 +            boolean found = false;
154.1156 +            if (search) {
154.1157 +                int nameLength = name.length();
154.1158 +
154.1159 +                // DEBUGGING: Look to make sure I don't already have it in the class doc!
154.1160 +                for (CachedIndexDocumentEntry entry : classDocument.entries) {
154.1161 +                    if (newKey.equals(entry.key)) {
154.1162 +                        if (entry.value.startsWith(name) &&
154.1163 +                                (entry.value.length() <= nameLength || entry.value.charAt(nameLength) == ';')) {
154.1164 +                             // Uh oh - what do I do here?
154.1165 +                            System.err.println("WARNING: I already have a definition for name " + name + " in class " + clz);
154.1166 +                            continue Search;
154.1167 +                        }
154.1168 +                    }
154.1169 +                }
154.1170 +
154.1171 +                for (CachedIndexDocumentEntry entry : doc.entries) {
154.1172 +                    if (key.equals(entry.key)) {
154.1173 +                        if (entry.value.startsWith(name) &&
154.1174 +                                (entry.value.length() <= nameLength || entry.value.charAt(nameLength) == ';')) {
154.1175 +                            // Found it!
154.1176 +                            classDocument.addPair(newKey, entry.value, entry.index);
154.1177 +                            found = true;
154.1178 +                            namesFound.add(name);
154.1179 +                            break;
154.1180 +                        }
154.1181 +                    }
154.1182 +                }
154.1183 +            }
154.1184 +
154.1185 +            if (!found) {
154.1186 +                if (addUnknown) {
154.1187 +                    // TODO - see if I can find a way to extract the signature too!
154.1188 +                    String args = "";
154.1189 +                    String signature = name + "()"; //
154.1190 +
154.1191 +                    assert signature.indexOf('(') != -1 && signature.indexOf(')') != -1 &&
154.1192 +                            signature.indexOf(')') > signature.indexOf('(') : signature;
154.1193 +                    char type;
154.1194 +                    if (name.equals("__init__")) { // NOI18N
154.1195 +                        type = 'c';
154.1196 +                    } else {
154.1197 +                        type = 'F';
154.1198 +                    }
154.1199 +                    StringBuilder sig = new StringBuilder();
154.1200 +                    sig.append(name);
154.1201 +
154.1202 +                    int symFlags = 0;
154.1203 +                    if (NameStyle.isPrivateName(name)) {
154.1204 +                        symFlags |= ScopeConstants.PRIVATE;
154.1205 +                    }
154.1206 +                    // TODO - look up deprecated etc.
154.1207 +                    SymInfo fakeSym = new SymInfo(symFlags);
154.1208 +
154.1209 +                    int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
154.1210 +                    appendFlags(sig, type, fakeSym, flags);
154.1211 +                    sig.append(args);
154.1212 +                    sig.append(';');
154.1213 +
154.1214 +                    classDocument.addPair(newKey, sig.toString(), true);
154.1215 +                } else {
154.1216 +                    namesMissing.add(name);
154.1217 +                }
154.1218 +            } else {
154.1219 +                noneFound = false;
154.1220 +            }
154.1221 +        }
154.1222 +
154.1223 +        if (PREINDEXING) {
154.1224 +            if (namesFound.size() > 0) {
154.1225 +                StringBuilder sb = new StringBuilder();
154.1226 +                sb.append("FOUND for ");
154.1227 +                sb.append(clz);
154.1228 +                sb.append(" in ");
154.1229 +                sb.append(module);
154.1230 +                sb.append(": ");
154.1231 +                appendList(sb, namesFound);
154.1232 +                System.err.println(sb.toString());
154.1233 +            }
154.1234 +
154.1235 +            if (noneFound && search) {
154.1236 +                System.err.println("ERROR: NONE of the passed in names for " + clz + " were found!");
154.1237 +            }
154.1238 +
154.1239 +            if (namesMissing.size() > 0) {
154.1240 +                StringBuilder sb = new StringBuilder();
154.1241 +                sb.append("WARNING: Missing these names from ");
154.1242 +                sb.append(module);
154.1243 +                sb.append(" for use by class ");
154.1244 +                sb.append(clz);
154.1245 +                sb.append(" : ");
154.1246 +                appendList(sb, namesMissing);
154.1247 +                System.err.println(sb.toString());
154.1248 +            }
154.1249 +        }
154.1250 +    }
154.1251 +
154.1252 +    private static void appendList(StringBuilder sb, List<String> list) {
154.1253 +        sb.append("{ ");
154.1254 +        boolean first = true;
154.1255 +        for (String m : list) {
154.1256 +            if (first) {
154.1257 +                first = false;
154.1258 +            } else {
154.1259 +                sb.append(", ");
154.1260 +            }
154.1261 +            sb.append('"');
154.1262 +            sb.append(m);
154.1263 +            sb.append('"');
154.1264 +        }
154.1265 +        sb.append(" }");
154.1266 +    }
154.1267 +
154.1268 +    private void indexRstFunction(String signature, String[] lines, int lineno, CachedIndexDocument document) {
154.1269 +        int dot = signature.indexOf('.');
154.1270 +        if (dot != -1) {
154.1271 +            int paren = signature.indexOf('(');
154.1272 +            if (paren == -1 || paren > dot) {
154.1273 +                assert signature.matches("\\w+\\.\\w+.*") : signature; // NOI18N
154.1274 +                signature = signature.substring(dot + 1);
154.1275 +            }
154.1276 +        }
154.1277 +        signature = cleanupSignature(signature);
154.1278 +        if (signature.indexOf('(') == -1) {
154.1279 +            signature = signature + "()"; // NOI18N
154.1280 +        } else if (signature.indexOf(')') == -1) {
154.1281 +            //signature = signature + ")";
154.1282 +            assert signature.indexOf(')') != -1;
154.1283 +        }
154.1284 +        int lparen = signature.indexOf('(');
154.1285 +        int rparen = signature.indexOf(')', lparen + 1);
154.1286 +        if (lparen != -1 && rparen != -1) {
154.1287 +            String methodName = signature.substring(0, lparen);
154.1288 +            String args = signature.substring(lparen + 1, rparen);
154.1289 +            StringBuilder sig = new StringBuilder();
154.1290 +            sig.append(methodName);
154.1291 +            int symFlags = 0;
154.1292 +            if (NameStyle.isPrivateName(methodName)) {
154.1293 +                symFlags |= ScopeConstants.PRIVATE;
154.1294 +            }
154.1295 +            // TODO - look up deprecated etc.
154.1296 +            SymInfo fakeSym = new SymInfo(symFlags);
154.1297 +            int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
154.1298 +            if (isDeprecated(lines, lineno)) {
154.1299 +                flags |= IndexedElement.DEPRECATED;
154.1300 +            }
154.1301 +            appendFlags(sig, 'F', fakeSym, flags);
154.1302 +            sig.append(args);
154.1303 +            sig.append(';');
154.1304 +
154.1305 +            document.addPair(FIELD_ITEM, sig.toString(), true);
154.1306 +        }
154.1307 +    }
154.1308 +
154.1309 +    private List<IndexDocument> scanEgg(FileObject fo, Indexable indexable, ParserResult result, IndexingSupport support) {
154.1310 +        List<IndexDocument> documents = new ArrayList<>();
154.1311 +
154.1312 +        if (fo == null) {
154.1313 +            return documents;
154.1314 +        }
154.1315 +
154.1316 +        try {
154.1317 +            String s = fo.toURL().toExternalForm() + "!"; // NOI18N
154.1318 +            URL u = new URL("jar:" + s); // NOI18N
154.1319 +            FileObject root = URLMapper.findFileObject(u);
154.1320 +            String rootUrl = PythonIndex.getPreindexUrl(u.toExternalForm());
154.1321 +            indexScriptDocRecursively(support, documents, root, rootUrl);
154.1322 +        } catch (MalformedURLException ex) {
154.1323 +            Exceptions.printStackTrace(ex);
154.1324 +        }
154.1325 +
154.1326 +        return documents;
154.1327 +    }
154.1328 +
154.1329 +    /**
154.1330 +     * Method which recursively indexes directory trees, such as the yui/ folder
154.1331 +     * for example
154.1332 +     */
154.1333 +    private void indexScriptDocRecursively(IndexingSupport support, List<IndexDocument> documents, final FileObject fo, String url) {
154.1334 +        if (fo.isFolder()) {
154.1335 +            for (FileObject c : fo.getChildren()) {
154.1336 +                indexScriptDocRecursively(support, documents, c, url + "/" + c.getNameExt()); // NOI18N
154.1337 +            }
154.1338 +            return;
154.1339 +        }
154.1340 +
154.1341 +        String ext = fo.getExt();
154.1342 +
154.1343 +//        if ("py".equals(ext)) { // NOI18N
154.1344 +//            DefaultParseListener listener = new DefaultParseListener();
154.1345 +//            List<ParserFile> files = Collections.<ParserFile>singletonList(new DefaultParserFile(fo, null, false));
154.1346 +//            SourceFileReader reader = new SourceFileReader() {
154.1347 +//                public CharSequence read(ParserFile file) throws IOException {
154.1348 +//                    BaseDocument doc = GsfUtilities.getDocument(fo, true);
154.1349 +//                    if (doc != null) {
154.1350 +//                        try {
154.1351 +//                            return doc.getText(0, doc.getLength());
154.1352 +//                        } catch (BadLocationException ex) {
154.1353 +//                            Exceptions.printStackTrace(ex);
154.1354 +//                        }
154.1355 +//                    }
154.1356 +//
154.1357 +//                    return "";
154.1358 +//                }
154.1359 +//
154.1360 +//                public int getCaretOffset(ParserFile file) {
154.1361 +//                    return -1;
154.1362 +//                }
154.1363 +//            };
154.1364 +//            Job job = new Job(files, listener, reader, null);
154.1365 +//            new PythonParser().parseFiles(job);
154.1366 +//            ParserResult parserResult = listener.getParserResult();
154.1367 +//            if (parserResult != null && parserResult.isValid()) {
154.1368 +//                documents.addAll(new IndexTask((PythonParserResult)parserResult, support, url).scan());
154.1369 +//            }
154.1370 +//        } else if ("rst".equals(ext)) { // NOI18N
154.1371 +//            documents.addAll(scanRst(fo, support, url));
154.1372 +//        }
154.1373 +    }
154.1374 +
154.1375 +    private FileObject getLibDir() {
154.1376 +        // TODO - fetch from projects!!!!
154.1377 +        PythonPlatformManager manager = PythonPlatformManager.getInstance();
154.1378 +        PythonPlatform platform = manager.getPlatform(manager.getDefaultPlatform());
154.1379 +        if (platform != null) {
154.1380 +            String cmd = platform.getInterpreterCommand();
154.1381 +            File file = new File(cmd);
154.1382 +            if (file.exists()) {
154.1383 +                file = file.getAbsoluteFile();
154.1384 +                File home = file.getParentFile().getParentFile();
154.1385 +                if (home != null) {
154.1386 +                    // Look for Lib - Jython style
154.1387 +                    File lib = new File(home, "Lib"); // NOI18N
154.1388 +                    boolean exists = lib.exists();
154.1389 +                    if (!exists) { // Unix style
154.1390 +                        lib = new File(home, "lib" + File.separator + "python"); // NOI18N
154.1391 +                        exists = lib.exists();
154.1392 +                    }
154.1393 +                    if (exists) {
154.1394 +                        return FileUtil.toFileObject(lib);
154.1395 +                    }
154.1396 +                }
154.1397 +            }
154.1398 +        }
154.1399 +
154.1400 +        return null;
154.1401 +    }
154.1402 +}
   155.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   155.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonIndexerFactory.java	Sun Sep 13 11:47:42 2015 +0200
   155.3 @@ -0,0 +1,47 @@
   155.4 +/*
   155.5 + * To change this license header, choose License Headers in Project Properties.
   155.6 + * To change this template file, choose Tools | Templates
   155.7 + * and open the template in the editor.
   155.8 + */
   155.9 +package org.netbeans.modules.python.source;
  155.10 +
  155.11 +import org.netbeans.modules.parsing.api.Snapshot;
  155.12 +import org.netbeans.modules.parsing.spi.indexing.Context;
  155.13 +import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexer;
  155.14 +import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory;
  155.15 +import org.netbeans.modules.parsing.spi.indexing.Indexable;
  155.16 +
  155.17 +/**
  155.18 + *
  155.19 + * @author Ralph Benjamin Ruijs
  155.20 + */
  155.21 +public class PythonIndexerFactory extends EmbeddingIndexerFactory {    
  155.22 +
  155.23 +    @Override
  155.24 +    public EmbeddingIndexer createIndexer(Indexable indexable, Snapshot snapshot) {
  155.25 +        if(PythonIndexer.isIndexable(indexable, snapshot)) {
  155.26 +            return new PythonIndexer();
  155.27 +        }
  155.28 +        return null;
  155.29 +    }
  155.30 +
  155.31 +    @Override
  155.32 +    public void filesDeleted(Iterable<? extends Indexable> indexables, Context context) {
  155.33 +//        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
  155.34 +    }
  155.35 +
  155.36 +    @Override
  155.37 +    public void filesDirty(Iterable<? extends Indexable> arg0, Context arg1) {
  155.38 +//        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
  155.39 +    }
  155.40 +
  155.41 +    @Override
  155.42 +    public String getIndexerName() {
  155.43 +        return PythonIndexer.NAME;
  155.44 +    }
  155.45 +
  155.46 +    @Override
  155.47 +    public int getIndexVersion() {
  155.48 +        return PythonIndexer.VERSION;
  155.49 +    }
  155.50 +}
   156.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   156.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonParser.java	Sun Sep 13 11:47:42 2015 +0200
   156.3 @@ -0,0 +1,760 @@
   156.4 +/*
   156.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   156.6 + *
   156.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   156.8 + *
   156.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  156.10 + * Other names may be trademarks of their respective owners.
  156.11 + *
  156.12 + * The contents of this file are subject to the terms of either the GNU
  156.13 + * General Public License Version 2 only ("GPL") or the Common
  156.14 + * Development and Distribution License("CDDL") (collectively, the
  156.15 + * "License"). You may not use this file except in compliance with the
  156.16 + * License. You can obtain a copy of the License at
  156.17 + * http://www.netbeans.org/cddl-gplv2.html
  156.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  156.19 + * specific language governing permissions and limitations under the
  156.20 + * License.  When distributing the software, include this License Header
  156.21 + * Notice in each file and include the License file at
  156.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  156.23 + * particular file as subject to the "Classpath" exception as provided
  156.24 + * by Oracle in the GPL Version 2 section of the License file that
  156.25 + * accompanied this code. If applicable, add the following below the
  156.26 + * License Header, with the fields enclosed by brackets [] replaced by
  156.27 + * your own identifying information:
  156.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  156.29 + *
  156.30 + * Contributor(s):
  156.31 + *
  156.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  156.33 + */
  156.34 +package org.netbeans.modules.python.source;
  156.35 +
  156.36 +import java.io.InputStream;
  156.37 +import java.io.InputStreamReader;
  156.38 +import java.util.ArrayList;
  156.39 +import java.util.List;
  156.40 +import java.util.logging.Level;
  156.41 +import java.util.logging.Logger;
  156.42 +import javax.swing.event.ChangeListener;
  156.43 +import javax.swing.text.BadLocationException;
  156.44 +import org.netbeans.modules.csl.api.Severity;
  156.45 +import org.netbeans.modules.csl.spi.DefaultError;
  156.46 +import org.netbeans.modules.csl.api.Error;
  156.47 +import org.netbeans.modules.csl.api.OffsetRange;
  156.48 +import org.netbeans.modules.csl.spi.GsfUtilities;
  156.49 +import org.netbeans.modules.parsing.api.Snapshot;
  156.50 +import org.netbeans.modules.parsing.api.Task;
  156.51 +import org.netbeans.modules.parsing.spi.Parser;
  156.52 +import org.netbeans.modules.parsing.spi.SourceModificationEvent;
  156.53 +import org.netbeans.modules.python.api.PythonFileEncodingQuery;
  156.54 +import org.openide.filesystems.FileObject;
  156.55 +import org.python.antlr.runtime.ANTLRStringStream;
  156.56 +import org.python.antlr.runtime.BaseRecognizer;
  156.57 +import org.python.antlr.runtime.BitSet;
  156.58 +import org.python.antlr.runtime.CommonToken;
  156.59 +import org.python.antlr.runtime.CommonTokenStream;
  156.60 +import org.python.antlr.runtime.IntStream;
  156.61 +import org.python.antlr.runtime.Lexer;
  156.62 +import org.python.antlr.runtime.MismatchedTokenException;
  156.63 +import org.python.antlr.runtime.RecognitionException;
  156.64 +
  156.65 +import org.openide.filesystems.FileUtil;
  156.66 +import org.openide.util.Exceptions;
  156.67 +import org.python.antlr.ListErrorHandler;
  156.68 +import org.python.antlr.ParseException;
  156.69 +import org.python.antlr.PythonLexer;
  156.70 +import org.python.antlr.PythonTokenSource;
  156.71 +import org.python.antlr.PythonTree;
  156.72 +import org.python.antlr.PythonTreeAdaptor;
  156.73 +import org.python.antlr.base.expr;
  156.74 +import org.python.antlr.base.mod;
  156.75 +import org.python.antlr.base.slice;
  156.76 +import org.python.antlr.base.stmt;
  156.77 +import org.python.antlr.runtime.ANTLRReaderStream;
  156.78 +import org.python.antlr.runtime.CharStream;
  156.79 +
  156.80 +/**
  156.81 + * Parser for Python. Wraps Jython.
  156.82 + * 
  156.83 + * @author Frank Wierzbicki
  156.84 + * @author Tor Norbye
  156.85 + */
  156.86 +public class PythonParser extends Parser {
  156.87 +    /** For unit tests such that they can make sure we didn't have a parser abort */
  156.88 +    static Throwable runtimeException;
  156.89 +
  156.90 +    static {
  156.91 +        org.python.core.PySystemState.initialize();
  156.92 +    }
  156.93 +    
  156.94 +    private Result lastResult;
  156.95 +    private final PythonFileEncodingQuery fileEncodingQuery = new PythonFileEncodingQuery();
  156.96 +    private String headerCached = null;
  156.97 +    private String encodingCache = null;
  156.98 +
  156.99 +    public mod file_input(CharStream charStream, String fileName) throws RecognitionException {
 156.100 +        ListErrorHandler eh = new ListErrorHandler();
 156.101 +        mod tree = null;
 156.102 +        PythonLexer lexer = new PythonLexer(charStream);
 156.103 +        lexer.setErrorHandler(eh);
 156.104 +        CommonTokenStream tokens = new CommonTokenStream(lexer);
 156.105 +        tokens.discardOffChannelTokens(true);
 156.106 +        PythonTokenSource indentedSource = new PythonTokenSource(tokens, fileName);
 156.107 +        tokens = new CommonTokenStream(indentedSource);
 156.108 +        org.python.antlr.PythonParser parser = new org.python.antlr.PythonParser(tokens);
 156.109 +        parser.setTreeAdaptor(new PythonTreeAdaptor());
 156.110 +        parser.setErrorHandler(eh);
 156.111 +        org.python.antlr.PythonParser.file_input_return r = parser.file_input();
 156.112 +        tree = (mod)r.getTree();
 156.113 +        return tree;
 156.114 +    }
 156.115 +
 156.116 +    @Override
 156.117 +    public void addChangeListener(ChangeListener changeListener) {}
 156.118 +
 156.119 +    @Override
 156.120 +    public void removeChangeListener(ChangeListener changeListener) {}
 156.121 +    
 156.122 +    public PythonTree parse(InputStream istream, String fileName) throws Exception {
 156.123 +        InputStreamReader reader = new InputStreamReader(istream, "ISO-8859-1");
 156.124 +        return file_input(new ANTLRReaderStream(reader), fileName);
 156.125 +    }
 156.126 +    
 156.127 +    @Override
 156.128 +    public final Result getResult(Task task) throws org.netbeans.modules.parsing.spi.ParseException {
 156.129 +        return lastResult;
 156.130 +    }
 156.131 +    
 156.132 +    private static final Logger LOG = Logger.getLogger(PythonParser.class.getName());
 156.133 +
 156.134 +    @Override
 156.135 +    public void parse(Snapshot snapshot, Task task, SourceModificationEvent event) throws org.netbeans.modules.parsing.spi.ParseException {
 156.136 +        Context context = new Context();
 156.137 +        context.snapshot = snapshot;
 156.138 +        context.event = event;
 156.139 +        context.task = task;
 156.140 +        context.caretOffset = GsfUtilities.getLastKnownCaretOffset(snapshot, event);
 156.141 +        context.source = snapshot.getText().toString();
 156.142 +        context.file = snapshot.getSource().getFileObject();
 156.143 +        if(context.file == null) {
 156.144 +            return; // TODO: parse the source, not the file
 156.145 +        }
 156.146 +        /* Let's not sanitize ;-) Would be great if we could have a more robust parser
 156.147 +        if (context.caretOffset != -1) {
 156.148 +            context.sanitized = Sanitize.EDITED_DOT;
 156.149 +        }
 156.150 +        */
 156.151 +        lastResult = parse(context, context.sanitized);
 156.152 +    }
 156.153 +    public PythonParserResult parse(final Context context, Sanitize sanitizing) {
 156.154 +        boolean sanitizedSource = false;
 156.155 +        String sourceCode = context.source;
 156.156 +        if (!((sanitizing == Sanitize.NONE) || (sanitizing == Sanitize.NEVER))) {
 156.157 +            boolean ok = sanitizeSource(context, sanitizing);
 156.158 +
 156.159 +            if (ok) {
 156.160 +                assert context.sanitizedSource != null;
 156.161 +                sanitizedSource = true;
 156.162 +                sourceCode = context.sanitizedSource;
 156.163 +            } else {
 156.164 +                // Try next trick
 156.165 +                return sanitize(context, sanitizing);
 156.166 +            }
 156.167 +        }
 156.168 +        final String source = sourceCode;
 156.169 +
 156.170 +        if (sanitizing == Sanitize.NONE) {
 156.171 +            context.errorOffset = -1;
 156.172 +        }
 156.173 +
 156.174 +        final List<Error> errors = new ArrayList<>();
 156.175 +        final FileObject file = context.file;
 156.176 +        try {
 156.177 +            String fileName = file.getNameExt();
 156.178 +            // TODO - sniff file headers etc. Frank's comment:
 156.179 +            // Longer term for Python compatibility, having NetBeans sniff the top two lines
 156.180 +            // for an encoding would be the right thing to do from a pure Python
 156.181 +            // compatibility standard (see http://www.python.org/dev/peps/pep-0263/) I
 156.182 +            // have pep-0263 code in Jython that I could probably extract for this
 156.183 +            // purpose down the road.
 156.184 +            //String charset = "ISO8859_1"; // NOI18N
 156.185 +            //String charset = "UTF-8"; // NOI18N
 156.186 +            //String charset = "iso8859_1"; // NOI18N
 156.187 +            // TODO: improve this check.
 156.188 +            int cache_len = sourceCode.length() >= 64 ? 64 : sourceCode.length();
 156.189 +            if (headerCached == null || cache_len != headerCached.length() || !headerCached.equals(sourceCode.substring(0, cache_len))) {
 156.190 +                headerCached = sourceCode.substring(0, cache_len);
 156.191 +                encodingCache = fileEncodingQuery.getPythonFileEncoding(sourceCode.split("\n", 2));                
 156.192 +            }
 156.193 +            String charset = encodingCache;            
 156.194 +                
 156.195 +            final boolean ignoreErrors = sanitizedSource;
 156.196 +            ListErrorHandler errorHandler = new ListErrorHandler() {
 156.197 +                @Override
 156.198 +                public void error(String message, PythonTree t) {
 156.199 +                    errors.add(new DefaultError(null, message, null, file, t.getCharStartIndex(), t.getCharStopIndex(), Severity.ERROR));
 156.200 +                    super.error(message, t);
 156.201 +                }
 156.202 +
 156.203 +                @Override
 156.204 +                public expr errorExpr(PythonTree t) {
 156.205 +                    return super.errorExpr(t);
 156.206 +                }
 156.207 +
 156.208 +                @Override
 156.209 +                public mod errorMod(PythonTree t) {
 156.210 +                    return super.errorMod(t);
 156.211 +                }
 156.212 +
 156.213 +                @Override
 156.214 +                public slice errorSlice(PythonTree t) {
 156.215 +                    return super.errorSlice(t);
 156.216 +                }
 156.217 +
 156.218 +                @Override
 156.219 +                public stmt errorStmt(PythonTree t) {
 156.220 +                    return super.errorStmt(t);
 156.221 +                }
 156.222 +
 156.223 +                @Override
 156.224 +                public boolean mismatch(BaseRecognizer br, IntStream input, int ttype, BitSet follow) {
 156.225 +                    return super.mismatch(br, input, ttype, follow);
 156.226 +                }
 156.227 +
 156.228 +                @Override
 156.229 +                public Object recoverFromMismatchedToken(BaseRecognizer br, IntStream input, int ttype, BitSet follow) {
 156.230 +                    MismatchedTokenException mt = new MismatchedTokenException(ttype, input);
 156.231 +                    String message = br.getErrorMessage(mt, br.getTokenNames());
 156.232 +                    if (mt.line >= 1) {
 156.233 +                        int lineOffset = findLineOffset(context.source, mt.line-1);
 156.234 +                        if (mt.charPositionInLine > 0) {
 156.235 +                            lineOffset += mt.charPositionInLine;
 156.236 +                        }
 156.237 +                        int start = lineOffset;//t.getCharStartIndex();
 156.238 +                        int stop = lineOffset;//t.getCharStopIndex();
 156.239 +                        errors.add(new DefaultError(null, message, null, file, start, stop, Severity.ERROR));
 156.240 +                    }
 156.241 +                    return super.recoverFromMismatchedToken(br, input, ttype, follow);
 156.242 +                }
 156.243 +
 156.244 +                @Override
 156.245 +                public void recover(Lexer lex, RecognitionException re) {
 156.246 +                    super.recover(lex, re);
 156.247 +                }
 156.248 +
 156.249 +                @Override
 156.250 +                public void recover(BaseRecognizer br, IntStream input, RecognitionException re) {
 156.251 +                    super.recover(br, input, re);
 156.252 +                }
 156.253 +
 156.254 +                @Override
 156.255 +                public void reportError(BaseRecognizer br, RecognitionException re) {
 156.256 +                    if (!ignoreErrors) {
 156.257 +                        String message = br.getErrorMessage(re, br.getTokenNames());
 156.258 +                        if (message == null || message.length() == 0) {
 156.259 +                            message = re.getMessage();
 156.260 +                        }
 156.261 +                        if (message == null) {
 156.262 +                            //message = re.getUnexpectedType();
 156.263 +                            message = re.toString();
 156.264 +                        }
 156.265 +                        int start = re.index;
 156.266 +
 156.267 +                        // Try to find the line offset. re.index doesn't do the trick.
 156.268 +                        start = PythonUtils.getOffsetByLineCol(source, re.line - 1, 0); // -1: 0-based
 156.269 +                        int end = start;
 156.270 +                        if (re.charPositionInLine > 0) {
 156.271 +                            try {
 156.272 +                                end = GsfUtilities.getRowLastNonWhite(source, start) + 1;
 156.273 +                                start += re.charPositionInLine;
 156.274 +                                if (end < start) {
 156.275 +                                    end = start;
 156.276 +                                }
 156.277 +                            } catch (BadLocationException ex) {
 156.278 +                                Exceptions.printStackTrace(ex);
 156.279 +                                end = start;
 156.280 +                            }
 156.281 +                            if (end == 0) {
 156.282 +                                end = start;
 156.283 +                            }
 156.284 +                        }
 156.285 +
 156.286 +                        // Some errors have better offsets if we look at the token stream
 156.287 +                        if (re instanceof MismatchedTokenException) {
 156.288 +                            MismatchedTokenException m = (MismatchedTokenException)re;
 156.289 +                            if (m.token != null) {
 156.290 +                                if (m.token instanceof org.python.antlr.runtime.CommonToken) {
 156.291 +                                    CommonToken token = (org.python.antlr.runtime.CommonToken)m.token;
 156.292 +                                    start = token.getStartIndex();
 156.293 +                                    end = token.getStopIndex();
 156.294 +                                }
 156.295 +                            }
 156.296 +                        }
 156.297 +
 156.298 +                        if (start > source.length()) {
 156.299 +                            start = source.length();
 156.300 +                            end = start;
 156.301 +                        }
 156.302 +
 156.303 +                        errors.add(new DefaultError(null, message, null, file, start, end, Severity.ERROR));
 156.304 +
 156.305 +                        // In order to avoid a StackOverflowError, the BaseRecognizer must be recreated.
 156.306 +                        // We must keep the names of the tokens to avoid a NullPointerException.
 156.307 +                        // See bz252630
 156.308 +                        final String[] tokenNames = br.getTokenNames();
 156.309 +                        br = new BaseRecognizer() {
 156.310 +
 156.311 +                            @Override
 156.312 +                            public String getSourceName() {
 156.313 +                                return file.getName();
 156.314 +                            }
 156.315 +
 156.316 +                            @Override
 156.317 +                            public String[] getTokenNames() {
 156.318 +                                return tokenNames;
 156.319 +                            }
 156.320 +                        };
 156.321 +
 156.322 +                        super.reportError(br, re);
 156.323 +                    }
 156.324 +                }
 156.325 +            };
 156.326 +
 156.327 +            PythonLexer lexer = new PythonLexer(new ANTLRStringStream(sourceCode));
 156.328 +            lexer.setErrorHandler(errorHandler);
 156.329 +            CommonTokenStream tokens = new CommonTokenStream(lexer);
 156.330 +            tokens.discardOffChannelTokens(true);
 156.331 +            PythonTokenSource indentedSource = new PythonTokenSource(tokens, fileName);
 156.332 +            CommonTokenStream indentedTokens = new CommonTokenStream(indentedSource);
 156.333 +            // Import line ending with a dot raise a NullPointerException in
 156.334 +            // org.python.antlr.GrammarActions.makeDottedText called from parser.file_input
 156.335 +            // sanitizeImportTokens will remove the dot token from the list of tokens in
 156.336 +            // indentedTokens to avoid the bug and add an error at this file.
 156.337 +            // See https://netbeans.org/bugzilla/show_bug.cgi?id=252356
 156.338 +            sanitizeImportTokens(indentedTokens, errors, file);
 156.339 +            org.python.antlr.PythonParser parser;
 156.340 +            if (charset != null) {
 156.341 +                parser = new org.python.antlr.PythonParser(indentedTokens, charset);
 156.342 +            } else {
 156.343 +                parser = new org.python.antlr.PythonParser(indentedTokens);
 156.344 +            }
 156.345 +            parser.setTreeAdaptor(new PythonTreeAdaptor());
 156.346 +            parser.setErrorHandler(errorHandler);
 156.347 +            org.python.antlr.PythonParser.file_input_return r = parser.file_input();
 156.348 +            PythonTree t = (PythonTree)r.getTree();
 156.349 +            PythonParserResult result = new PythonParserResult(t, context.snapshot);
 156.350 +            result.setErrors(errors);
 156.351 +
 156.352 +            result.setSanitized(context.sanitized, context.sanitizedRange, context.sanitizedContents);
 156.353 +            result.setSource(sourceCode);
 156.354 +
 156.355 +            return result;
 156.356 +        } catch (ParseException pe) {
 156.357 +            if (sanitizing == Sanitize.NONE) {
 156.358 +                PythonParserResult sanitizedResult = sanitize(context, sanitizing);
 156.359 +                if (sanitizedResult.isValid()) {
 156.360 +                    return sanitizedResult;
 156.361 +                } else {
 156.362 +                    int offset = pe.index;
 156.363 +                    assert offset >= 0;
 156.364 +                    String desc = pe.getLocalizedMessage();
 156.365 +                    if (desc == null) {
 156.366 +                        desc = pe.getMessage();
 156.367 +                    }
 156.368 +                    DefaultError error = new DefaultError(null /*key*/, desc, null, file, offset, offset, Severity.ERROR);
 156.369 +                    PythonParserResult parserResult = new PythonParserResult(null, context.snapshot);
 156.370 +                    parserResult.addError(error);
 156.371 +                    for (Error e : errors) {
 156.372 +                        parserResult.addError(e);
 156.373 +                    }
 156.374 +
 156.375 +                    return parserResult;
 156.376 +                }
 156.377 +            } else {
 156.378 +                return sanitize(context, sanitizing);
 156.379 +            }
 156.380 +        } catch (NullPointerException e) {
 156.381 +            String fileName = "";
 156.382 +            if (file != null) {
 156.383 +                fileName = FileUtil.getFileDisplayName(file);
 156.384 +            }
 156.385 +            e = Exceptions.attachMessage(e, "Was parsing " + fileName);
 156.386 +            Exceptions.printStackTrace(e);
 156.387 +            return new PythonParserResult(null, context.snapshot);
 156.388 +        } catch (Throwable t) {
 156.389 +            runtimeException = t;
 156.390 +            StackTraceElement[] stackTrace = t.getStackTrace();
 156.391 +            if (stackTrace != null && stackTrace.length > 0 && stackTrace[0].getClassName().startsWith("org.python.antlr")) {//.runtime.tree.RewriteRuleElementStream")) {
 156.392 +                // This is issue 150921
 156.393 +                // Don't bug user about it -- we already know
 156.394 +                Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Encountered issue #150921", t);
 156.395 +            } else {
 156.396 +                t = Exceptions.attachMessage(t, "Was parsing " + FileUtil.getFileDisplayName(file));
 156.397 +                Exceptions.printStackTrace(t);
 156.398 +            }
 156.399 +            return new PythonParserResult(null, context.snapshot);
 156.400 +        }
 156.401 +    }
 156.402 +
 156.403 +    private void sanitizeImportTokens(CommonTokenStream indentedTokens, List errors, FileObject file) {
 156.404 +        List tokens = indentedTokens.getTokens();
 156.405 +        List<CommonToken> tokensToRemove = new ArrayList<>();
 156.406 +        int i = 0;
 156.407 +        while (i < tokens.size()) {
 156.408 +            CommonToken importToken = (CommonToken)tokens.get(i);
 156.409 +            if ("import".equals(importToken.getText()) || "from".equals(importToken.getText())) {
 156.410 +                // sanitizeDotTokens return the index of the token that starts the next line
 156.411 +                i = sanitizeDotTokens(tokens, tokensToRemove, importToken, i + 1, errors, file);
 156.412 +            } else {
 156.413 +                i++;
 156.414 +            }
 156.415 +        }
 156.416 +
 156.417 +        for (CommonToken token : tokensToRemove) {
 156.418 +            tokens.remove(token);
 156.419 +        }
 156.420 +    }
 156.421 +
 156.422 +    private int sanitizeDotTokens(List tokens, List tokensToRemove, CommonToken importToken,
 156.423 +            int startIndex, List errors, FileObject file) {
 156.424 +        for (int j = startIndex; j < tokens.size() - 1; j++) {
 156.425 +            CommonToken dotToken = (CommonToken)tokens.get(j);
 156.426 +            CommonToken nextToken = (CommonToken)tokens.get(j + 1);
 156.427 +            if (".".equals(dotToken.getText())) {
 156.428 +                if (nextToken.getText().startsWith("\n")) {
 156.429 +                    tokensToRemove.add(dotToken);
 156.430 +                    String rawTokenText;
 156.431 +                    if (nextToken.getText().startsWith("\n")) {
 156.432 +                        rawTokenText = "\\n";
 156.433 +                    } else {
 156.434 +                        rawTokenText = " ";
 156.435 +                    }
 156.436 +                    errors.add(
 156.437 +                        new DefaultError(null, "Mismatch input '.' expecting NAME\nMissing NAME at '" + rawTokenText + "'",
 156.438 +                            null, file, importToken.getStartIndex(), dotToken.getStopIndex(), Severity.ERROR));
 156.439 +                }
 156.440 +            } else if ("\n".equals(nextToken.getText())) { // End of line, must continue looping from external loop
 156.441 +                return j + 1;
 156.442 +            }
 156.443 +        }
 156.444 +
 156.445 +        return startIndex;
 156.446 +    }
 156.447 +
 156.448 +    private static String asString(CharSequence sequence) {
 156.449 +        if (sequence instanceof String) {
 156.450 +            return (String)sequence;
 156.451 +        } else {
 156.452 +            return sequence.toString();
 156.453 +        }
 156.454 +    }
 156.455 +
 156.456 +
 156.457 +    @SuppressWarnings("fallthrough")
 156.458 +    private PythonParserResult sanitize(final Context context, final Sanitize sanitizing) {
 156.459 +
 156.460 +        switch (sanitizing) {
 156.461 +        case NEVER:
 156.462 +            return new PythonParserResult(null, context.snapshot);
 156.463 +
 156.464 +        case NONE:
 156.465 +            if (context.caretOffset != -1) {
 156.466 +                return parse(context, Sanitize.EDITED_DOT);
 156.467 +            }
 156.468 +
 156.469 +        case EDITED_DOT:
 156.470 +            // We've tried removing whitespace around the edit location
 156.471 +            // Fall through to try parsing with removing stuff around error location
 156.472 +            // (Don't bother doing this if errorOffset==caretOffset since that would try the same
 156.473 +            // source as EDITED_DOT which has no better chance of succeeding...)
 156.474 +            if (context.errorOffset != -1 && context.errorOffset != context.caretOffset) {
 156.475 +                return parse(context, Sanitize.ERROR_DOT);
 156.476 +            }
 156.477 +
 156.478 +        // Fall through to try the next trick
 156.479 +        case ERROR_DOT:
 156.480 +
 156.481 +            // We've tried removing dots - now try removing the whole line at the error position
 156.482 +            if (context.errorOffset != -1) {
 156.483 +                return parse(context, Sanitize.ERROR_LINE);
 156.484 +            }
 156.485 +
 156.486 +        // Fall through to try the next trick
 156.487 +        case ERROR_LINE:
 156.488 +
 156.489 +            // Messing with the error line didn't work - we could try "around" the error line
 156.490 +            // but I'm not attempting that now.
 156.491 +            // Finally try removing the whole line around the user editing position
 156.492 +            // (which could be far from where the error is showing up - but if you're typing
 156.493 +            // say a new "def" statement in a class, this will show up as an error on a mismatched
 156.494 +            // "end" statement rather than here
 156.495 +            if (context.caretOffset != -1) {
 156.496 +                return parse(context, Sanitize.EDITED_LINE);
 156.497 +            }
 156.498 +
 156.499 +        // Fall through for default handling
 156.500 +        case EDITED_LINE:
 156.501 +        default:
 156.502 +            // We're out of tricks - just return the failed parse result
 156.503 +            return new PythonParserResult(null, context.snapshot);
 156.504 +        }
 156.505 +    }
 156.506 +
 156.507 +    /**
 156.508 +     * Try cleaning up the source buffer around the current offset to increase
 156.509 +     * likelihood of parse success. Initially this method had a lot of
 156.510 +     * logic to determine whether a parse was likely to fail (e.g. invoking
 156.511 +     * the isEndMissing method from bracket completion etc.).
 156.512 +     * However, I am now trying a parse with the real source first, and then
 156.513 +     * only if that fails do I try parsing with sanitized source. Therefore,
 156.514 +     * this method has to be less conservative in ripping out code since it
 156.515 +     * will only be used when the regular source is failing.
 156.516 +     *
 156.517 +     * @todo Automatically close current statement by inserting ";"
 156.518 +     * @todo Handle sanitizing "new ^" from parse errors
 156.519 +     * @todo Replace "end" insertion fix with "}" insertion
 156.520 +     */
 156.521 +    private boolean sanitizeSource(Context context, Sanitize sanitizing) {
 156.522 +        int offset = context.caretOffset;
 156.523 +
 156.524 +        // Let caretOffset represent the offset of the portion of the buffer we'll be operating on
 156.525 +        if ((sanitizing == Sanitize.ERROR_DOT) || (sanitizing == Sanitize.ERROR_LINE)) {
 156.526 +            offset = context.errorOffset;
 156.527 +        }
 156.528 +
 156.529 +        // Don't attempt cleaning up the source if we don't have the buffer position we need
 156.530 +        if (offset == -1) {
 156.531 +            return false;
 156.532 +        }
 156.533 +
 156.534 +        // The user might be editing around the given caretOffset.
 156.535 +        // See if it looks modified
 156.536 +        // Insert an end statement? Insert a } marker?
 156.537 +        String doc = context.source;
 156.538 +        if (offset > doc.length()) {
 156.539 +            return false;
 156.540 +        }
 156.541 +
 156.542 +        try {
 156.543 +            // Sometimes the offset shows up on the next line
 156.544 +            if (GsfUtilities.isRowEmpty(doc, offset) || GsfUtilities.isRowWhite(doc, offset)) {
 156.545 +                offset = GsfUtilities.getRowStart(doc, offset) - 1;
 156.546 +                if (offset < 0) {
 156.547 +                    offset = 0;
 156.548 +                }
 156.549 +            }
 156.550 +
 156.551 +            if (!(GsfUtilities.isRowEmpty(doc, offset) || GsfUtilities.isRowWhite(doc, offset))) {
 156.552 +                if ((sanitizing == Sanitize.EDITED_LINE) || (sanitizing == Sanitize.ERROR_LINE)) {
 156.553 +                    // See if I should try to remove the current line, since it has text on it.
 156.554 +                    int lineEnd = GsfUtilities.getRowLastNonWhite(doc, offset);
 156.555 +
 156.556 +                    if (lineEnd != -1) {
 156.557 +                        lineEnd++; // lineEnd is exclusive, not inclusive
 156.558 +                        StringBuilder sb = new StringBuilder(doc.length());
 156.559 +                        int lineStart = GsfUtilities.getRowStart(doc, offset);
 156.560 +                        if (lineEnd >= lineStart + 2) {
 156.561 +                            sb.append(doc.substring(0, lineStart));
 156.562 +                            sb.append("//");
 156.563 +                            int rest = lineStart + 2;
 156.564 +                            if (rest < doc.length()) {
 156.565 +                                sb.append(doc.substring(rest, doc.length()));
 156.566 +                            }
 156.567 +                        } else {
 156.568 +                            // A line with just one character - can't replace with a comment
 156.569 +                            // Just replace the char with a space
 156.570 +                            sb.append(doc.substring(0, lineStart));
 156.571 +                            sb.append(" ");
 156.572 +                            int rest = lineStart + 1;
 156.573 +                            if (rest < doc.length()) {
 156.574 +                                sb.append(doc.substring(rest, doc.length()));
 156.575 +                            }
 156.576 +
 156.577 +                        }
 156.578 +
 156.579 +                        assert sb.length() == doc.length();
 156.580 +
 156.581 +                        context.sanitizedRange = new OffsetRange(lineStart, lineEnd);
 156.582 +                        context.sanitizedSource = sb.toString();
 156.583 +                        context.sanitizedContents = doc.substring(lineStart, lineEnd);
 156.584 +                        return true;
 156.585 +                    }
 156.586 +                } else {
 156.587 +                    assert sanitizing == Sanitize.ERROR_DOT || sanitizing == Sanitize.EDITED_DOT;
 156.588 +                    // Try nuking dots/colons from this line
 156.589 +                    // See if I should try to remove the current line, since it has text on it.
 156.590 +                    int lineStart = GsfUtilities.getRowStart(doc, offset);
 156.591 +                    int lineEnd = offset - 1;
 156.592 +                    while (lineEnd >= lineStart && lineEnd < doc.length()) {
 156.593 +                        if (!Character.isWhitespace(doc.charAt(lineEnd))) {
 156.594 +                            break;
 156.595 +                        }
 156.596 +                        lineEnd--;
 156.597 +                    }
 156.598 +                    if (lineEnd > lineStart) {
 156.599 +                        StringBuilder sb = new StringBuilder(doc.length());
 156.600 +                        String line = doc.substring(lineStart, lineEnd + 1);
 156.601 +                        int removeChars = 0;
 156.602 +                        int removeEnd = lineEnd + 1;
 156.603 +                        boolean isLineEnd = GsfUtilities.getRowLastNonWhite(context.source, lineEnd) <= lineEnd;
 156.604 +
 156.605 +                        if (line.endsWith(".")) { // NOI18N
 156.606 +                            removeChars = 1;
 156.607 +                        } else if (line.endsWith("(")) { // NOI18N
 156.608 +                            if (isLineEnd) {
 156.609 +                                removeChars = 1;
 156.610 +                            }
 156.611 +                        } else if (line.endsWith(",")) { // NOI18N                            removeChars = 1;
 156.612 +                            if (!isLineEnd) {
 156.613 +                                removeChars = 1;
 156.614 +                            }
 156.615 +                        } else if (line.endsWith(", ")) { // NOI18N
 156.616 +                            if (!isLineEnd) {
 156.617 +                                removeChars = 2;
 156.618 +                            }
 156.619 +                        } else if (line.endsWith(",)")) { // NOI18N
 156.620 +                            // Handle lone comma in parameter list - e.g.
 156.621 +                            // type "foo(a," -> you end up with "foo(a,|)" which doesn't parse - but
 156.622 +                            // the line ends with ")", not "," !
 156.623 +                            // Just remove the comma
 156.624 +                            removeChars = 1;
 156.625 +                            removeEnd--;
 156.626 +                        } else if (line.endsWith(", )")) { // NOI18N
 156.627 +                            // Just remove the comma
 156.628 +                            removeChars = 1;
 156.629 +                            removeEnd -= 2;
 156.630 +                        } else if (line.endsWith(" def") && isLineEnd) { // NOI18N
 156.631 +                            removeChars = 3;
 156.632 +                        } else {
 156.633 +//                            // Make sure the line doesn't end with one of the JavaScript keywords
 156.634 +//                            // (new, do, etc) - we can't handle that!
 156.635 +//                            for (String keyword : PythonUtils.PYTHON_KEYWORDS) { // reserved words are okay
 156.636 +//                                if (line.endsWith(keyword)) {
 156.637 +//                                    if ("print".equals(keyword)) { // NOI18N
 156.638 +//                                        // Only remove the keyword if it's the end of the line. Otherwise,
 156.639 +//                                        // it could have just been typed in front of something (e.g. inserted a print) and we don't
 156.640 +//                                        // want to confuse the parser with "va foo" instead of "var foo"
 156.641 +//                                        if (!isLineEnd) {
 156.642 +//                                            continue;
 156.643 +//                                        }
 156.644 +//                                    }
 156.645 +//                                    removeChars = 1;
 156.646 +//                                    break;
 156.647 +//                                }
 156.648 +//                            }
 156.649 +                        }
 156.650 +
 156.651 +                        if (removeChars == 0) {
 156.652 +                            return false;
 156.653 +                        }
 156.654 +
 156.655 +                        int removeStart = removeEnd - removeChars;
 156.656 +
 156.657 +                        sb.append(doc.substring(0, removeStart));
 156.658 +
 156.659 +                        for (int i = 0; i < removeChars; i++) {
 156.660 +                            sb.append(' ');
 156.661 +                        }
 156.662 +
 156.663 +                        if (removeEnd < doc.length()) {
 156.664 +                            sb.append(doc.substring(removeEnd, doc.length()));
 156.665 +                        }
 156.666 +                        assert sb.length() == doc.length();
 156.667 +
 156.668 +                        context.sanitizedRange = new OffsetRange(removeStart, removeEnd);
 156.669 +                        context.sanitizedSource = sb.toString();
 156.670 +                        context.sanitizedContents = doc.substring(removeStart, removeEnd);
 156.671 +                        return true;
 156.672 +                    }
 156.673 +                }
 156.674 +            }
 156.675 +        } catch (BadLocationException ble) {
 156.676 +            Exceptions.printStackTrace(ble);
 156.677 +        }
 156.678 +
 156.679 +        return false;
 156.680 +    }
 156.681 +
 156.682 +    private static int findLineOffset(String source, int line) {
 156.683 +        int offset = -1;
 156.684 +        for (int i = 0; i < line; i++) {
 156.685 +            offset = source.indexOf("\n", offset+1);
 156.686 +            if (offset == -1) {
 156.687 +                return source.length();
 156.688 +            }
 156.689 +        }
 156.690 +
 156.691 +        return Math.min(source.length(), offset+1);
 156.692 +    }
 156.693 +
 156.694 +    /** Attempts to sanitize the input buffer */
 156.695 +    public static enum Sanitize {
 156.696 +        /** Only parse the current file accurately, don't try heuristics */
 156.697 +        NEVER,
 156.698 +        /** Perform no sanitization */
 156.699 +        NONE,
 156.700 +        /** Try to remove the trailing . or :: at the caret line */
 156.701 +        EDITED_DOT,
 156.702 +        /** Try to remove the trailing . or :: at the error position, or the prior
 156.703 +         * line, or the caret line */
 156.704 +        ERROR_DOT,
 156.705 +        /** Try to cut out the error line */
 156.706 +        ERROR_LINE,
 156.707 +        /** Try to cut out the current edited line, if known */
 156.708 +        EDITED_LINE,
 156.709 +    }
 156.710 +
 156.711 +    /** Sanitize context */
 156.712 +    public static class Context {
 156.713 +        private FileObject file;
 156.714 +//        private ParseListener listener;
 156.715 +        private int errorOffset;
 156.716 +        private String source;
 156.717 +        private String sanitizedSource;
 156.718 +        private OffsetRange sanitizedRange = OffsetRange.NONE;
 156.719 +        private String sanitizedContents;
 156.720 +        private int caretOffset;
 156.721 +        private Sanitize sanitized = Sanitize.NONE;
 156.722 +//        private TranslatedSource translatedSource;
 156.723 +//        private Parser.Job job;
 156.724 +        private Snapshot snapshot;
 156.725 +        private Task task;
 156.726 +        private SourceModificationEvent event;
 156.727 +//
 156.728 +//        public Context(ParserFile parserFile, ParseListener listener, String source, int caretOffset, TranslatedSource translatedSource, Parser.Job job) {
 156.729 +//            this.file = parserFile;
 156.730 +//            this.listener = listener;
 156.731 +//            this.source = source;
 156.732 +//            this.caretOffset = caretOffset;
 156.733 +//            this.translatedSource = translatedSource;
 156.734 +//            this.job = job;
 156.735 +//
 156.736 +//
 156.737 +//            if (caretOffset != -1) {
 156.738 +//                sanitized = Sanitize.EDITED_DOT;
 156.739 +//            }
 156.740 +//        }
 156.741 +//
 156.742 +//        @Override
 156.743 +//        public String toString() {
 156.744 +//            return "PythonParser.Context(" + file.toString() + ")"; // NOI18N
 156.745 +//        }
 156.746 +//
 156.747 +//        public OffsetRange getSanitizedRange() {
 156.748 +//            return sanitizedRange;
 156.749 +//        }
 156.750 +//
 156.751 +//        public Sanitize getSanitized() {
 156.752 +//            return sanitized;
 156.753 +//        }
 156.754 +//
 156.755 +//        public String getSanitizedSource() {
 156.756 +//            return sanitizedSource;
 156.757 +//        }
 156.758 +//
 156.759 +//        public int getErrorOffset() {
 156.760 +//            return errorOffset;
 156.761 +//        }
 156.762 +    }
 156.763 +}
   157.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   157.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonParserResult.java	Sun Sep 13 11:47:42 2015 +0200
   157.3 @@ -0,0 +1,152 @@
   157.4 +/*
   157.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   157.6 + *
   157.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   157.8 + *
   157.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  157.10 + * Other names may be trademarks of their respective owners.
  157.11 + *
  157.12 + * The contents of this file are subject to the terms of either the GNU
  157.13 + * General Public License Version 2 only ("GPL") or the Common
  157.14 + * Development and Distribution License("CDDL") (collectively, the
  157.15 + * "License"). You may not use this file except in compliance with the
  157.16 + * License. You can obtain a copy of the License at
  157.17 + * http://www.netbeans.org/cddl-gplv2.html
  157.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  157.19 + * specific language governing permissions and limitations under the
  157.20 + * License.  When distributing the software, include this License Header
  157.21 + * Notice in each file and include the License file at
  157.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  157.23 + * particular file as subject to the "Classpath" exception as provided
  157.24 + * by Oracle in the GPL Version 2 section of the License file that
  157.25 + * accompanied this code. If applicable, add the following below the
  157.26 + * License Header, with the fields enclosed by brackets [] replaced by
  157.27 + * your own identifying information:
  157.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  157.29 + *
  157.30 + * Contributor(s):
  157.31 + *
  157.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  157.33 + */
  157.34 +package org.netbeans.modules.python.source;
  157.35 +
  157.36 +import java.util.LinkedList;
  157.37 +import java.util.List;
  157.38 +import org.netbeans.api.annotations.common.NonNull;
  157.39 +import org.netbeans.modules.csl.api.Error;
  157.40 +import org.netbeans.modules.csl.api.OffsetRange;
  157.41 +import org.netbeans.modules.csl.spi.ParserResult;
  157.42 +import org.netbeans.modules.parsing.api.Snapshot;
  157.43 +import org.netbeans.modules.python.source.PythonParser.Sanitize;
  157.44 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  157.45 +import org.python.antlr.PythonTree;
  157.46 +
  157.47 +/**
  157.48 + * A ParserResult for Python. The AST Jython's AST.
  157.49 + *
  157.50 + * @todo Cache AstPath for caret position here!
  157.51 + * @author Tor Norbye
  157.52 + */
  157.53 +public class PythonParserResult extends ParserResult {
  157.54 +    private PythonTree root;
  157.55 +    private List<Error> errors;
  157.56 +    private OffsetRange sanitizedRange = OffsetRange.NONE;
  157.57 +    private String source;
  157.58 +    private String sanitizedContents;
  157.59 +    private PythonParser.Sanitize sanitized;
  157.60 +    private PythonStructureScanner.AnalysisResult analysisResult;
  157.61 +    private SymbolTable symbolTable;
  157.62 +    private int codeTemplateOffset = -1;
  157.63 +
  157.64 +    public PythonParserResult(PythonTree tree, @NonNull Snapshot snapshot) {
  157.65 +        super(snapshot);
  157.66 +        this.root = tree;
  157.67 +        this.errors = new LinkedList<>();
  157.68 +    }
  157.69 +
  157.70 +    public PythonTree getRoot() {
  157.71 +        return root;
  157.72 +    }
  157.73 +
  157.74 +    @Override
  157.75 +    public List<? extends Error> getDiagnostics() {
  157.76 +        return errors;
  157.77 +    }
  157.78 +
  157.79 +    @Override
  157.80 +    protected void invalidate() {
  157.81 +    }
  157.82 +
  157.83 +    public void setErrors(List<? extends Error> errors) {
  157.84 +        this.errors.clear();
  157.85 +        this.errors.addAll(errors);
  157.86 +    }
  157.87 +    
  157.88 +    /**
  157.89 +     * Set the range of source that was sanitized, if any.
  157.90 +     */
  157.91 +    void setSanitized(PythonParser.Sanitize sanitized, OffsetRange sanitizedRange, String sanitizedContents) {
  157.92 +        this.sanitized = sanitized;
  157.93 +        this.sanitizedRange = sanitizedRange;
  157.94 +        this.sanitizedContents = sanitizedContents;
  157.95 +        if (sanitizedContents == null || sanitizedRange == OffsetRange.NONE) {
  157.96 +            this.sanitized = Sanitize.NONE;
  157.97 +        }
  157.98 +    }
  157.99 +
 157.100 +    public PythonParser.Sanitize getSanitized() {
 157.101 +        return sanitized;
 157.102 +    }
 157.103 +
 157.104 +    /**
 157.105 +     * Return whether the source code for the parse result was "cleaned"
 157.106 +     * or "sanitized" (modified to reduce chance of parser errors) or not.
 157.107 +     * This method returns OffsetRange.NONE if the source was not sanitized,
 157.108 +     * otherwise returns the actual sanitized range.
 157.109 +     */
 157.110 +    public OffsetRange getSanitizedRange() {
 157.111 +        return sanitizedRange;
 157.112 +    }
 157.113 +
 157.114 +    public SymbolTable getSymbolTable() {
 157.115 +        if (symbolTable == null) {
 157.116 +            symbolTable = new SymbolTable(root, getSnapshot().getSource().getFileObject());
 157.117 +        }
 157.118 +
 157.119 +        return symbolTable;
 157.120 +    }
 157.121 +
 157.122 +    public String getSanitizedContents() {
 157.123 +        return sanitizedContents;
 157.124 +    }
 157.125 +
 157.126 +    public String getSource() {
 157.127 +        return source;
 157.128 +    }
 157.129 +
 157.130 +    public void setSource(String source) {
 157.131 +        this.source = source;
 157.132 +    }
 157.133 +
 157.134 +    /**
 157.135 +     * @return the codeTemplateOffset
 157.136 +     */
 157.137 +    public int getCodeTemplateOffset() {
 157.138 +        return codeTemplateOffset;
 157.139 +    }
 157.140 +
 157.141 +    /**
 157.142 +     * @param codeTemplateOffset the codeTemplateOffset to set
 157.143 +     */
 157.144 +    public void setCodeTemplateOffset(int codeTemplateOffset) {
 157.145 +        this.codeTemplateOffset = codeTemplateOffset;
 157.146 +    }
 157.147 +
 157.148 +    public void addError(Error e) {
 157.149 +        errors.add(e);
 157.150 +    }
 157.151 +
 157.152 +    public boolean isValid() {
 157.153 +        return errors.isEmpty();
 157.154 +    }
 157.155 +}
   158.1 --- a/python.source/src/org/netbeans/modules/python/source/PythonProjectSourceLevelQuery.java	Sat Sep 12 23:03:15 2015 -0700
   158.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   158.3 @@ -1,29 +0,0 @@
   158.4 -/*
   158.5 - * To change this license header, choose License Headers in Project Properties.
   158.6 - * To change this template file, choose Tools | Templates
   158.7 - * and open the template in the editor.
   158.8 - */
   158.9 -package org.netbeans.modules.python.source;
  158.10 -
  158.11 -import org.netbeans.modules.python.source.queries.SourceLevelQueryImplementation;
  158.12 -import org.netbeans.api.project.FileOwnerQuery;
  158.13 -import org.netbeans.api.project.Project;
  158.14 -import org.openide.filesystems.FileObject;
  158.15 -import org.openide.util.lookup.ServiceProvider;
  158.16 -
  158.17 -@ServiceProvider(service = SourceLevelQueryImplementation.class, position = 400)
  158.18 -public class PythonProjectSourceLevelQuery implements SourceLevelQueryImplementation {
  158.19 -
  158.20 -    @Override
  158.21 -    public Result getSourceLevel(FileObject pythonFile) {
  158.22 -        final Project project = FileOwnerQuery.getOwner(pythonFile);
  158.23 -        if (project != null) {
  158.24 -            SourceLevelQueryImplementation impl = project.getLookup().lookup(SourceLevelQueryImplementation.class);
  158.25 -            if (impl != null) {
  158.26 -                return impl.getSourceLevel(pythonFile);
  158.27 -            }
  158.28 -        }
  158.29 -        return null;
  158.30 -    }
  158.31 -
  158.32 -}
   159.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   159.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonStructureItem.java	Sun Sep 13 11:47:42 2015 +0200
   159.3 @@ -0,0 +1,195 @@
   159.4 +/*
   159.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   159.6 + *
   159.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   159.8 + *
   159.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  159.10 + * Other names may be trademarks of their respective owners.
  159.11 + *
  159.12 + * The contents of this file are subject to the terms of either the GNU
  159.13 + * General Public License Version 2 only ("GPL") or the Common
  159.14 + * Development and Distribution License("CDDL") (collectively, the
  159.15 + * "License"). You may not use this file except in compliance with the
  159.16 + * License. You can obtain a copy of the License at
  159.17 + * http://www.netbeans.org/cddl-gplv2.html
  159.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  159.19 + * specific language governing permissions and limitations under the
  159.20 + * License.  When distributing the software, include this License Header
  159.21 + * Notice in each file and include the License file at
  159.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  159.23 + * particular file as subject to the "Classpath" exception as provided
  159.24 + * by Oracle in the GPL Version 2 section of the License file that
  159.25 + * accompanied this code. If applicable, add the following below the
  159.26 + * License Header, with the fields enclosed by brackets [] replaced by
  159.27 + * your own identifying information:
  159.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  159.29 + *
  159.30 + * Contributor(s):
  159.31 + *
  159.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  159.33 + */
  159.34 +package org.netbeans.modules.python.source;
  159.35 +
  159.36 +import java.util.ArrayList;
  159.37 +import java.util.Collections;
  159.38 +import java.util.List;
  159.39 +import javax.swing.ImageIcon;
  159.40 +import org.netbeans.modules.csl.api.ElementHandle;
  159.41 +import org.netbeans.modules.csl.api.ElementKind;
  159.42 +import org.netbeans.modules.csl.api.HtmlFormatter;
  159.43 +import org.netbeans.modules.csl.api.Modifier;
  159.44 +import org.netbeans.modules.csl.api.StructureItem;
  159.45 +import org.netbeans.modules.python.source.elements.AstElement;
  159.46 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  159.47 +import org.openide.util.ImageUtilities;
  159.48 +import org.python.antlr.PythonTree;
  159.49 +import org.python.antlr.ast.ClassDef;
  159.50 +import org.python.antlr.ast.FunctionDef;
  159.51 +
  159.52 +public final class PythonStructureItem extends AstElement implements StructureItem {
  159.53 +    private List<PythonStructureItem> children;
  159.54 +    private PythonStructureItem parent;
  159.55 +
  159.56 +    public PythonStructureItem(SymbolTable scopes, ClassDef def) {
  159.57 +        this(scopes, def, def.getInternalName(), ElementKind.CLASS);
  159.58 +    }
  159.59 +
  159.60 +    public PythonStructureItem(SymbolTable scopes, FunctionDef def) {
  159.61 +        this(scopes, def, def.getInternalName(), ElementKind.METHOD);
  159.62 +        if ("__init__".equals(name)) { // NOI18N
  159.63 +            kind = ElementKind.CONSTRUCTOR;
  159.64 +        }
  159.65 +    }
  159.66 +    
  159.67 +    public PythonStructureItem(SymbolTable scopes, PythonTree node, String name, ElementKind kind) {
  159.68 +        super(scopes, node, name, kind);
  159.69 +        this.node = node;
  159.70 +        this.name = name;
  159.71 +        this.kind = kind;
  159.72 +    }
  159.73 +
  159.74 +    void add(PythonStructureItem child) {
  159.75 +        if (children == null) {
  159.76 +            children = new ArrayList<>();
  159.77 +        }
  159.78 +        children.add(child);
  159.79 +        child.parent = this;
  159.80 +    }
  159.81 +
  159.82 +    @Override
  159.83 +    public String getSortText() {
  159.84 +        return name;
  159.85 +    }
  159.86 +
  159.87 +    @Override
  159.88 +    public String getHtml(HtmlFormatter formatter) {
  159.89 +        formatter.appendText(name);
  159.90 +        if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
  159.91 +            FunctionDef def = (FunctionDef)node;
  159.92 +            List<String> params = PythonAstUtils.getParameters(def);
  159.93 +            if (params.size() > 0) {
  159.94 +                boolean isFirst = true;
  159.95 +                formatter.appendHtml("(");
  159.96 +                formatter.parameters(true);
  159.97 +                for (String param : params) {
  159.98 +                    if (isFirst) {
  159.99 +                        isFirst = false;
 159.100 +                    } else {
 159.101 +                        formatter.appendText(",");
 159.102 +                    }
 159.103 +                    formatter.appendText(param);
 159.104 +                }
 159.105 +                formatter.parameters(false);
 159.106 +                formatter.appendHtml(")");
 159.107 +            }
 159.108 +        }
 159.109 +        return formatter.getText();
 159.110 +    }
 159.111 +
 159.112 +    @Override
 159.113 +    public ElementHandle getElementHandle() {
 159.114 +        return null;
 159.115 +    }
 159.116 +
 159.117 +    @Override
 159.118 +    public boolean isLeaf() {
 159.119 +        return children == null;
 159.120 +    }
 159.121 +
 159.122 +    @Override
 159.123 +    public List<? extends StructureItem> getNestedItems() {
 159.124 +        return children == null ? Collections.<StructureItem>emptyList() : children;
 159.125 +    }
 159.126 +
 159.127 +    @Override
 159.128 +    public long getPosition() {
 159.129 +        return node.getCharStartIndex();
 159.130 +    }
 159.131 +
 159.132 +    @Override
 159.133 +    public long getEndPosition() {
 159.134 +        return node.getCharStopIndex();
 159.135 +    }
 159.136 +
 159.137 +    @Override
 159.138 +    public ImageIcon getCustomIcon() {
 159.139 +        if (kind == ElementKind.CLASS && getModifiers().contains(Modifier.PRIVATE)) {
 159.140 +            // GSF doesn't automatically handle icons on private classes, so I have to
 159.141 +            // work around that here
 159.142 +            return ImageUtilities.loadImageIcon("org/netbeans/modules/python/editor/resources/private-class.png", false); //NOI18N
 159.143 +        }
 159.144 +
 159.145 +        return null;
 159.146 +    }
 159.147 +
 159.148 +    @Override
 159.149 +    public Object getSignature() {
 159.150 +        if ((kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) && parent != null &&
 159.151 +                parent.kind == ElementKind.CLASS) {
 159.152 +            return parent.name + "." + name;
 159.153 +        }
 159.154 +        return super.getSignature();
 159.155 +    }
 159.156 +
 159.157 +    @Override
 159.158 +    public boolean equals(Object obj) {
 159.159 +        if (obj == null) {
 159.160 +            return false;
 159.161 +        }
 159.162 +        if (getClass() != obj.getClass()) {
 159.163 +            return false;
 159.164 +        }
 159.165 +        final PythonStructureItem other = (PythonStructureItem)obj;
 159.166 +        if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
 159.167 +            return false;
 159.168 +        }
 159.169 +        if (this.kind != other.kind) {
 159.170 +            return false;
 159.171 +        }
 159.172 +        if (this.getModifiers() != other.getModifiers() && (this.modifiers == null || !this.modifiers.equals(other.modifiers))) {
 159.173 +            return false;
 159.174 +        }
 159.175 +
 159.176 +        if ((kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) && node != null && other.node != null) {
 159.177 +            FunctionDef def = (FunctionDef)node;
 159.178 +            List<String> params = PythonAstUtils.getParameters(def);
 159.179 +            List<String> otherParams = PythonAstUtils.getParameters((FunctionDef)other.node);
 159.180 +            if (!params.equals((otherParams))) {
 159.181 +                return false;
 159.182 +            }
 159.183 +        }
 159.184 +
 159.185 +//        if (this.getNestedItems().size() != other.getNestedItems().size()) {
 159.186 +//            return false;
 159.187 +//        }
 159.188 +//
 159.189 +        return true;
 159.190 +    }
 159.191 +
 159.192 +    @Override
 159.193 +    public int hashCode() {
 159.194 +        int hash = 7;
 159.195 +        hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0);
 159.196 +        return hash;
 159.197 +    }
 159.198 +}
   160.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   160.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonStructureScanner.java	Sun Sep 13 11:47:42 2015 +0200
   160.3 @@ -0,0 +1,274 @@
   160.4 +/*
   160.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   160.6 + *
   160.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   160.8 + *
   160.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  160.10 + * Other names may be trademarks of their respective owners.
  160.11 + *
  160.12 + * The contents of this file are subject to the terms of either the GNU
  160.13 + * General Public License Version 2 only ("GPL") or the Common
  160.14 + * Development and Distribution License("CDDL") (collectively, the
  160.15 + * "License"). You may not use this file except in compliance with the
  160.16 + * License. You can obtain a copy of the License at
  160.17 + * http://www.netbeans.org/cddl-gplv2.html
  160.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  160.19 + * specific language governing permissions and limitations under the
  160.20 + * License.  When distributing the software, include this License Header
  160.21 + * Notice in each file and include the License file at
  160.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  160.23 + * particular file as subject to the "Classpath" exception as provided
  160.24 + * by Oracle in the GPL Version 2 section of the License file that
  160.25 + * accompanied this code. If applicable, add the following below the
  160.26 + * License Header, with the fields enclosed by brackets [] replaced by
  160.27 + * your own identifying information:
  160.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  160.29 + *
  160.30 + * Contributor(s):
  160.31 + *
  160.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  160.33 + */
  160.34 +package org.netbeans.modules.python.source;
  160.35 +
  160.36 +import java.util.ArrayList;
  160.37 +import java.util.Collections;
  160.38 +import java.util.HashMap;
  160.39 +import java.util.List;
  160.40 +import java.util.Map;
  160.41 +import javax.swing.text.BadLocationException;
  160.42 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  160.43 +import org.netbeans.editor.BaseDocument;
  160.44 +import org.netbeans.editor.Utilities;
  160.45 +import org.netbeans.modules.csl.api.ElementKind;
  160.46 +import org.netbeans.modules.csl.api.OffsetRange;
  160.47 +import org.netbeans.modules.csl.api.StructureItem;
  160.48 +import org.netbeans.modules.csl.api.StructureScanner;
  160.49 +import org.netbeans.modules.csl.api.StructureScanner.Configuration;
  160.50 +import org.netbeans.modules.csl.spi.GsfUtilities;
  160.51 +import org.netbeans.modules.csl.spi.ParserResult;
  160.52 +import org.netbeans.modules.python.source.scopes.ScopeInfo;
  160.53 +import org.netbeans.modules.python.source.scopes.SymInfo;
  160.54 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  160.55 +import org.openide.util.Exceptions;
  160.56 +import org.python.antlr.PythonTree;
  160.57 +import org.python.antlr.Visitor;
  160.58 +import org.python.antlr.ast.ClassDef;
  160.59 +import org.python.antlr.ast.FunctionDef;
  160.60 +import org.python.antlr.ast.Str;
  160.61 +
  160.62 +/**
  160.63 + * This class analyzes the structure of a Python parse tree
  160.64 + * and infers structure (navigation items, folds, etc.)
  160.65 + *
  160.66 + * @author Tor Norbye
  160.67 + */
  160.68 +public class PythonStructureScanner implements StructureScanner {
  160.69 +    
  160.70 +    public static AnalysisResult analyze(PythonParserResult info) {
  160.71 +        AnalysisResult analysisResult = new AnalysisResult();
  160.72 +
  160.73 +        PythonTree root = PythonAstUtils.getRoot(info);
  160.74 +        if (root != null) {
  160.75 +            SymbolTable scopes = PythonAstUtils.getParseResult(info).getSymbolTable();
  160.76 +            StructureVisitor visitor = new StructureVisitor(scopes);
  160.77 +            try {
  160.78 +                visitor.visit(root);
  160.79 +                analysisResult.setElements(visitor.getRoots());
  160.80 +            } catch (Exception ex) {
  160.81 +                Exceptions.printStackTrace(ex);
  160.82 +            }
  160.83 +        }
  160.84 +
  160.85 +        return analysisResult;
  160.86 +    }
  160.87 +
  160.88 +    @Override
  160.89 +    public List<? extends StructureItem> scan(ParserResult info) {
  160.90 +        PythonParserResult parseResult = PythonAstUtils.getParseResult(info);
  160.91 +        if (parseResult == null) {
  160.92 +            return Collections.emptyList();
  160.93 +        }
  160.94 +
  160.95 +        return getStructure(parseResult).getElements();
  160.96 +    }
  160.97 +    
  160.98 +    public PythonStructureScanner.AnalysisResult getStructure(PythonParserResult result) {
  160.99 +        // TODO Cache ! (Used to be in PythonParserResult
 160.100 +        AnalysisResult analysisResult = PythonStructureScanner.analyze(result);
 160.101 +        return analysisResult;
 160.102 +    }
 160.103 +
 160.104 +    @Override
 160.105 +    public Map<String, List<OffsetRange>> folds(ParserResult info) {
 160.106 +        PythonParserResult result = PythonAstUtils.getParseResult(info);
 160.107 +        PythonTree root = PythonAstUtils.getRoot(result);
 160.108 +        if (root == null) {
 160.109 +            return Collections.emptyMap();
 160.110 +        }
 160.111 +
 160.112 +        //TranslatedSource source = result.getTranslatedSource();
 160.113 +        //
 160.114 +        //AnalysisResult ar = result.getStructure();
 160.115 +        //
 160.116 +        //List<?extends AstElement> elements = ar.getElements();
 160.117 +        //List<StructureItem> itemList = new ArrayList<StructureItem>(elements.size());
 160.118 +
 160.119 +        BaseDocument doc = GsfUtilities.getDocument(result.getSnapshot().getSource().getFileObject(), false);
 160.120 +        if (doc != null) {
 160.121 +            try {
 160.122 +                doc.readLock(); // For Utilities.getRowEnd() access
 160.123 +                FoldVisitor visitor = new FoldVisitor((PythonParserResult) info, doc);
 160.124 +                visitor.visit(root);
 160.125 +                List<OffsetRange> codeBlocks = visitor.getCodeBlocks();
 160.126 +
 160.127 +                Map<String, List<OffsetRange>> folds = new HashMap<>();
 160.128 +                folds.put("codeblocks", codeBlocks); // NOI18N
 160.129 +
 160.130 +                return folds;
 160.131 +            } catch (Exception ex) {
 160.132 +                Exceptions.printStackTrace(ex);
 160.133 +            } finally {
 160.134 +                doc.readUnlock();
 160.135 +            }
 160.136 +        }
 160.137 +        return Collections.emptyMap();
 160.138 +    }
 160.139 +
 160.140 +    @Override
 160.141 +    public Configuration getConfiguration() {
 160.142 +        return new Configuration(true, true, -1);
 160.143 +    }
 160.144 +
 160.145 +    private static class FoldVisitor extends Visitor {
 160.146 +        private List<OffsetRange> codeBlocks = new ArrayList<>();
 160.147 +        private PythonParserResult info;
 160.148 +        private BaseDocument doc;
 160.149 +
 160.150 +        private FoldVisitor(PythonParserResult info, BaseDocument doc) {
 160.151 +            this.info = info;
 160.152 +            this.doc = doc;
 160.153 +        }
 160.154 +
 160.155 +        private void addFoldRange(PythonTree node) {
 160.156 +            OffsetRange astRange = PythonAstUtils.getRange(node);
 160.157 +
 160.158 +            OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 160.159 +            if (lexRange != OffsetRange.NONE) {
 160.160 +                try {
 160.161 +                    int startRowEnd = Utilities.getRowEnd(doc, lexRange.getStart());
 160.162 +                    if (startRowEnd < lexRange.getEnd()) {
 160.163 +                        codeBlocks.add(new OffsetRange(startRowEnd, lexRange.getEnd()));
 160.164 +                    }
 160.165 +                } catch (BadLocationException ex) {
 160.166 +                    Exceptions.printStackTrace(ex);
 160.167 +                }
 160.168 +            }
 160.169 +        }
 160.170 +
 160.171 +        @Override
 160.172 +        public Object visitClassDef(ClassDef node) throws Exception {
 160.173 +            addFoldRange(node);
 160.174 +
 160.175 +            return super.visitClassDef(node);
 160.176 +        }
 160.177 +
 160.178 +        @Override
 160.179 +        public Object visitFunctionDef(FunctionDef node) throws Exception {
 160.180 +            addFoldRange(node);
 160.181 +
 160.182 +            return super.visitFunctionDef(node);
 160.183 +        }
 160.184 +
 160.185 +        @Override
 160.186 +        public Object visitStr(Str node) throws Exception {
 160.187 +            addFoldRange(node);
 160.188 +            return super.visitStr(node);
 160.189 +        }
 160.190 +
 160.191 +        public List<OffsetRange> getCodeBlocks() {
 160.192 +            return codeBlocks;
 160.193 +        }
 160.194 +    }
 160.195 +
 160.196 +    private static class StructureVisitor extends Visitor {
 160.197 +        List<PythonStructureItem> roots = new ArrayList<>();
 160.198 +        List<PythonStructureItem> stack = new ArrayList<>();
 160.199 +        SymbolTable scopes;
 160.200 +
 160.201 +        StructureVisitor(SymbolTable scopes) {
 160.202 +            this.scopes = scopes;
 160.203 +        }
 160.204 +
 160.205 +        private List<PythonStructureItem> getRoots() {
 160.206 +            return roots;
 160.207 +        }
 160.208 +
 160.209 +        @Override
 160.210 +        public Object visitClassDef(ClassDef def) throws Exception {
 160.211 +            PythonStructureItem item = new PythonStructureItem(scopes, def);
 160.212 +            add(item);
 160.213 +
 160.214 +            ScopeInfo scope = scopes.getScopeInfo(def);
 160.215 +            if (scope != null && scope.attributes.size() > 0) {
 160.216 +                for (Map.Entry<String, SymInfo> entry : scope.attributes.entrySet()) {
 160.217 +                    // TODO - sort these puppies? Right now their natural order will be
 160.218 +                    // random (hashkey dependent) instead of by source position or by name
 160.219 +                    SymInfo sym = entry.getValue();
 160.220 +                    if (sym.node != null) {
 160.221 +                        String name = entry.getKey();
 160.222 +                        PythonStructureItem attribute = new PythonStructureItem(scopes, sym.node, name, ElementKind.ATTRIBUTE);
 160.223 +                        item.add(attribute);
 160.224 +                    }
 160.225 +                }
 160.226 +            }
 160.227 +
 160.228 +            stack.add(item);
 160.229 +            Object result = super.visitClassDef(def);
 160.230 +            stack.remove(stack.size() - 1);
 160.231 +
 160.232 +            return result;
 160.233 +        }
 160.234 +
 160.235 +        @Override
 160.236 +        public Object visitFunctionDef(FunctionDef def) throws Exception {
 160.237 +            PythonStructureItem item = new PythonStructureItem(scopes, def);
 160.238 +
 160.239 +            add(item);
 160.240 +            stack.add(item);
 160.241 +            Object result = super.visitFunctionDef(def);
 160.242 +            stack.remove(stack.size() - 1);
 160.243 +
 160.244 +            return result;
 160.245 +        }
 160.246 +
 160.247 +        private void add(PythonStructureItem child) {
 160.248 +            PythonStructureItem parent = stack.size() > 0 ? stack.get(stack.size() - 1) : null;
 160.249 +            if (parent == null) {
 160.250 +                roots.add(child);
 160.251 +            } else {
 160.252 +                parent.add(child);
 160.253 +            }
 160.254 +        }
 160.255 +    }
 160.256 +
 160.257 +    public static class AnalysisResult {
 160.258 +        //private List<?extends AstElement> elements;
 160.259 +        private List<PythonStructureItem> elements;
 160.260 +
 160.261 +        private AnalysisResult() {
 160.262 +        }
 160.263 +
 160.264 +        //private void setElements(List<?extends AstElement> elements) {
 160.265 +        private void setElements(List<PythonStructureItem> elements) {
 160.266 +            this.elements = elements;
 160.267 +        }
 160.268 +
 160.269 +        //public List<?extends AstElement> getElements() {
 160.270 +        public List<PythonStructureItem> getElements() {
 160.271 +            if (elements == null) {
 160.272 +                return Collections.emptyList();
 160.273 +            }
 160.274 +            return elements;
 160.275 +        }
 160.276 +    }
 160.277 +}
   161.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   161.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonUtils.java	Sun Sep 13 11:47:42 2015 +0200
   161.3 @@ -0,0 +1,506 @@
   161.4 +/*
   161.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   161.6 + *
   161.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   161.8 + *
   161.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  161.10 + * Other names may be trademarks of their respective owners.
  161.11 + *
  161.12 + * The contents of this file are subject to the terms of either the GNU
  161.13 + * General Public License Version 2 only ("GPL") or the Common
  161.14 + * Development and Distribution License("CDDL") (collectively, the
  161.15 + * "License"). You may not use this file except in compliance with the
  161.16 + * License. You can obtain a copy of the License at
  161.17 + * http://www.netbeans.org/cddl-gplv2.html
  161.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  161.19 + * specific language governing permissions and limitations under the
  161.20 + * License.  When distributing the software, include this License Header
  161.21 + * Notice in each file and include the License file at
  161.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  161.23 + * particular file as subject to the "Classpath" exception as provided
  161.24 + * by Oracle in the GPL Version 2 section of the License file that
  161.25 + * accompanied this code. If applicable, add the following below the
  161.26 + * License Header, with the fields enclosed by brackets [] replaced by
  161.27 + * your own identifying information:
  161.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  161.29 + *
  161.30 + * Contributor(s):
  161.31 + *
  161.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  161.33 + */
  161.34 +package org.netbeans.modules.python.source;
  161.35 +
  161.36 +import java.util.Comparator;
  161.37 +import java.util.List;
  161.38 +import javax.swing.text.Document;
  161.39 +import org.netbeans.api.annotations.common.NonNull;
  161.40 +import org.netbeans.api.project.FileOwnerQuery;
  161.41 +import org.netbeans.api.project.Project;
  161.42 +import org.netbeans.api.project.ProjectUtils;
  161.43 +import org.netbeans.api.project.SourceGroup;
  161.44 +import org.netbeans.api.project.Sources;
  161.45 +import org.netbeans.modules.python.api.PythonMIMEResolver;
  161.46 +import org.netbeans.modules.python.api.PythonPlatform;
  161.47 +import org.netbeans.modules.python.api.PythonPlatformManager;
  161.48 +import org.openide.filesystems.FileObject;
  161.49 +import org.openide.filesystems.FileUtil;
  161.50 +import org.openide.util.NbBundle;
  161.51 +import org.python.antlr.PythonTree;
  161.52 +import org.python.antlr.ast.Attribute;
  161.53 +import org.python.antlr.ast.Name;
  161.54 +
  161.55 +/**
  161.56 + *
  161.57 + * @author Tor Norbye
  161.58 + */
  161.59 +public class PythonUtils {
  161.60 +    public static boolean canContainPython(FileObject f) {
  161.61 +        String mimeType = f.getMIMEType();
  161.62 +        return PythonMIMEResolver.PYTHON_MIME_TYPE.equals(mimeType);
  161.63 +    // TODO:       "text/x-yaml".equals(mimeType) ||  // NOI18N
  161.64 +    // RubyInstallation.RHTML_MIME_TYPE.equals(mimeType);
  161.65 +    }
  161.66 +
  161.67 +    public static boolean isPythonFile(FileObject f) {
  161.68 +        return PythonMIMEResolver.PYTHON_MIME_TYPE.equals(f.getMIMEType());
  161.69 +    }
  161.70 +
  161.71 +    public static boolean isRstFile(FileObject f) {
  161.72 +        return "rst".equals(f.getExt()); // NOI18N
  161.73 +    }
  161.74 +
  161.75 +    public static boolean isPythonDocument(Document doc) {
  161.76 +        String mimeType = (String)doc.getProperty("mimeType"); // NOI18N
  161.77 +
  161.78 +        return PythonMIMEResolver.PYTHON_MIME_TYPE.equals(mimeType);
  161.79 +    }
  161.80 +    public static final String DOT__INIT__ = ".__init__"; // NOI18N
  161.81 +
  161.82 +    // From PythonProjectType
  161.83 +    public static final String SOURCES_TYPE_PYTHON = "python"; // NOI18N
  161.84 +
  161.85 +    // Cache
  161.86 +    private static FileObject prevParent;
  161.87 +    private static String prevRootUrl;
  161.88 +
  161.89 +    /**
  161.90 +     * Produce the module name (including packages) for a given python source file.
  161.91 +     * 
  161.92 +     * @param fo The source file (can be null, if file is not))
  161.93 +     * @param file The parser file (can be null, if fo is not).
  161.94 +     * @param fileName The filename (basename only)
  161.95 +     * @param projectRelativeName If non null, the path from the project root down to this file
  161.96 +     * @return A string for the full package module name
  161.97 +     */
  161.98 +    public static String getModuleName(@NonNull FileObject fo) {
  161.99 +
 161.100 +        // TODO - use PythonPlatform's library roots!
 161.101 +
 161.102 +        String module = fo.getName();
 161.103 +
 161.104 +        // First see if we're on the load path for the platform, and if so,
 161.105 +        // use that as the base
 161.106 +        // TODO - look up platform for the current search context instead of all platforms!!
 161.107 +        if (fo.getParent() != prevParent) {
 161.108 +            prevRootUrl = null;
 161.109 +            prevParent = fo.getParent();
 161.110 +        }
 161.111 +
 161.112 +        String url = fo.toURL().toExternalForm();
 161.113 +        if (prevRootUrl == null) {
 161.114 +            boolean found = false;
 161.115 +            PythonPlatformManager manager = PythonPlatformManager.getInstance();
 161.116 +
 161.117 +            PlatformSearch:
 161.118 +            for (String name : manager.getPlatformList()) {
 161.119 +                PythonPlatform platform = manager.getPlatform(name);
 161.120 +                if (platform != null) {
 161.121 +                    List<FileObject> unique = platform.getUniqueLibraryRoots();
 161.122 +                    for (FileObject root : unique) {
 161.123 +                        if (FileUtil.isParentOf(root, fo)) {
 161.124 +                            for (FileObject r : platform.getLibraryRoots()) {
 161.125 +                                if (FileUtil.isParentOf(r, fo)) {
 161.126 +                                    // See if the folder itself contains
 161.127 +                                    // an __init__.py file - if it does,
 161.128 +                                    // then include the directory itself
 161.129 +                                    // in the package name.
 161.130 +                                    if (r.getFileObject("__init__.py") != null) { // NOI18N
 161.131 +                                        r = r.getParent();
 161.132 +                                    }
 161.133 +
 161.134 +                                    prevRootUrl = r.toURL().toExternalForm();
 161.135 +                                    found = true;
 161.136 +                                    break PlatformSearch;
 161.137 +                                }
 161.138 +                            }
 161.139 +                            break PlatformSearch;
 161.140 +                        }
 161.141 +                    }
 161.142 +                }
 161.143 +            }
 161.144 +
 161.145 +            if (!found) {
 161.146 +                Project project = FileOwnerQuery.getOwner(fo);
 161.147 +                if (project != null) {
 161.148 +                    Sources source = ProjectUtils.getSources(project);
 161.149 +                    // Look up the source path
 161.150 +                    SourceGroup[] sourceGroups = source.getSourceGroups(SOURCES_TYPE_PYTHON);
 161.151 +                    for (SourceGroup group : sourceGroups) {
 161.152 +                        FileObject folder = group.getRootFolder();
 161.153 +                        if (FileUtil.isParentOf(folder, fo)) {
 161.154 +                            // See if the folder itself contains
 161.155 +                            // an __init__.py file - if it does,
 161.156 +                            // then include the directory itself
 161.157 +                            // in the package name.
 161.158 +                            if (folder.getFileObject("__init__.py") != null) { // NOI18N
 161.159 +                                folder = folder.getParent();
 161.160 +                            }
 161.161 +
 161.162 +                            prevRootUrl = folder.toURL().toExternalForm();
 161.163 +                            break;
 161.164 +                        }
 161.165 +                    }
 161.166 +                }
 161.167 +            }
 161.168 +        }
 161.169 +
 161.170 +        if (prevRootUrl != null) {
 161.171 +            module = url.substring(prevRootUrl.length());
 161.172 +            if (module.startsWith("/")) {
 161.173 +                module = module.substring(1);
 161.174 +            }
 161.175 +        }
 161.176 +
 161.177 +        // Strip off .y extension
 161.178 +        if (module.endsWith(".py")) { // NOI18N
 161.179 +            module = module.substring(0, module.length() - 3);
 161.180 +        }
 161.181 +
 161.182 +        if (module.indexOf('/') != -1) {
 161.183 +            module = module.replace('/', '.');
 161.184 +        }
 161.185 +
 161.186 +        if (module.endsWith(DOT__INIT__)) {
 161.187 +            module = module.substring(0, module.length() - DOT__INIT__.length());
 161.188 +        }
 161.189 +
 161.190 +        return module;
 161.191 +    }
 161.192 +
 161.193 +    // Keywords - according to http://docs.python.org/ref/keywords.html
 161.194 +    static final String[] PYTHON_KEYWORDS = new String[]{
 161.195 +        "and", // NOI18N
 161.196 +        "as", // NOI18N
 161.197 +        "assert", // NOI18N
 161.198 +        "break", // NOI18N
 161.199 +        "class", // NOI18N
 161.200 +        "continue", // NOI18N
 161.201 +        "def", // NOI18N
 161.202 +        "del", // NOI18N
 161.203 +        "elif", // NOI18N
 161.204 +        "else", // NOI18N
 161.205 +        "except", // NOI18N
 161.206 +        "exec", // NOI18N
 161.207 +        "finally", // NOI18N
 161.208 +        "for", // NOI18N
 161.209 +        "from", // NOI18N
 161.210 +        "global", // NOI18N
 161.211 +        "if", // NOI18N
 161.212 +        "import", // NOI18N
 161.213 +        "in", // NOI18N
 161.214 +        "is", // NOI18N
 161.215 +        "lambda", // NOI18N
 161.216 +        "not", // NOI18N
 161.217 +        "or", // NOI18N
 161.218 +        "pass", // NOI18N
 161.219 +        "print", // NOI18N
 161.220 +        "raise", // NOI18N
 161.221 +        "return", // NOI18N
 161.222 +        "try", // NOI18N
 161.223 +        "while", // NOI18N
 161.224 +        "with", // NOI18N
 161.225 +        "yield", // NOI18N
 161.226 +    };
 161.227 +
 161.228 +    public static boolean isPythonKeyword(String name) {
 161.229 +        for (String s : PYTHON_KEYWORDS) {
 161.230 +            if (s.equals(name)) {
 161.231 +                return true;
 161.232 +            }
 161.233 +        }
 161.234 +
 161.235 +        return false;
 161.236 +    }
 161.237 +
 161.238 +    /**
 161.239 +     * Return true iff the name is a class name
 161.240 +     * @param name The name
 161.241 +     * @param emptyDefault Whether empty or _ names should be considered a class name or not
 161.242 +     * @return True iff the name looks like a class name
 161.243 +     */
 161.244 +    public static boolean isClassName(String name, boolean emptyDefault) {
 161.245 +        if (name == null || name.length() == 0) {
 161.246 +            return emptyDefault;
 161.247 +        }
 161.248 +        if (name.startsWith("_") && name.length() > 1) {
 161.249 +            return Character.isUpperCase(name.charAt(1));
 161.250 +        }
 161.251 +
 161.252 +        return Character.isUpperCase(name.charAt(0));
 161.253 +    }
 161.254 +
 161.255 +    /**
 161.256 +     * Return true iff the name is a method name
 161.257 +     * @param name The name
 161.258 +     * @param emptyDefault Whether empty or _ names should be considered a class name or not
 161.259 +     * @return True iff the name looks like a method name
 161.260 +     */
 161.261 +    public static boolean isMethodName(String name, boolean emptyDefault) {
 161.262 +        if (name == null || name.length() == 0) {
 161.263 +            return emptyDefault;
 161.264 +        }
 161.265 +        if (name.startsWith("__") && name.length() > 2) {
 161.266 +            return Character.isLowerCase(name.charAt(2));
 161.267 +        }
 161.268 +        if (name.startsWith("_") && name.length() > 1) {
 161.269 +            return Character.isLowerCase(name.charAt(1));
 161.270 +        }
 161.271 +
 161.272 +        return Character.isLowerCase(name.charAt(0));
 161.273 +    }
 161.274 +
 161.275 +    public static boolean isValidPythonClassName(String name) {
 161.276 +        if (isPythonKeyword(name)) {
 161.277 +            return false;
 161.278 +        }
 161.279 +
 161.280 +        if (name.trim().length() == 0) {
 161.281 +            return false;
 161.282 +        }
 161.283 +
 161.284 +        if (!Character.isUpperCase(name.charAt(0))) {
 161.285 +            return false;
 161.286 +        }
 161.287 +
 161.288 +        for (int i = 1; i < name.length(); i++) {
 161.289 +            char c = name.charAt(i);
 161.290 +            if (!Character.isJavaIdentifierPart(c)) {
 161.291 +                return false;
 161.292 +            }
 161.293 +
 161.294 +        }
 161.295 +
 161.296 +        return true;
 161.297 +    }
 161.298 +
 161.299 +    /** Is this name a valid operator name? */
 161.300 +    public static boolean isOperator(String name) {
 161.301 +        // TODO - update to Python
 161.302 +        if (name.length() == 0) {
 161.303 +            return false;
 161.304 +        }
 161.305 +
 161.306 +        switch (name.charAt(0)) {
 161.307 +        case '+':
 161.308 +            return name.equals("+") || name.equals("+@");
 161.309 +        case '-':
 161.310 +            return name.equals("-") || name.equals("-@");
 161.311 +        case '*':
 161.312 +            return name.equals("*") || name.equals("**");
 161.313 +        case '<':
 161.314 +            return name.equals("<") || name.equals("<<") || name.equals("<=") || name.equals("<=>");
 161.315 +        case '>':
 161.316 +            return name.equals(">") || name.equals(">>") || name.equals(">=");
 161.317 +        case '=':
 161.318 +            return name.equals("=") || name.equals("==") || name.equals("===") || name.equals("=~");
 161.319 +        case '!':
 161.320 +            return name.equals("!=") || name.equals("!~");
 161.321 +        case '&':
 161.322 +            return name.equals("&") || name.equals("&&");
 161.323 +        case '|':
 161.324 +            return name.equals("|") || name.equals("||");
 161.325 +        case '[':
 161.326 +            return name.equals("[]") || name.equals("[]=");
 161.327 +        case '%':
 161.328 +            return name.equals("%");
 161.329 +        case '/':
 161.330 +            return name.equals("/");
 161.331 +        case '~':
 161.332 +            return name.equals("~");
 161.333 +        case '^':
 161.334 +            return name.equals("^");
 161.335 +        case '`':
 161.336 +            return name.equals("`");
 161.337 +        default:
 161.338 +            return false;
 161.339 +        }
 161.340 +    }
 161.341 +
 161.342 +    public static boolean isValidPythonMethodName(String name) {
 161.343 +        if (isPythonKeyword(name)) {
 161.344 +            return false;
 161.345 +        }
 161.346 +
 161.347 +        if (name.trim().length() == 0) {
 161.348 +            return false;
 161.349 +        }
 161.350 +
 161.351 +        // TODO - allow operators
 161.352 +        if (isOperator(name)) {
 161.353 +            return true;
 161.354 +        }
 161.355 +
 161.356 +        if (Character.isUpperCase(name.charAt(0)) || Character.isWhitespace(name.charAt(0))) {
 161.357 +            return false;
 161.358 +        }
 161.359 +
 161.360 +        for (int i = 0; i < name.length(); i++) {
 161.361 +            char c = name.charAt(i);
 161.362 +            if (!(Character.isLetterOrDigit(c) || c == '_')) {
 161.363 +                return false;
 161.364 +            }
 161.365 +
 161.366 +        }
 161.367 +
 161.368 +        return true;
 161.369 +    }
 161.370 +
 161.371 +    public static boolean isValidPythonIdentifier(String name) {
 161.372 +        if (isPythonKeyword(name)) {
 161.373 +            return false;
 161.374 +        }
 161.375 +
 161.376 +        if (name.trim().length() == 0) {
 161.377 +            return false;
 161.378 +        }
 161.379 +
 161.380 +        for (int i = 0; i < name.length(); i++) {
 161.381 +            // Identifier char isn't really accurate - I can have a function named "[]" etc.
 161.382 +            // so just look for -obvious- mistakes
 161.383 +            if (Character.isWhitespace(name.charAt(i))) {
 161.384 +                return false;
 161.385 +            }
 161.386 +
 161.387 +        // TODO - make this more accurate, like the method validifier
 161.388 +        }
 161.389 +
 161.390 +        return true;
 161.391 +    }
 161.392 +
 161.393 +    /**
 161.394 +     * Ruby identifiers should consist of [a-zA-Z0-9_]
 161.395 +     * http://www.headius.com/rubyspec/index.php/Variables
 161.396 +     * <p>
 161.397 +     * This method also accepts the field/global chars
 161.398 +     * since it's unlikely
 161.399 +     */
 161.400 +    public static boolean isSafeIdentifierName(String name, int fromIndex) {
 161.401 +        int i = fromIndex;
 161.402 +        for (; i < name.length(); i++) {
 161.403 +            char c = name.charAt(i);
 161.404 +            if (!(c == '$' || c == '@' || c == ':')) {
 161.405 +                break;
 161.406 +            }
 161.407 +        }
 161.408 +        for (; i < name.length(); i++) {
 161.409 +            char c = name.charAt(i);
 161.410 +            if (!((c >= 'a' && c <= 'z') || (c == '_') ||
 161.411 +                    (c >= 'A' && c <= 'Z') ||
 161.412 +                    (c >= '0' && c <= '9') ||
 161.413 +                    (c == '?') || (c == '=') || (c == '!'))) { // Method suffixes; only allowed on the last line
 161.414 +
 161.415 +                if (isOperator(name)) {
 161.416 +                    return true;
 161.417 +                }
 161.418 +
 161.419 +                return false;
 161.420 +            }
 161.421 +        }
 161.422 +
 161.423 +        return true;
 161.424 +    }
 161.425 +
 161.426 +    /**
 161.427 +     * Return null if the given identifier name is valid, otherwise a localized
 161.428 +     * error message explaining the problem.
 161.429 +     */
 161.430 +    public static String getIdentifierWarning(String name, int fromIndex) {
 161.431 +        if (isSafeIdentifierName(name, fromIndex)) {
 161.432 +            return null;
 161.433 +        } else {
 161.434 +            return NbBundle.getMessage(PythonUtils.class, "UnsafeIdentifierName");
 161.435 +        }
 161.436 +    }
 161.437 +
 161.438 +    /** @todo Move into GsfUtilities after 6.5 */
 161.439 +    public static int getOffsetByLineCol(String source, int line, int col) {
 161.440 +        int offset = 0;
 161.441 +        for (int i = 0; i < line; i++) {
 161.442 +            offset = source.indexOf('\n', offset);
 161.443 +            if (offset == -1) {
 161.444 +                offset = source.length();
 161.445 +                break;
 161.446 +            }
 161.447 +            offset++;
 161.448 +        }
 161.449 +        if (col > 0) { // -1: invalid
 161.450 +            offset += col;
 161.451 +        }
 161.452 +
 161.453 +        return offset;
 161.454 +    }
 161.455 +    public static Comparator NAME_NODE_COMPARATOR = new Comparator<Name>() {
 161.456 +        @Override
 161.457 +        public int compare(Name n1, Name n2) {
 161.458 +            return n1.getInternalId().compareTo(n2.getInternalId());
 161.459 +        }
 161.460 +    };
 161.461 +    public static Comparator ATTRIBUTE_NAME_NODE_COMPARATOR = new Comparator<Object>() {
 161.462 +        @SuppressWarnings("unchecked")
 161.463 +        @Override
 161.464 +        public int compare(Object n1, Object n2) {
 161.465 +            String s1 = "";
 161.466 +            String s2 = "";
 161.467 +
 161.468 +            if (n1 instanceof Name) {
 161.469 +                s1 = ((Name)n1).getInternalId();
 161.470 +            } else if (n1 instanceof Attribute) {
 161.471 +                Attribute a = (Attribute)n1;
 161.472 +                String v = PythonAstUtils.getName(a.getInternalValue());
 161.473 +                if (v != null) {
 161.474 +                    s1 = a.getInternalAttr() + "." + v;
 161.475 +                } else {
 161.476 +                    s1 = a.getInternalAttr();
 161.477 +                }
 161.478 +            }
 161.479 +
 161.480 +            if (n2 instanceof Name) {
 161.481 +                s2 = ((Name)n2).getInternalId();
 161.482 +            } else if (n2 instanceof Attribute) {
 161.483 +                Attribute a = (Attribute)n2;
 161.484 +                String v = PythonAstUtils.getName(a.getInternalValue());
 161.485 +                if (v != null) {
 161.486 +                    s2 = a.getInternalAttr() + "." + v;
 161.487 +                } else {
 161.488 +                    s2 = a.getInternalAttr();
 161.489 +                }
 161.490 +            }
 161.491 +
 161.492 +            return s1.compareTo(s2);
 161.493 +        }
 161.494 +    };
 161.495 +    public static Comparator NODE_POS_COMPARATOR = new Comparator<PythonTree>() {
 161.496 +        @Override
 161.497 +        public int compare(PythonTree p1, PythonTree p2) {
 161.498 +            int ret = p1.getCharStartIndex() - p2.getCharStartIndex();
 161.499 +            if (ret != 0) {
 161.500 +                return ret;
 161.501 +            }
 161.502 +            ret = p2.getCharStopIndex() - p1.getCharStopIndex();
 161.503 +            if (ret != 0) {
 161.504 +                return ret;
 161.505 +            }
 161.506 +            return p2.getAntlrType() - p1.getAntlrType();
 161.507 +        }
 161.508 +    };
 161.509 +}
   162.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   162.2 +++ b/python.source/src/org/netbeans/modules/python/source/RstFormatter.java	Sun Sep 13 11:47:42 2015 +0200
   162.3 @@ -0,0 +1,1342 @@
   162.4 +/*
   162.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   162.6 + *
   162.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   162.8 + *
   162.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  162.10 + * Other names may be trademarks of their respective owners.
  162.11 + *
  162.12 + * The contents of this file are subject to the terms of either the GNU
  162.13 + * General Public License Version 2 only ("GPL") or the Common
  162.14 + * Development and Distribution License("CDDL") (collectively, the
  162.15 + * "License"). You may not use this file except in compliance with the
  162.16 + * License. You can obtain a copy of the License at
  162.17 + * http://www.netbeans.org/cddl-gplv2.html
  162.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  162.19 + * specific language governing permissions and limitations under the
  162.20 + * License.  When distributing the software, include this License Header
  162.21 + * Notice in each file and include the License file at
  162.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  162.23 + * particular file as subject to the "Classpath" exception as provided
  162.24 + * by Oracle in the GPL Version 2 section of the License file that
  162.25 + * accompanied this code. If applicable, add the following below the
  162.26 + * License Header, with the fields enclosed by brackets [] replaced by
  162.27 + * your own identifying information:
  162.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  162.29 + *
  162.30 + * If you wish your version of this file to be governed by only the CDDL
  162.31 + * or only the GPL Version 2, indicate your decision by adding
  162.32 + * "[Contributor] elects to include this software in this distribution
  162.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  162.34 + * single choice of license, a recipient has the option to distribute
  162.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  162.36 + * to extend the choice of license to its licensees as provided above.
  162.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  162.38 + * Version 2 license, then the option applies only if the new code is
  162.39 + * made subject to such option by the copyright holder.
  162.40 + *
  162.41 + * Contributor(s):
  162.42 + *
  162.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  162.44 + */
  162.45 +package org.netbeans.modules.python.source;
  162.46 +
  162.47 +import java.awt.Color;
  162.48 +import java.io.CharConversionException;
  162.49 +import java.util.ArrayList;
  162.50 +import java.util.Collections;
  162.51 +import java.util.List;
  162.52 +import javax.swing.text.AttributeSet;
  162.53 +import javax.swing.text.BadLocationException;
  162.54 +import javax.swing.text.StyleConstants;
  162.55 +import org.netbeans.api.editor.mimelookup.MimeLookup;
  162.56 +import org.netbeans.api.editor.mimelookup.MimePath;
  162.57 +import org.netbeans.api.editor.settings.FontColorSettings;
  162.58 +import org.netbeans.api.lexer.Language;
  162.59 +import org.netbeans.api.lexer.Token;
  162.60 +import org.netbeans.api.lexer.TokenHierarchy;
  162.61 +import org.netbeans.api.lexer.TokenSequence;
  162.62 +import org.netbeans.editor.BaseDocument;
  162.63 +import org.netbeans.modules.csl.api.ElementHandle;
  162.64 +import org.netbeans.modules.csl.api.ElementKind;
  162.65 +import org.netbeans.modules.csl.spi.GsfUtilities;
  162.66 +import org.netbeans.modules.csl.spi.ParserResult;
  162.67 +import org.netbeans.modules.python.api.PythonMIMEResolver;
  162.68 +import org.netbeans.modules.python.source.elements.Element;
  162.69 +import org.netbeans.modules.python.source.elements.IndexedElement;
  162.70 +import org.netbeans.modules.python.source.elements.IndexedMethod;
  162.71 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
  162.72 +import org.openide.filesystems.FileObject;
  162.73 +import org.openide.util.Exceptions;
  162.74 +import org.openide.util.Lookup;
  162.75 +import org.openide.xml.XMLUtil;
  162.76 +import org.python.antlr.PythonTree;
  162.77 +
  162.78 +/**
  162.79 + * Support for reStructured text. Parse .rst files and rst content in
  162.80 + * Python doc strings and format it as HTML. Also provide functions
  162.81 + * to locate a code element in RST files.
  162.82 + * @see http://www.python.org/dev/peps/pep-0287/
  162.83 + * @see http://docutils.sourceforge.net/docs/user/rst/quickstart.html
  162.84 + *
  162.85 + * @todo Render verbatim blocks
  162.86 + * @todo Syntax highlight verbatim blocks?
  162.87 + * @todo Render *bold* and `identifier` stuff
  162.88 + * @todo For class definitions which nest the method documentation,
  162.89 + *    try to remove all items, or perhaps just make it shorter
  162.90 + * @todo Render note:: into something cleaner etc.
  162.91 + *
  162.92 + * @author Tor Norbye
  162.93 + */
  162.94 +public class RstFormatter {
  162.95 +    private static final String BRBR = "\n<br><br>\n"; // NOI18N
  162.96 +    private StringBuilder sb = new StringBuilder();
  162.97 +    private boolean lastWasEmpty = false;
  162.98 +    private int beginPos;
  162.99 +    private boolean inVerbatim;
 162.100 +    private boolean inIndex;
 162.101 +    private boolean inTable;
 162.102 +    private boolean inDiv;
 162.103 +    private int lastIndent;
 162.104 +    private boolean maybeVerbatim;
 162.105 +    private boolean inDocTest;
 162.106 +    private List<String> code;
 162.107 +
 162.108 +    public RstFormatter() {
 162.109 +    }
 162.110 +
 162.111 +    private void flush() {
 162.112 +        if (inTable) {
 162.113 +            sb.append("</pre>\n"); // NOI18N
 162.114 +            inTable = false;
 162.115 +            inVerbatim = false;
 162.116 +        } else if (inVerbatim) {
 162.117 +            // Process code and format as Python
 162.118 +            String html = getPythonHtml(code, true);
 162.119 +            if (html != null) {
 162.120 +                // <pre> tag is added as part of the rubyhtml (since it
 162.121 +                // needs to pick up the background color from the syntax
 162.122 +                // coloring settings)
 162.123 +                sb.append(html);
 162.124 +            } else {
 162.125 +                sb.append("<pre style=\"margin: 5px 5px; background: #ffffdd; border-size: 1px; padding: 5px\">"); // NOI18N
 162.126 +                sb.append("\n"); // NOI18N
 162.127 +                // Some kind of error; normal append
 162.128 +                for (String s : code) {
 162.129 +                    appendEscaped(s);
 162.130 +                    sb.append("<br>"); // NOI18N
 162.131 +                }
 162.132 +                sb.append("</pre>\n"); // NOI18N
 162.133 +            }
 162.134 +            inVerbatim = false;
 162.135 +            code = null;
 162.136 +        } else if (inDiv) {
 162.137 +            sb.append("</div>\n"); // NOI18N
 162.138 +            inDiv = false;
 162.139 +        }
 162.140 +    }
 162.141 +
 162.142 +    private void appendEscaped(char c) {
 162.143 +        if ('<' == c) {
 162.144 +            sb.append("&lt;"); // NOI18N
 162.145 +        } else if ('&' == c) {
 162.146 +            sb.append("&amp;"); // NOI18N
 162.147 +        } else {
 162.148 +            sb.append(c);
 162.149 +        }
 162.150 +    }
 162.151 +
 162.152 +    private void appendEscaped(CharSequence s) {
 162.153 +        for (int i = 0, n = s.length(); i < n; i++) {
 162.154 +            char c = s.charAt(i);
 162.155 +            if ('<' == c) {
 162.156 +                sb.append("&lt;"); // NOI18N
 162.157 +            } else if ('&' == c) {
 162.158 +                sb.append("&amp;"); // NOI18N
 162.159 +            } else {
 162.160 +                sb.append(c);
 162.161 +            }
 162.162 +        }
 162.163 +    }
 162.164 +
 162.165 +    private int appendColonCmd(String line, int i, String marker, boolean url) throws CharConversionException {
 162.166 +        String MARKER = ":" + marker + ":`"; // NOI18N
 162.167 +        if (line.startsWith(MARKER, i)) {
 162.168 +            int end = line.indexOf("`", i + MARKER.length()); // NOI18N
 162.169 +            if (end != -1) {
 162.170 +                String token = line.substring(i + MARKER.length(), end);
 162.171 +                if (url) {
 162.172 +                    sb.append("<a href=\""); // NOI18N
 162.173 +                    if ("pep".equals(marker)) { // NOI18N
 162.174 +                        sb.append("http://www.python.org/dev/peps/pep-"); // NOI18N
 162.175 +                        for (int j = 0; j < 4 - token.length(); j++) {
 162.176 +                            sb.append("0");
 162.177 +                        }
 162.178 +                        sb.append(token);
 162.179 +                        sb.append("/"); // NOI18N
 162.180 +                        sb.append("\">PEP "); // NOI18N
 162.181 +                        sb.append(token);
 162.182 +                        sb.append("</a>");
 162.183 +                        return end;
 162.184 +                    } else {
 162.185 +                        sb.append(marker);
 162.186 +                        sb.append(":"); // NOI18N
 162.187 +                        appendEscaped(token);
 162.188 +                    }
 162.189 +                    sb.append("\">"); // NOI18N
 162.190 +                } else if (marker.equals("keyword")) { // NOI18N
 162.191 +                    sb.append("<code style=\""); // NOI18N
 162.192 +
 162.193 +                    MimePath mimePath = MimePath.parse(PythonMIMEResolver.PYTHON_MIME_TYPE);
 162.194 +                    Lookup lookup = MimeLookup.getLookup(mimePath);
 162.195 +                    FontColorSettings fcs = lookup.lookup(FontColorSettings.class);
 162.196 +
 162.197 +                    AttributeSet attribs = fcs.getTokenFontColors("keyword"); // NOI18N
 162.198 +                    Color fg = (Color)attribs.getAttribute(StyleConstants.Foreground);
 162.199 +                    if (fg != null) {
 162.200 +                        sb.append("color:"); // NOI18N
 162.201 +                        sb.append(getHtmlColor(fg));
 162.202 +                        sb.append(";"); // NOI18N
 162.203 +                    }
 162.204 +                    Color bg = (Color)attribs.getAttribute(StyleConstants.Background);
 162.205 +                    // Only set the background for dark colors
 162.206 +                    if (bg != null && bg.getRed() < 128) {
 162.207 +                        sb.append("background:"); // NOI18N
 162.208 +                        sb.append(getHtmlColor(bg));
 162.209 +                    }
 162.210 +
 162.211 +                    sb.append("\">"); // NOI18N
 162.212 +                } else {
 162.213 +                    sb.append("<code>"); // NOI18N
 162.214 +                }
 162.215 +                appendEscaped(token);
 162.216 +                if (url) {
 162.217 +                    sb.append("</a>"); // NOI18N
 162.218 +                } else {
 162.219 +                    sb.append("</code>"); // NOI18N
 162.220 +                }
 162.221 +                //return end+1; // instead of end+2: get to end of ``, minus loop increment
 162.222 +                return end; // instead of end+2: get to end of ``, minus loop increment
 162.223 +            }
 162.224 +        }
 162.225 +
 162.226 +        return -1;
 162.227 +    }
 162.228 +
 162.229 +    private void appendRstLine(String line) throws CharConversionException {
 162.230 +        int n = line.length();
 162.231 +        char prev = 0;
 162.232 +        Loop:
 162.233 +        for (int i = 0; i < n; i++) {
 162.234 +            char c = line.charAt(i);
 162.235 +            if (c == '`') {
 162.236 +                if (i < n - 2 && line.charAt(i + 1) == '`') {
 162.237 +                    // See if it's an ``identifier``
 162.238 +                    int end = line.indexOf("``", i + 2);
 162.239 +                    if (end != -1) {
 162.240 +                        sb.append("<code>"); // NOI18N
 162.241 +                        appendEscaped(line.substring(i + 2, end));
 162.242 +                        sb.append("</code>"); // NOI18N
 162.243 +                        i = end + 1; // instead of end+2: get to end of ``, minus loop increment
 162.244 +                        continue;
 162.245 +                    }
 162.246 +                } else {
 162.247 +                    // Single identifier
 162.248 +                    for (int j = i + 1; j < n; j++) {
 162.249 +                        char d = line.charAt(j);
 162.250 +                        if (d == '`') {
 162.251 +                            sb.append("<code>"); // NOI18N
 162.252 +                            appendEscaped(line.substring(i + 1, j));
 162.253 +                            sb.append("</code>"); // NOI18N
 162.254 +                            i = j;
 162.255 +                            continue Loop;
 162.256 +                        } else if (!Character.isJavaIdentifierPart(d)) {
 162.257 +                            break;
 162.258 +                        }
 162.259 +                    }
 162.260 +                }
 162.261 +            } else if (c == ':') {
 162.262 +                int nextI = appendColonCmd(line, i, "class", true); // NOI18N
 162.263 +                if (nextI == -1) {
 162.264 +                    nextI = appendColonCmd(line, i, "exc", true); // NOI18N
 162.265 +                    if (nextI == -1) {
 162.266 +                        nextI = appendColonCmd(line, i, "var", false); // NOI18N
 162.267 +                        if (nextI == -1) {
 162.268 +                            nextI = appendColonCmd(line, i, "meth", true); // NOI18N
 162.269 +                            if (nextI == -1) {
 162.270 +                                nextI = appendColonCmd(line, i, "func", true); // NOI18N
 162.271 +                                if (nextI == -1) {
 162.272 +                                    nextI = appendColonCmd(line, i, "data", false); // NOI18N
 162.273 +                                    if (nextI == -1) {
 162.274 +                                        nextI = appendColonCmd(line, i, "attr", false); // NOI18N
 162.275 +                                        if (nextI == -1) {
 162.276 +                                            nextI = appendColonCmd(line, i, "envvar", false); // NOI18N
 162.277 +                                            if (nextI == -1) {
 162.278 +                                                nextI = appendColonCmd(line, i, "mod", true); // NOI18N
 162.279 +                                                if (nextI == -1) {
 162.280 +                                                    nextI = appendColonCmd(line, i, "pep", true); // NOI18N
 162.281 +                                                    if (nextI == -1) {
 162.282 +                                                        nextI = appendColonCmd(line, i, "ref", false); // NOI18N
 162.283 +                                                        if (nextI == -1) {
 162.284 +                                                            nextI = appendColonCmd(line, i, "mod", true); // NOI18N
 162.285 +                                                            if (nextI == -1) {
 162.286 +                                                                nextI = appendColonCmd(line, i, "keyword", false); // NOI18N
 162.287 +                                                                if (nextI == -1) {
 162.288 +                                                                    if (line.startsWith(":noindex:", i)) { // NOI18N
 162.289 +                                                                        nextI = i + 9;
 162.290 +                                                                    } else if (line.startsWith(":synopsis:", i)) { // NOI18N
 162.291 +                                                                        nextI = i + 10;
 162.292 +                                                                    } else if (line.startsWith(":deprecated:", i)) {
 162.293 +                                                                        sb.append("Deprecated. ");
 162.294 +                                                                        nextI = i + 12;
 162.295 +                                                                    } else if (line.startsWith(":platform:", i)) {
 162.296 +                                                                        sb.append("Platform: ");
 162.297 +                                                                        nextI = i + 10;
 162.298 +                                                                    }
 162.299 +                                                                }
 162.300 +                                                            }
 162.301 +                                                        }
 162.302 +                                                    }
 162.303 +                                                }
 162.304 +                                            }
 162.305 +                                        }
 162.306 +                                    }
 162.307 +                                }
 162.308 +                            }
 162.309 +                        }
 162.310 +                    }
 162.311 +                }
 162.312 +                if (nextI != -1) {
 162.313 +                    i = nextI;
 162.314 +                    continue;
 162.315 +                }
 162.316 +            } else if (c == '*') {
 162.317 +                // Bold?
 162.318 +                if (i < n - 1 && Character.isJavaIdentifierPart(line.charAt(i + 1)) && !Character.isJavaIdentifierPart(prev)) { // TODO Use PythonUtils
 162.319 +                    // Peek ahead to see if we have [not-identifier-char]*[identifierchars]*[not-identifier-chars]
 162.320 +                    for (int j = i + 1; j < n; j++) {
 162.321 +                        char d = line.charAt(j);
 162.322 +                        if (d == '*') {
 162.323 +                            if (j == n - 1 || !Character.isJavaIdentifierPart(line.charAt(j + 1))) {
 162.324 +                                // Yess, make bold
 162.325 +                                sb.append("<b>"); // NOI18N
 162.326 +                                appendEscaped(line.substring(i + 1, j));
 162.327 +                                sb.append("</b>"); // NOI18N
 162.328 +                                i = j;
 162.329 +                                continue Loop;
 162.330 +                            }
 162.331 +                        } else if (!Character.isJavaIdentifierPart(d)) {
 162.332 +                            break;
 162.333 +                        }
 162.334 +                    }
 162.335 +                }
 162.336 +            } // TODO: :addedin, :deprecated, etc
 162.337 +
 162.338 +            appendEscaped(c);
 162.339 +            prev = c;
 162.340 +        }
 162.341 +    }
 162.342 +
 162.343 +    public void append(String line) {
 162.344 +        try {
 162.345 +            String trim = line.trim();
 162.346 +            if (trim.length() == 0) {
 162.347 +                inDocTest = false;
 162.348 +                if (inIndex) {
 162.349 +                    // Completely swallow all indexing entries
 162.350 +                    return;
 162.351 +                } else if (inTable) {
 162.352 +                    sb.append("</pre>\n"); // NOI18N
 162.353 +                    inVerbatim = false;
 162.354 +                    inTable = false;
 162.355 +                } else if (inVerbatim) {
 162.356 +                    sb.append("\n"); // NOI18N
 162.357 +                } else if (!lastWasEmpty && sb.length() > beginPos) {
 162.358 +                    sb.append(BRBR); // NOI18N
 162.359 +                }
 162.360 +                lastWasEmpty = true;
 162.361 +            } else {
 162.362 +                if (!lastWasEmpty && trim.startsWith("- ")) { // NOI18N
 162.363 +                    // lists - make sure they're on a new line
 162.364 +                    sb.append("<br>"); // NOI18N
 162.365 +                }
 162.366 +
 162.367 +                lastWasEmpty = false;
 162.368 +
 162.369 +                if (maybeVerbatim) {
 162.370 +                    int indent = getIndentation(line, 0);
 162.371 +                    if (indent > lastIndent) {
 162.372 +                        // Truncate last whitespace separator before <pre> if any
 162.373 +                        if (sb.length() > BRBR.length() && sb.substring(sb.length() - BRBR.length()).equals(BRBR)) {
 162.374 +                            sb.setLength(sb.length() - BRBR.length());
 162.375 +                        }
 162.376 +                        inVerbatim = true;
 162.377 +                        code = new ArrayList<>();
 162.378 +                        code.add(line);
 162.379 +                        maybeVerbatim = false;
 162.380 +                        return;
 162.381 +                    }
 162.382 +                    maybeVerbatim = false;
 162.383 +                } else if (inVerbatim || inTable) {
 162.384 +                    int indent = getIndentation(line, 0);
 162.385 +                    if (indent <= lastIndent) {
 162.386 +////                        // Truncate trailing whitespace
 162.387 +////                        while (sb.length() > 0 && sb.charAt(sb.length()-1) == '\n') {
 162.388 +////                            sb.setLength(sb.length()-1);
 162.389 +////                        }
 162.390 +////                        sb.append("</pre>"); // NOI18N
 162.391 +//                        inVerbatim = false;
 162.392 +//                        inTable = false;
 162.393 +                        flush();
 162.394 +                        lastWasEmpty = true;
 162.395 +                    } else if (inVerbatim) {
 162.396 +                        // We need to buffer up the text such that we can lex it as a unit
 162.397 +                        // (and determine when done with the section if it's code or regular text)
 162.398 +                        code.add(line);
 162.399 +                        return;
 162.400 +                    } else {
 162.401 +                        appendEscaped(line);
 162.402 +                        sb.append("\n"); // NOI18N
 162.403 +                        return;
 162.404 +                    }
 162.405 +                } else if (inDiv) {
 162.406 +                    int indent = getIndentation(line, 0);
 162.407 +                    if (indent <= lastIndent) {
 162.408 +                        // Truncate last whitespace separator before <pre> if any
 162.409 +                        if (sb.length() > BRBR.length() && sb.substring(sb.length() - BRBR.length()).equals(BRBR)) {
 162.410 +                            sb.setLength(sb.length() - BRBR.length());
 162.411 +                        }
 162.412 +                        sb.append("</div>\n"); // NOI18N
 162.413 +                        inDiv = false;
 162.414 +                        lastWasEmpty = true;
 162.415 +                    } else {
 162.416 +                        appendRstLine(line);
 162.417 +                        sb.append("\n"); // NOI18N
 162.418 +                        return;
 162.419 +                    }
 162.420 +                } else if (inIndex) {
 162.421 +                    int indent = getIndentation(line, 0);
 162.422 +                    if (indent <= lastIndent) {
 162.423 +                        inIndex = false;
 162.424 +                        lastWasEmpty = true;
 162.425 +                    } else {
 162.426 +                        return;
 162.427 +                    }
 162.428 +
 162.429 +                }
 162.430 +
 162.431 +                if (trim.startsWith(".. method:: ")) { // NOI18N
 162.432 +                    String sig = trim.substring(12).trim();
 162.433 +                    sb.append("<a href=\"meth:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
 162.434 +                    return;
 162.435 +                } else if (trim.startsWith(".. function:: ")) { // NOI18N
 162.436 +                    String sig = trim.substring(14).trim();
 162.437 +                    sb.append("<a href=\"func:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
 162.438 +                    return;
 162.439 +                } else if (trim.startsWith(".. class:: ")) { // NOI18N
 162.440 +                    String sig = trim.substring(11).trim();
 162.441 +                    sb.append("<a href=\"class:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
 162.442 +                    return;
 162.443 +                } else if (trim.startsWith(".. attribute:: ")) { // NOI18N
 162.444 +                    String sig = trim.substring(15).trim();
 162.445 +                    sb.append("<a href=\"attr:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
 162.446 +                    return;
 162.447 +                } else if (trim.startsWith(".. data:: ")) { // NOI18N
 162.448 +                    String sig = trim.substring(10).trim();
 162.449 +                    sb.append("<a href=\"data:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
 162.450 +                    return;
 162.451 +                } else if (trim.startsWith(".. module:: ")) { // NOI18N
 162.452 +                    String sig = trim.substring(12).trim();
 162.453 +                    sb.append("<a href=\"module:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>"); // NOI18N
 162.454 +                    sb.append("<br>\n");
 162.455 +                    return;
 162.456 +                } else if (trim.startsWith(".. productionlist:")) {
 162.457 +                    lastIndent = getIndentation(line, 0);
 162.458 +                    inVerbatim = true;
 162.459 +                    code = new ArrayList<>();
 162.460 +                    code.add(line);
 162.461 +                    maybeVerbatim = false;
 162.462 +                    return;
 162.463 +                }
 162.464 +
 162.465 +                if (trim.startsWith(">>>") || inDocTest) { // NOI18N
 162.466 +                    if (!trim.startsWith(">>>")) { // NOI18N
 162.467 +                        sb.append("<code>"); // NOI18N
 162.468 +                        appendEscaped(line); // NOI18N
 162.469 +                        // Wait until there is an empty line before we mark doctest done!
 162.470 +                        // inDocTest = false;
 162.471 +                        sb.append("</code><br>"); // NOI18N
 162.472 +                    } else {
 162.473 +                        sb.append("<code>"); // NOI18N
 162.474 +                        appendEscaped(">>>"); // NOI18N
 162.475 +                        String html = getPythonHtml(Collections.singletonList(trim.substring(3)), false);
 162.476 +                        sb.append(html);
 162.477 +                        sb.append("</code>"); // NOI18N
 162.478 +                        inDocTest = true;
 162.479 +                    }
 162.480 +                    return;
 162.481 +                }
 162.482 +                inDocTest = false;
 162.483 +
 162.484 +                if (trim.startsWith(".. note::") || trim.startsWith(".. warning::") || trim.startsWith(".. seealso:")) { // NOI18N
 162.485 +                    // Truncate last whitespace separator before <pre> if any
 162.486 +                    if (sb.length() > BRBR.length() && sb.substring(sb.length() - BRBR.length()).equals(BRBR)) {
 162.487 +                        sb.setLength(sb.length() - BRBR.length());
 162.488 +                    }
 162.489 +                    sb.append("<div style=\"margin: 5px 5px; "); // NOI18N
 162.490 +                    if (!trim.contains("seealso")) { // NOI18N
 162.491 +                        sb.append("background: #ffdddd; "); // NOI18N
 162.492 +                    } else {
 162.493 +                        sb.append("background: #ddffdd; "); // NOI18N
 162.494 +                    }
 162.495 +                    sb.append("border-size: 1px; padding: 5px\">"); // NOI18N
 162.496 +                    if (trim.contains("note:")) {
 162.497 +                        sb.append("<b>NOTE</b>: "); // NOI18N
 162.498 +                    } else if (trim.contains("warning")) {
 162.499 +                        sb.append("<b>WARNING</b>: "); // NOI18N
 162.500 +                    } else {
 162.501 +                        sb.append("<b>See Also</b>: "); // NOI18N
 162.502 +                    }
 162.503 +                    sb.append("\n"); // NOI18N
 162.504 +                    inDiv = true;
 162.505 +                    lastIndent = getIndentation(line, 0);
 162.506 +                    maybeVerbatim = false;
 162.507 +                    return;
 162.508 +                } else if (trim.startsWith(".. versionadded::") || trim.startsWith(".. versionchanged::") || trim.startsWith(".. deprecated::")) { // NOI18N
 162.509 +                    // Truncate last whitespace separator before <pre> if any
 162.510 +                    if (sb.length() > BRBR.length() && sb.substring(sb.length() - BRBR.length()).equals(BRBR)) {
 162.511 +                        sb.setLength(sb.length() - BRBR.length());
 162.512 +                    }
 162.513 +                    sb.append("<div style=\"margin: 5px 5px; background: #dddddd; border-size: 1px; padding: 5px\">"); // NOI18N
 162.514 +                    if (trim.contains("added:")) {
 162.515 +                        sb.append("<b>Version Added</b>: "); // NOI18N
 162.516 +                    } else if (trim.contains("changed")) {
 162.517 +                        sb.append("<b>Version Changed</b>: "); // NOI18N
 162.518 +                    } else {
 162.519 +                        assert trim.contains("deprecated"); // NOI18N
 162.520 +                        sb.append("<b>Deprecated</b>: "); // NOI18N
 162.521 +                    }
 162.522 +                    sb.append(trim.substring(trim.indexOf("::") + 2));
 162.523 +                    sb.append("\n"); // NOI18N
 162.524 +                    inDiv = true;
 162.525 +                    lastIndent = getIndentation(line, 0);
 162.526 +                    maybeVerbatim = false;
 162.527 +                    return;
 162.528 +                } else if (trim.startsWith(".. index:")) { // NOI18N
 162.529 +                    inIndex = true;
 162.530 +                    lastIndent = getIndentation(line, 0);
 162.531 +                    return;
 162.532 +                } else if (trim.startsWith(".. _") && trim.endsWith(":")) {
 162.533 +                    // skip lines like .. _pyzipfile-objects: 
 162.534 +                    return;
 162.535 +                } else if (trim.startsWith(".. moduleauthor::") || trim.startsWith(".. sectionauthor::")) { // NOI18N
 162.536 +                    if (trim.startsWith(".. mod")) {
 162.537 +                        sb.append("<br>Module Author:</b>");
 162.538 +                    } else {
 162.539 +                        sb.append("<br>Section Author:</b>");
 162.540 +                    }
 162.541 +                    appendEscaped(trim.substring(trim.indexOf("::") + 2)); //
 162.542 +                    sb.append("\n");
 162.543 +                    return;
 162.544 +                } else if (trim.endsWith("::")) { // NOI18N
 162.545 +                    maybeVerbatim = true;
 162.546 +                    lastIndent = getIndentation(line, 0);
 162.547 +                } else if (trim.startsWith("+-----")) { // NOI18N
 162.548 +                    // A table
 162.549 +                    sb.append("<pre>"); // NOI18N
 162.550 +                    appendEscaped(line);
 162.551 +                    sb.append("\n"); // NOI18N
 162.552 +                    inTable = true;
 162.553 +                    lastIndent = getIndentation(line, 0) - 1;
 162.554 +                    return;
 162.555 +                } else if (line.startsWith("======") || line.startsWith("------") || line.startsWith("******") || line.startsWith("^^^^^^^^")) { // NOI18N
 162.556 +                    // PREVIOUS line could be a title.
 162.557 +                    // Note -- we're comparing on "line" and not "trim" here because in indented contexts,
 162.558 +                    //  === sometimes represents parts of tables -- see the turtle.rst file for examples.
 162.559 +
 162.560 +                    int n = sb.length();
 162.561 +                    if (n > 0 && sb.charAt(n - 1) == '\n') {
 162.562 +                        n--;
 162.563 +                    }
 162.564 +                    int index = n - 1;
 162.565 +                    for (; index >= 0; index--) {
 162.566 +                        char c = sb.charAt(index);
 162.567 +                        if (c == '\n') {
 162.568 +                            index++;
 162.569 +                            break;
 162.570 +                        }
 162.571 +                    }
 162.572 +                    if (index == -1) {
 162.573 +                        index = 0;
 162.574 +                    }
 162.575 +                    // Index now points to the beginning of the previous line
 162.576 +                    boolean empty = true;
 162.577 +//                    boolean okay = true;
 162.578 +                    int start = index;
 162.579 +                    for (; index < n; index++) {
 162.580 +                        char c = sb.charAt(index);
 162.581 +                        if (c == '\n') {
 162.582 +                            break;
 162.583 +                        }
 162.584 +                        empty = false;
 162.585 +//                        if (c == '<') {
 162.586 +//                            okay = false;
 162.587 +//                        }
 162.588 +                    }
 162.589 +                    if (!empty/* && okay*/) {
 162.590 +                        String tag = "h2"; // NOI18N
 162.591 +                        if (line.startsWith("-") || line.startsWith("^")) { // NOI18N
 162.592 +                            tag = "h3"; // NOI18N
 162.593 +                        }
 162.594 +                        sb.insert(start, "<" + tag + ">"); // NOI18N
 162.595 +                        sb.append("</" + tag + ">\n"); // NOI18N
 162.596 +                        lastWasEmpty = true;
 162.597 +                        return;
 162.598 +                    }
 162.599 +                }
 162.600 +
 162.601 +                //sb.append(line);
 162.602 +                appendRstLine(line);
 162.603 +
 162.604 +                sb.append("\n"); // NOI18N
 162.605 +            }
 162.606 +        } catch (CharConversionException ex) {
 162.607 +            Exceptions.printStackTrace(ex);
 162.608 +        }
 162.609 +    }
 162.610 +
 162.611 +    public void appendSignature(Element element) {
 162.612 +        sb.append("<pre>"); // NOI18N
 162.613 +
 162.614 +        if (element instanceof IndexedMethod) {
 162.615 +            IndexedMethod executable = (IndexedMethod)element;
 162.616 +            if (element.getIn() != null && !PythonIndex.isBuiltinModule(element.getIn())) {
 162.617 +                String in = element.getIn();
 162.618 +                sb.append("<i>"); // NOI18N
 162.619 +                sb.append(in);
 162.620 +                sb.append("</i>"); // NOI18N
 162.621 +                sb.append("<br>"); // NOI18N
 162.622 +            }
 162.623 +            // TODO - share this between Navigator implementation and here...
 162.624 +            sb.append("<b>"); // NOI18N
 162.625 +            sb.append(element.getName());
 162.626 +            sb.append("</b>"); // NOI18N
 162.627 +            String[] parameters = executable.getParams();
 162.628 +
 162.629 +            if ((parameters != null) && (parameters.length > 0)) {
 162.630 +                sb.append("("); // NOI18N
 162.631 +
 162.632 +                sb.append("<font color=\"#808080\">"); // NOI18N
 162.633 +
 162.634 +                boolean first = true;
 162.635 +                for (String parameter : parameters) {
 162.636 +                    if (first) {
 162.637 +                        first = false;
 162.638 +                    } else {
 162.639 +                        sb.append(", ");
 162.640 +                    }
 162.641 +                    sb.append(parameter);
 162.642 +                }
 162.643 +
 162.644 +                sb.append("</font>"); // NOI18N
 162.645 +
 162.646 +                sb.append(")"); // NOI18N
 162.647 +            }
 162.648 +        } else if (element instanceof IndexedElement) {
 162.649 +            //IndexedElement clz = (IndexedElement)element;
 162.650 +            String name = element.getName();
 162.651 +//            final String fqn = clz.getFqn();
 162.652 +//            if (fqn != null && !name.equals(fqn)) {
 162.653 +//                signature.append("<i>"); // NOI18N
 162.654 +//                signature.append(fqn); // NOI18N
 162.655 +//                signature.append("</i>"); // NOI18N
 162.656 +//                signature.append("<br>"); // NOI18N
 162.657 +//            }
 162.658 +            sb.append("<b>"); // NOI18N
 162.659 +            sb.append(name);
 162.660 +            sb.append("</b>"); // NOI18N
 162.661 +        } else {
 162.662 +            sb.append(element.getName());
 162.663 +        }
 162.664 +
 162.665 +        sb.append("</pre>\n"); // NOI18N
 162.666 +    }
 162.667 +
 162.668 +    public void appendHtml(String html) {
 162.669 +        sb.append(html);
 162.670 +    }
 162.671 +
 162.672 +    public void markEmpty() {
 162.673 +        beginPos = sb.length();
 162.674 +    }
 162.675 +
 162.676 +    public String toHtml() {
 162.677 +        flush();
 162.678 +        return sb.toString();
 162.679 +    }
 162.680 +
 162.681 +    public static String document(String rst) {
 162.682 +        RstFormatter formatter = new RstFormatter();
 162.683 +        String[] lines = rst.split("\n"); // NOI18N
 162.684 +        for (String line : lines) {
 162.685 +            formatter.append(line);
 162.686 +        }
 162.687 +        return formatter.toHtml();
 162.688 +    }
 162.689 +
 162.690 +    public static String getDocumentation(IndexedElement indexedElement) {
 162.691 +        RstFormatter formatter = new RstFormatter();
 162.692 +        FileObject fileObject = indexedElement.getFileObject();
 162.693 +        if (fileObject == null) {
 162.694 +            return null;
 162.695 +        }
 162.696 +        BaseDocument document = GsfUtilities.getDocument(fileObject, true);
 162.697 +        if (document == null) {
 162.698 +            return null;
 162.699 +        }
 162.700 +
 162.701 +        String[] signatureHolder = new String[1];
 162.702 +        String rst = formatter.extractRst(indexedElement, document, signatureHolder);
 162.703 +        if (rst != null && rst.length() > 0) {
 162.704 +            String signature = signatureHolder[0];
 162.705 +            if (signature == null) {
 162.706 +                formatter.appendSignature(indexedElement);
 162.707 +                formatter.appendHtml("\n<hr>\n"); // NOI18N
 162.708 +                formatter.markEmpty();
 162.709 +            } else {
 162.710 +                formatter.appendHtml("<pre>"); // NOI18N
 162.711 +                formatter.appendHtml("<b>"); // NOI18N
 162.712 +                int paren = signature.indexOf('(');
 162.713 +                if (paren != -1) {
 162.714 +                    formatter.appendHtml(signature.substring(0, paren));
 162.715 +                    formatter.appendHtml("</b>"); // NOI18N
 162.716 +                    formatter.appendHtml("<font color=\"#808080\">"); // NOI18N
 162.717 +                    formatter.appendHtml(signature.substring(paren));
 162.718 +                    formatter.appendHtml("</font>"); // NOI18N
 162.719 +                } else {
 162.720 +                    formatter.appendHtml(signature);
 162.721 +                    formatter.appendHtml("()"); // NOI18N
 162.722 +                    formatter.appendHtml("</b>"); // NOI18N
 162.723 +                }
 162.724 +                formatter.appendHtml("</pre>"); // NOI18N
 162.725 +                formatter.appendHtml("\n<hr>\n"); // NOI18N
 162.726 +                formatter.markEmpty();
 162.727 +            }
 162.728 +
 162.729 +            String[] lines = rst.split("\n"); // NOI18N
 162.730 +            for (String line : lines) {
 162.731 +                formatter.append(line);
 162.732 +            }
 162.733 +            return formatter.toHtml();
 162.734 +        }
 162.735 +
 162.736 +        return null;
 162.737 +    }
 162.738 +
 162.739 +    /**
 162.740 +     * Find the reStructured text for the documentation for the given element
 162.741 +     * in the given RST document
 162.742 +     * @param indexedElement
 162.743 +     * @param document
 162.744 +     * @return
 162.745 +     */
 162.746 +    private String extractRst(IndexedElement element, BaseDocument doc, String[] signatureHolder) {
 162.747 +        return extractRst(element.getName(), element.getClz(), element.getKind(), doc, signatureHolder);
 162.748 +    }
 162.749 +
 162.750 +    String extractRst(String name, String clz, ElementKind kind, BaseDocument doc, String[] signatureHolder) {
 162.751 +        try {
 162.752 +            String text = doc.getText(0, doc.getLength());
 162.753 +            // What about functions?
 162.754 +            if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
 162.755 +                int offset = findElementMatch(text, "function::", name, true); // NOI18N
 162.756 +                if (offset == -1) {
 162.757 +                    offset = findElementMatch(text, "method::", name, false); // NOI18N
 162.758 +                    if (offset == -1 && kind == ElementKind.CONSTRUCTOR) {
 162.759 +                        offset = findElementMatch(text, "class::", name, false); // NOI18N
 162.760 +                        if (offset == -1 && clz != null && clz.length() > 0 && "__init__".equals(name)) { // NOI18N
 162.761 +                            offset = findElementMatch(text, "method::", clz, false); // NOI18N
 162.762 +                            if (offset == -1) {
 162.763 +                                offset = findElementMatch(text, "class::", clz, false); // NOI18N
 162.764 +                            }
 162.765 +                        }
 162.766 +                    }
 162.767 +                }
 162.768 +                if (offset != -1) {
 162.769 +                    int end = findElementEnd(text, offset);
 162.770 +                    int nextLine = getNextLineOffset(text, offset);
 162.771 +                    if (nextLine < end) {
 162.772 +                        if (signatureHolder != null) {
 162.773 +                            String signature = text.substring(text.indexOf("::", offset) + 2, nextLine).trim(); // NOI18N
 162.774 +                            signatureHolder[0] = signature;
 162.775 +                        }
 162.776 +                        return text.substring(nextLine, end);
 162.777 +                    }
 162.778 +                }
 162.779 +            } else if (kind == ElementKind.CLASS) {
 162.780 +                int offset = findElementMatch(text, "class::", name, false); // NOI18N
 162.781 +                if (offset == -1) {
 162.782 +                    offset = findElementMatch(text, "exception::", name, false); // NOI18N
 162.783 +                }
 162.784 +                if (offset != -1) {
 162.785 +                    int end = findElementEnd(text, offset);
 162.786 +                    int nextLine = getNextLineOffset(text, offset);
 162.787 +                    if (nextLine < end) {
 162.788 +                        String elementText = text.substring(nextLine, end);
 162.789 +                        return elementText;
 162.790 +                    }
 162.791 +                }
 162.792 +            } else if (kind == ElementKind.MODULE) {
 162.793 +                int offset = findElementMatch(text, "module::", name, false); // NOI18N
 162.794 +                if (offset == -1) {
 162.795 +                    offset = findElementMatch(text, "currentmodule::", name, false); // NOI18N
 162.796 +                }
 162.797 +                if (offset != -1) {
 162.798 +                    int end = findElementEnd(text, offset);
 162.799 +                    int nextLine = getNextLineOffset(text, offset);
 162.800 +                    if (nextLine < end) {
 162.801 +                        String elementText = text.substring(nextLine, end);
 162.802 +                        return elementText;
 162.803 +                    }
 162.804 +                }
 162.805 +            } else {
 162.806 +//                assert kind == ElementKind.ATTRIBUTE :;
 162.807 +                int offset = findElementMatch(text, "data::", name, true); // NOI18N
 162.808 +                if (offset == -1) {
 162.809 +                    offset = findElementMatch(text, "attribute::", name, false); // NOI18N
 162.810 +                }
 162.811 +                if (offset != -1) {
 162.812 +                    int end = findElementEnd(text, offset);
 162.813 +                    int nextLine = getNextLineOffset(text, offset);
 162.814 +                    if (nextLine < end) {
 162.815 +                        String elementText = text.substring(nextLine, end);
 162.816 +                        return elementText;
 162.817 +                    }
 162.818 +                }
 162.819 +            }
 162.820 +        } catch (BadLocationException ex) {
 162.821 +            Exceptions.printStackTrace(ex);
 162.822 +            return "";
 162.823 +        }
 162.824 +
 162.825 +//        while (true) {
 162.826 +//            try {
 162.827 +//                int ret = doc.find(new FinderFactory.StringFwdFinder(".. " + key + "::", true), offset, -1);
 162.828 +//                if (ret == -1) {
 162.829 +//                    break;
 162.830 +//                }
 162.831 +//            } catch (BadLocationException ex) {
 162.832 +//                Exceptions.printStackTrace(ex);
 162.833 +//            }
 162.834 +//        }
 162.835 +
 162.836 +
 162.837 +        return "";
 162.838 +    }
 162.839 +
 162.840 +    public static int getIndentation(String text, int lineBegin) {
 162.841 +        for (int i = lineBegin; i < text.length(); i++) {
 162.842 +            char c = text.charAt(i);
 162.843 +            if (c == '\n') {
 162.844 +                // Empty lines don't count
 162.845 +                return -1;
 162.846 +            }
 162.847 +            if (!Character.isWhitespace(c)) {
 162.848 +                // Doesn't quite work for tabs etc. but those aren't
 162.849 +                // really used in rst files... Fix when I switch to
 162.850 +                // direct document iteration
 162.851 +                return i - lineBegin;
 162.852 +            }
 162.853 +        }
 162.854 +
 162.855 +        return -1;
 162.856 +    }
 162.857 +
 162.858 +    public static int getNextLineOffset(String text, int offset) {
 162.859 +        int index = text.indexOf('\n', offset);
 162.860 +        if (index == -1) {
 162.861 +            return -1;
 162.862 +        } else {
 162.863 +            return index + 1;
 162.864 +        }
 162.865 +    }
 162.866 +
 162.867 +    public static int findElementEnd(String text, int offset) {
 162.868 +        // Find beginning of line
 162.869 +        int lineBegin = 0;
 162.870 +        for (int i = offset; i > 0; i--) {
 162.871 +            char c = text.charAt(i);
 162.872 +            if (c == '\n') {
 162.873 +                lineBegin = i + 1;
 162.874 +                break;
 162.875 +            }
 162.876 +        }
 162.877 +
 162.878 +        // Compute indentation of the ..
 162.879 +        int firstIndent = getIndentation(text, lineBegin);
 162.880 +        offset = getNextLineOffset(text, lineBegin);
 162.881 +        while (true) {
 162.882 +            offset = getNextLineOffset(text, offset);
 162.883 +            if (offset == -1) {
 162.884 +                return text.length();
 162.885 +            }
 162.886 +            int indent = getIndentation(text, offset);
 162.887 +            if (indent == -1) {
 162.888 +                // Empty line - doesn't count
 162.889 +                continue;
 162.890 +            } else if (indent <= firstIndent) {
 162.891 +                return offset;
 162.892 +            }
 162.893 +        }
 162.894 +    }
 162.895 +
 162.896 +    public static int findElementMatch(String text, String key, String name, boolean checkAdjacentLines) {
 162.897 +        int nameLength = name.length();
 162.898 +        int offset = 0;
 162.899 +        int keyLength = key.length();
 162.900 +        while (true) {
 162.901 +            int next = text.indexOf(key, offset);
 162.902 +            if (next == -1) {
 162.903 +                break;
 162.904 +            }
 162.905 +            offset = next + keyLength;
 162.906 +
 162.907 +            int lineEnd = text.indexOf('\n', offset);
 162.908 +            if (lineEnd == -1) {
 162.909 +                lineEnd = text.length(); // on last line with no crlf at the end
 162.910 +            }
 162.911 +
 162.912 +            // Skip whitespace
 162.913 +            for (; offset < lineEnd; offset++) {
 162.914 +                char c = text.charAt(offset);
 162.915 +                if (c != ' ') {
 162.916 +                    break;
 162.917 +                }
 162.918 +            }
 162.919 +
 162.920 +            int nameBegin = offset;
 162.921 +            int nameEnd = -1;
 162.922 +
 162.923 +            // Pick out the bame
 162.924 +            for (int i = offset; i < lineEnd; i++) {
 162.925 +                char c = text.charAt(i);
 162.926 +                if (c == '(' || c == ' ') {
 162.927 +                    nameEnd = i;
 162.928 +                    break;
 162.929 +                } else if (c == '.') {
 162.930 +                    nameBegin = i + 1;
 162.931 +                }
 162.932 +            }
 162.933 +            if (nameEnd == -1) {
 162.934 +                nameEnd = lineEnd;
 162.935 +            }
 162.936 +
 162.937 +
 162.938 +            if (nameEnd - nameBegin == nameLength &&
 162.939 +                    text.regionMatches(nameBegin, name, 0, nameLength)) {
 162.940 +                // TODO - validate the arguments list?
 162.941 +                return next;
 162.942 +            }
 162.943 +
 162.944 +            // Look on subsequent lines too - we sometimes have adjacent lines
 162.945 +            // with additional signatures
 162.946 +            if (checkAdjacentLines) {
 162.947 +                while (true) {
 162.948 +                    int lineBegin = lineEnd+1;
 162.949 +                    if (lineBegin >= text.length()) {
 162.950 +                        break;
 162.951 +                    }
 162.952 +
 162.953 +                    lineEnd = text.indexOf('\n', lineBegin);
 162.954 +                    if (lineEnd == -1) {
 162.955 +                        lineEnd = text.length(); // on last line with no crlf at the end
 162.956 +                    }
 162.957 +
 162.958 +                    while (lineBegin < lineEnd) {
 162.959 +                        char c = text.charAt(lineBegin);
 162.960 +                        if (!Character.isWhitespace(c)) {
 162.961 +                            break;
 162.962 +                        }
 162.963 +                        lineBegin++;
 162.964 +                    }
 162.965 +
 162.966 +                    while (lineEnd > lineBegin) {
 162.967 +                        char c = text.charAt(lineEnd-1);
 162.968 +                        if (!Character.isWhitespace(c)) {
 162.969 +                            break;
 162.970 +                        }
 162.971 +                        lineEnd--;
 162.972 +                    }
 162.973 +
 162.974 +                    if (lineEnd <= lineBegin) {
 162.975 +                        break;
 162.976 +                    }
 162.977 +
 162.978 +                    nameBegin = lineBegin;
 162.979 +                    nameEnd = -1;
 162.980 +
 162.981 +                    // Pick out the name
 162.982 +                    for (int i = lineBegin; i < lineEnd; i++) {
 162.983 +                        char c = text.charAt(i);
 162.984 +                        if (c == '(' || c == ' ') {
 162.985 +                            nameEnd = i;
 162.986 +                            break;
 162.987 +                        } else if (c == '.') {
 162.988 +                            nameBegin = i + 1;
 162.989 +                        }
 162.990 +                    }
 162.991 +                    if (nameEnd == -1) {
 162.992 +                        nameEnd = lineEnd;
 162.993 +                    }
 162.994 +
 162.995 +                    if (nameEnd - nameBegin == nameLength &&
 162.996 +                            text.regionMatches(nameBegin, name, 0, nameLength)) {
 162.997 +                        // TODO - validate the arguments list?
 162.998 +                        return next;
 162.999 +                    }
162.1000 +                }
162.1001 +            }
162.1002 +
162.1003 +        }
162.1004 +
162.1005 +        return -1;
162.1006 +    }
162.1007 +
162.1008 +    public static String document(ParserResult info, ElementHandle element) {
162.1009 +        if (element instanceof IndexedElement) {
162.1010 +            IndexedElement indexedElement = (IndexedElement)element;
162.1011 +
162.1012 +            FileObject fo = indexedElement.getFileObject();
162.1013 +
162.1014 +            if (fo == null) {
162.1015 +                return null;
162.1016 +            }
162.1017 +
162.1018 +            if (PythonUtils.isRstFile(fo)) {
162.1019 +                return getDocumentation(indexedElement);
162.1020 +            }
162.1021 +
162.1022 +
162.1023 +            PythonTree node = indexedElement.getNode();
162.1024 +            if (node != null) {
162.1025 +                return document(info, node, indexedElement);
162.1026 +            }
162.1027 +        }
162.1028 +        return null;
162.1029 +    }
162.1030 +
162.1031 +    public static String document(ParserResult info, PythonTree node, IndexedElement element) {
162.1032 +        if (node != null) {
162.1033 +            String doc = PythonAstUtils.getDocumentation(node);
162.1034 +            if (doc != null) {
162.1035 +                // Honor empty lines: paragraphs
162.1036 +                RstFormatter formatter = new RstFormatter();
162.1037 +                if (element != null) {
162.1038 +                    formatter.appendSignature(element);
162.1039 +                }
162.1040 +                if (doc.indexOf('\n') != -1) {
162.1041 +                    formatter.appendHtml("\n<hr>\n"); // NOI18N
162.1042 +                    formatter.markEmpty();
162.1043 +                    String[] lines = doc.split("\n"); // NOI18N
162.1044 +                    for (String line : lines) {
162.1045 +                        formatter.append(line);
162.1046 +                    }
162.1047 +                } else if (doc.length() > 0) {
162.1048 +                    formatter.appendHtml("\n<hr>\n"); // NOI18N
162.1049 +                    formatter.markEmpty();
162.1050 +                    formatter.append(doc);
162.1051 +                }
162.1052 +
162.1053 +                return formatter.toHtml();
162.1054 +            }
162.1055 +        }
162.1056 +
162.1057 +        return null;
162.1058 +    }
162.1059 +
162.1060 +    public static String getSignature(Element element) {
162.1061 +        StringBuilder signature = new StringBuilder();
162.1062 +        // TODO:
162.1063 +        signature.append("<pre>"); // NOI18N
162.1064 +
162.1065 +        if (element instanceof IndexedMethod) {
162.1066 +            IndexedMethod executable = (IndexedMethod)element;
162.1067 +            if (element.getIn() != null) {
162.1068 +                String in = element.getIn();
162.1069 +                signature.append("<i>"); // NOI18N
162.1070 +                signature.append(in);
162.1071 +                signature.append("</i>"); // NOI18N
162.1072 +                signature.append("<br>"); // NOI18N
162.1073 +            }
162.1074 +            // TODO - share this between Navigator implementation and here...
162.1075 +            signature.append("<b>"); // NOI18N
162.1076 +            signature.append(element.getName());
162.1077 +            signature.append("</b>"); // NOI18N
162.1078 +            String[] parameters = executable.getParams();
162.1079 +
162.1080 +            if ((parameters != null) && (parameters.length > 0)) {
162.1081 +                signature.append("("); // NOI18N
162.1082 +
162.1083 +                signature.append("<font color=\"#808080\">"); // NOI18N
162.1084 +
162.1085 +                boolean first = true;
162.1086 +                for (String parameter : parameters) {
162.1087 +                    if (first) {
162.1088 +                        first = false;
162.1089 +                    } else {
162.1090 +                        signature.append(", "); // NOI18N
162.1091 +                    }
162.1092 +                    signature.append(parameter);
162.1093 +                }
162.1094 +
162.1095 +                signature.append("</font>"); // NOI18N
162.1096 +
162.1097 +                signature.append(")"); // NOI18N
162.1098 +            }
162.1099 +        } else if (element instanceof IndexedElement) {
162.1100 +//            IndexedElement clz = (IndexedElement)element;
162.1101 +            String name = element.getName();
162.1102 +//            final String fqn = clz.getFqn();
162.1103 +//            if (fqn != null && !name.equals(fqn)) {
162.1104 +//                signature.append("<i>"); // NOI18N
162.1105 +//                signature.append(fqn); // NOI18N
162.1106 +//                signature.append("</i>"); // NOI18N
162.1107 +//                signature.append("<br>"); // NOI18N
162.1108 +//            }
162.1109 +            signature.append("<b>"); // NOI18N
162.1110 +            signature.append(name);
162.1111 +            signature.append("</b>"); // NOI18N
162.1112 +        } else {
162.1113 +            signature.append(element.getName());
162.1114 +        }
162.1115 +
162.1116 +        signature.append("</pre>\n"); // NOI18N
162.1117 +
162.1118 +        return signature.toString();
162.1119 +    }
162.1120 +
162.1121 +    @SuppressWarnings("unchecked")
162.1122 +    private String getPythonHtml(List<String> source, boolean addPre) {
162.1123 +        StringBuilder python = new StringBuilder(500);
162.1124 +
162.1125 +        for (String s : source) {
162.1126 +            python.append(s);
162.1127 +            python.append("\n"); // NOI18N
162.1128 +        }
162.1129 +
162.1130 +        Language<?> language = PythonTokenId.language();
162.1131 +        String mimeType = PythonMIMEResolver.PYTHON_MIME_TYPE;
162.1132 +        // TODO - handle YAML and other languages I can see in the documentation...
162.1133 +        /*if (python.indexOf(" <%") != -1) { // NOI18N
162.1134 +        mimeType = "application/x-httpd-eruby"; // RHTML
162.1135 +        Collection<LanguageProvider> providers = (Collection<LanguageProvider>) Lookup.getDefault().lookupAll(LanguageProvider.class);
162.1136 +        for (LanguageProvider provider : providers) {
162.1137 +        language = provider.findLanguage(mimeType);
162.1138 +        if (language != null) {
162.1139 +        break;
162.1140 +        }
162.1141 +        }
162.1142 +
162.1143 +        if (language == null) {
162.1144 +        mimeType = PythonTokenId.PYTHON_MIME_TYPE;
162.1145 +        language = PythonTokenId.language();
162.1146 +        }
162.1147 +        } else*/ if (source.get(0).trim().startsWith("<")) {
162.1148 +            // Looks like markup (other than RHTML) - don't colorize it
162.1149 +            // since we don't know how
162.1150 +            return null;
162.1151 +        }
162.1152 +
162.1153 +        StringBuilder buffer = new StringBuilder(1500);
162.1154 +
162.1155 +        boolean errors = appendSequence(buffer, python.toString(), language, mimeType, addPre);
162.1156 +        return errors ? null : buffer.toString();
162.1157 +    }
162.1158 +
162.1159 +    @SuppressWarnings("unchecked")
162.1160 +    private boolean appendSequence(StringBuilder sb, String text,
162.1161 +            Language<?> language, String mimeType, boolean addPre) {
162.1162 +        // XXX is this getting called twice?
162.1163 +        MimePath mimePath = MimePath.parse(mimeType);
162.1164 +        Lookup lookup = MimeLookup.getLookup(mimePath);
162.1165 +        FontColorSettings fcs = lookup.lookup(FontColorSettings.class);
162.1166 +
162.1167 +        if (addPre) {
162.1168 +            sb.append("<pre style=\""); // NOI18N
162.1169 +
162.1170 +            sb.append("border-color: #dddddd; border-style: solid; border-width: 1px; ");
162.1171 +
162.1172 +            AttributeSet attribs = fcs.getTokenFontColors("default"); // NOI18N
162.1173 +            Color fg = (Color)attribs.getAttribute(StyleConstants.Foreground);
162.1174 +            if (fg != null) {
162.1175 +                sb.append("color:"); // NOI18N
162.1176 +                sb.append(getHtmlColor(fg));
162.1177 +                sb.append(";"); // NOI18N
162.1178 +            }
162.1179 +            Color bg = (Color)attribs.getAttribute(StyleConstants.Background);
162.1180 +            // Only set the background for dark colors
162.1181 +            if (bg != null && bg.getRed() < 128) {
162.1182 +                sb.append("background:"); // NOI18N
162.1183 +                sb.append(getHtmlColor(bg));
162.1184 +            }
162.1185 +
162.1186 +            sb.append("\">\n"); // NOI18N
162.1187 +        }
162.1188 +        TokenHierarchy hi = TokenHierarchy.create(text, language);
162.1189 +        TokenSequence ts = hi.tokenSequence();
162.1190 +
162.1191 +        int offset = 0;
162.1192 +        ts.move(offset);
162.1193 +
162.1194 +        if (ts.moveNext()) {
162.1195 +            do {
162.1196 +                Token t = ts.token();
162.1197 +                String tokenText = t.text().toString();
162.1198 +
162.1199 +                // TODO - make style classes instead of inlining everything as font!
162.1200 +                String category = t.id().name();
162.1201 +                String primaryCategory = t.id().primaryCategory();
162.1202 +
162.1203 +                if ("error".equals(primaryCategory)) { // NOI18N
162.1204 +                    // Abort: an error token means the output probably isn't
162.1205 +                    // code, or it's code or markup but in a different language
162.1206 +                    // than we're trying to process it as
162.1207 +                    return true;
162.1208 +                }
162.1209 +
162.1210 +                AttributeSet attribs = fcs.getTokenFontColors(category);
162.1211 +                String escapedText = tokenText;
162.1212 +                try {
162.1213 +                    escapedText = XMLUtil.toElementContent(tokenText);
162.1214 +                } catch (CharConversionException cce) {
162.1215 +                    Exceptions.printStackTrace(cce);
162.1216 +                }
162.1217 +
162.1218 +                if (attribs == null) {
162.1219 +                    category = primaryCategory;
162.1220 +                    attribs = fcs.getTokenFontColors(category);
162.1221 +
162.1222 +                }
162.1223 +
162.1224 +                TokenSequence embedded = ts.embedded();
162.1225 +                if (embedded != null) {
162.1226 +                    //embedded.languagePath().mimePath();
162.1227 +                    String embeddedMimeType = MimePath.parse(embedded.languagePath().mimePath()).getPath();
162.1228 +                    Color bg = null;
162.1229 +                    Color fg = null;
162.1230 +                    if (attribs != null) {
162.1231 +                        bg = (Color)attribs.getAttribute(StyleConstants.Background);
162.1232 +                        fg = (Color)attribs.getAttribute(StyleConstants.Foreground);
162.1233 +                        if (fg != null || bg != null) {
162.1234 +                            sb.append("<span style=\"");
162.1235 +                            if (bg != null) {
162.1236 +                                sb.append("background:"); // NOI18N
162.1237 +                                sb.append(getHtmlColor(bg));
162.1238 +                                sb.append(";");
162.1239 +                            }
162.1240 +                            if (fg != null) {
162.1241 +                                sb.append("color:"); // NOI18N
162.1242 +                                sb.append(getHtmlColor(fg));
162.1243 +                            }
162.1244 +                            sb.append("\">"); // NOI18N
162.1245 +                        }
162.1246 +                    }
162.1247 +                    appendSequence(sb, tokenText, embedded.language(), embeddedMimeType, false);
162.1248 +                    if (fg != null || bg != null) {
162.1249 +                        sb.append("</span>"); // NOI18N
162.1250 +                    }
162.1251 +                    continue;
162.1252 +                }
162.1253 +
162.1254 +                if (attribs == null) {
162.1255 +                    sb.append(escapedText);
162.1256 +
162.1257 +                    continue;
162.1258 +                }
162.1259 +
162.1260 +                if (escapedText.indexOf('\n') != -1) {
162.1261 +                    escapedText = escapedText.replace("\n", "<br>"); // NOI18N
162.1262 +                }
162.1263 +
162.1264 +                if (t.id() == PythonTokenId.WHITESPACE) {
162.1265 +                    sb.append(escapedText);
162.1266 +                } else {
162.1267 +                    sb.append("<span style=\""); // NOI18N
162.1268 +
162.1269 +                    Color fg = (Color)attribs.getAttribute(StyleConstants.Foreground);
162.1270 +
162.1271 +                    if (fg != null) {
162.1272 +                        sb.append("color:"); // NOI18N
162.1273 +                        sb.append(getHtmlColor(fg));
162.1274 +                        sb.append(";"); // NOI18N
162.1275 +                    }
162.1276 +
162.1277 +                    Color bg = (Color)attribs.getAttribute(StyleConstants.Background);
162.1278 +
162.1279 +                    if (bg != null) {
162.1280 +                        sb.append("background:"); // NOI18N
162.1281 +                        sb.append(getHtmlColor(bg));
162.1282 +                        sb.append(";"); // NOI18NP
162.1283 +                    }
162.1284 +
162.1285 +                    Boolean b = (Boolean)attribs.getAttribute(StyleConstants.Bold);
162.1286 +
162.1287 +                    if ((b != null) && b) {
162.1288 +                        sb.append("font-weight:bold;"); // NOI18N
162.1289 +                    }
162.1290 +
162.1291 +                    b = (Boolean)attribs.getAttribute(StyleConstants.Italic);
162.1292 +
162.1293 +                    if ((b != null) && b) {
162.1294 +                        sb.append("font-style:italic;"); // NOI18N
162.1295 +                    }
162.1296 +
162.1297 +                    // TODO - underline, strikethrough, ... and FONTS!
162.1298 +                    sb.append("\">"); // NOI18N
162.1299 +                    sb.append(escapedText);
162.1300 +                    sb.append("</span>"); // NOI18N
162.1301 +                }
162.1302 +            } while (ts.moveNext());
162.1303 +        }
162.1304 +
162.1305 +        if (addPre) {
162.1306 +            sb.append("</pre>\n");
162.1307 +        }
162.1308 +
162.1309 +        return false;
162.1310 +    }
162.1311 +
162.1312 +
162.1313 +    // TODO - move to GsfUtilities?
162.1314 +    private static String getHtmlColor(Color c) {
162.1315 +        int r = c.getRed();
162.1316 +        int g = c.getGreen();
162.1317 +        int b = c.getBlue();
162.1318 +        StringBuffer result = new StringBuffer();
162.1319 +        result.append('#');
162.1320 +
162.1321 +        String rs = Integer.toHexString(r);
162.1322 +        String gs = Integer.toHexString(g);
162.1323 +        String bs = Integer.toHexString(b);
162.1324 +
162.1325 +        if (r < 0x10) {
162.1326 +            result.append('0');
162.1327 +        }
162.1328 +
162.1329 +        result.append(rs);
162.1330 +
162.1331 +        if (g < 0x10) {
162.1332 +            result.append('0');
162.1333 +        }
162.1334 +
162.1335 +        result.append(gs);
162.1336 +
162.1337 +        if (b < 0x10) {
162.1338 +            result.append('0');
162.1339 +        }
162.1340 +
162.1341 +        result.append(bs);
162.1342 +
162.1343 +        return result.toString();
162.1344 +    }
162.1345 +}
   163.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   163.2 +++ b/python.source/src/org/netbeans/modules/python/source/elements/AstElement.java	Sun Sep 13 11:47:42 2015 +0200
   163.3 @@ -0,0 +1,117 @@
   163.4 +/*
   163.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   163.6 + *
   163.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   163.8 + *
   163.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  163.10 + * Other names may be trademarks of their respective owners.
  163.11 + *
  163.12 + * The contents of this file are subject to the terms of either the GNU
  163.13 + * General Public License Version 2 only ("GPL") or the Common
  163.14 + * Development and Distribution License("CDDL") (collectively, the
  163.15 + * "License"). You may not use this file except in compliance with the
  163.16 + * License. You can obtain a copy of the License at
  163.17 + * http://www.netbeans.org/cddl-gplv2.html
  163.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  163.19 + * specific language governing permissions and limitations under the
  163.20 + * License.  When distributing the software, include this License Header
  163.21 + * Notice in each file and include the License file at
  163.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  163.23 + * particular file as subject to the "Classpath" exception as provided
  163.24 + * by Oracle in the GPL Version 2 section of the License file that
  163.25 + * accompanied this code. If applicable, add the following below the
  163.26 + * License Header, with the fields enclosed by brackets [] replaced by
  163.27 + * your own identifying information:
  163.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  163.29 + *
  163.30 + * Contributor(s):
  163.31 + *
  163.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  163.33 + */
  163.34 +package org.netbeans.modules.python.source.elements;
  163.35 +
  163.36 +import java.util.Set;
  163.37 +import org.netbeans.modules.csl.api.ElementKind;
  163.38 +import org.netbeans.modules.csl.api.Modifier;
  163.39 +import org.netbeans.modules.csl.api.OffsetRange;
  163.40 +import org.netbeans.modules.csl.spi.ParserResult;
  163.41 +import org.netbeans.modules.python.source.PythonAstUtils;
  163.42 +import org.netbeans.modules.python.source.PythonParserResult;
  163.43 +import org.netbeans.modules.python.source.PythonStructureItem;
  163.44 +import org.netbeans.modules.python.source.PythonStructureScanner;
  163.45 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  163.46 +import org.python.antlr.PythonTree;
  163.47 +import org.python.antlr.ast.Call;
  163.48 +import org.python.antlr.ast.ClassDef;
  163.49 +import org.python.antlr.ast.FunctionDef;
  163.50 +import org.python.antlr.ast.Name;
  163.51 +
  163.52 +/**
  163.53 + * Elements representing a node in a parse tree
  163.54 + *
  163.55 + * @author Tor Norbye
  163.56 + */
  163.57 +public class AstElement extends Element {
  163.58 +    protected PythonTree node;
  163.59 +    protected String name;
  163.60 +    protected ElementKind kind;
  163.61 +    //protected CompilationInfo info;
  163.62 +    protected Set<Modifier> modifiers;
  163.63 +    protected SymbolTable scopes;
  163.64 +
  163.65 +    public AstElement(SymbolTable scopes, PythonTree node, String name, ElementKind kind) {
  163.66 +        //this.info = info;
  163.67 +        this.scopes = scopes;
  163.68 +        this.node = node;
  163.69 +        this.name = name;
  163.70 +        this.kind = kind;
  163.71 +    }
  163.72 +
  163.73 +    public static AstElement create(PythonParserResult result, PythonTree node) {
  163.74 +        SymbolTable scopes = result.getSymbolTable();
  163.75 +
  163.76 +        if (node instanceof FunctionDef) {
  163.77 +            return new PythonStructureItem(scopes, (FunctionDef)node);
  163.78 +        } else if (node instanceof ClassDef) {
  163.79 +            return new PythonStructureItem(scopes, (ClassDef)node);
  163.80 +        } else if (node instanceof Call) {
  163.81 +            String name = PythonAstUtils.getCallName((Call)node);
  163.82 +            return new AstElement(scopes, node, name, ElementKind.METHOD);
  163.83 +        } else if (node instanceof Name) {
  163.84 +            return new AstElement(scopes, node, ((Name)node).getInternalId(), ElementKind.VARIABLE);
  163.85 +        } else {
  163.86 +            return new AstElement(scopes, node, null, ElementKind.OTHER);
  163.87 +        }
  163.88 +    }
  163.89 +
  163.90 +    public PythonTree getNode() {
  163.91 +        return node;
  163.92 +    }
  163.93 +
  163.94 +    @Override
  163.95 +    public String getName() {
  163.96 +        return name;
  163.97 +    }
  163.98 +
  163.99 +    @Override
 163.100 +    public ElementKind getKind() {
 163.101 +        return kind;
 163.102 +    }
 163.103 +
 163.104 +    @Override
 163.105 +    public Set<Modifier> getModifiers() {
 163.106 +        if (modifiers == null) {
 163.107 +            if (name != null && scopes.isPrivate(node, name)) {
 163.108 +                modifiers = IndexedElement.PRIVATE_MODIFIERS;
 163.109 +            } else {
 163.110 +                modifiers = IndexedElement.PUBLIC_MODIFIERS;
 163.111 +            }
 163.112 +        }
 163.113 +
 163.114 +        return modifiers;
 163.115 +    }
 163.116 +
 163.117 +    public Object getSignature() {
 163.118 +        return name;
 163.119 +    }
 163.120 +}
   164.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   164.2 +++ b/python.source/src/org/netbeans/modules/python/source/elements/Element.java	Sun Sep 13 11:47:42 2015 +0200
   164.3 @@ -0,0 +1,85 @@
   164.4 +/*
   164.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   164.6 + *
   164.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   164.8 + *
   164.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  164.10 + * Other names may be trademarks of their respective owners.
  164.11 + *
  164.12 + * The contents of this file are subject to the terms of either the GNU
  164.13 + * General Public License Version 2 only ("GPL") or the Common
  164.14 + * Development and Distribution License("CDDL") (collectively, the
  164.15 + * "License"). You may not use this file except in compliance with the
  164.16 + * License. You can obtain a copy of the License at
  164.17 + * http://www.netbeans.org/cddl-gplv2.html
  164.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  164.19 + * specific language governing permissions and limitations under the
  164.20 + * License.  When distributing the software, include this License Header
  164.21 + * Notice in each file and include the License file at
  164.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  164.23 + * particular file as subject to the "Classpath" exception as provided
  164.24 + * by Oracle in the GPL Version 2 section of the License file that
  164.25 + * accompanied this code. If applicable, add the following below the
  164.26 + * License Header, with the fields enclosed by brackets [] replaced by
  164.27 + * your own identifying information:
  164.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  164.29 + *
  164.30 + * Contributor(s):
  164.31 + *
  164.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  164.33 + */
  164.34 +package org.netbeans.modules.python.source.elements;
  164.35 +
  164.36 +import java.util.Collections;
  164.37 +import java.util.Set;
  164.38 +import org.netbeans.modules.csl.api.ElementHandle;
  164.39 +import org.netbeans.modules.csl.api.ElementKind;
  164.40 +import org.netbeans.modules.csl.api.Modifier;
  164.41 +import org.netbeans.modules.csl.api.OffsetRange;
  164.42 +import org.netbeans.modules.csl.spi.ParserResult;
  164.43 +import org.netbeans.modules.python.api.PythonMIMEResolver;
  164.44 +import org.openide.filesystems.FileObject;
  164.45 +
  164.46 +/**
  164.47 + *
  164.48 + * @author Tor Norbye
  164.49 + */
  164.50 +public abstract class Element implements ElementHandle {
  164.51 +    @Override
  164.52 +    public abstract String getName();
  164.53 +
  164.54 +    @Override
  164.55 +    public abstract ElementKind getKind();
  164.56 +
  164.57 +    @Override
  164.58 +    public String getMimeType() {
  164.59 +        return PythonMIMEResolver.PYTHON_MIME_TYPE;
  164.60 +    }
  164.61 +
  164.62 +    @Override
  164.63 +    public boolean signatureEquals(ElementHandle handle) {
  164.64 +        // XXX TODO
  164.65 +        return false;
  164.66 +    }
  164.67 +
  164.68 +    @Override
  164.69 +    public OffsetRange getOffsetRange(ParserResult pr) {
  164.70 +        // XXX TODO
  164.71 +        return null;
  164.72 +    }
  164.73 +
  164.74 +    @Override
  164.75 +    public FileObject getFileObject() {
  164.76 +        return null;
  164.77 +    }
  164.78 +
  164.79 +    @Override
  164.80 +    public Set<Modifier> getModifiers() {
  164.81 +        return Collections.emptySet();
  164.82 +    }
  164.83 +
  164.84 +    @Override
  164.85 +    public String getIn() {
  164.86 +        return null;
  164.87 +    }
  164.88 +}
   165.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   165.2 +++ b/python.source/src/org/netbeans/modules/python/source/elements/IndexedElement.java	Sun Sep 13 11:47:42 2015 +0200
   165.3 @@ -0,0 +1,527 @@
   165.4 +/*
   165.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   165.6 + *
   165.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   165.8 + *
   165.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  165.10 + * Other names may be trademarks of their respective owners.
  165.11 + *
  165.12 + * The contents of this file are subject to the terms of either the GNU
  165.13 + * General Public License Version 2 only ("GPL") or the Common
  165.14 + * Development and Distribution License("CDDL") (collectively, the
  165.15 + * "License"). You may not use this file except in compliance with the
  165.16 + * License. You can obtain a copy of the License at
  165.17 + * http://www.netbeans.org/cddl-gplv2.html
  165.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  165.19 + * specific language governing permissions and limitations under the
  165.20 + * License.  When distributing the software, include this License Header
  165.21 + * Notice in each file and include the License file at
  165.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  165.23 + * particular file as subject to the "Classpath" exception as provided
  165.24 + * by Oracle in the GPL Version 2 section of the License file that
  165.25 + * accompanied this code. If applicable, add the following below the
  165.26 + * License Header, with the fields enclosed by brackets [] replaced by
  165.27 + * your own identifying information:
  165.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  165.29 + *
  165.30 + * Contributor(s):
  165.31 + *
  165.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  165.33 + */
  165.34 +package org.netbeans.modules.python.source.elements;
  165.35 +
  165.36 +import java.util.Collections;
  165.37 +import java.util.EnumSet;
  165.38 +import java.util.Set;
  165.39 +import org.netbeans.modules.csl.api.ElementKind;
  165.40 +import org.netbeans.modules.csl.api.Modifier;
  165.41 +import org.netbeans.modules.csl.api.OffsetRange;
  165.42 +import org.netbeans.modules.csl.spi.ParserResult;
  165.43 +import org.netbeans.modules.python.source.PythonIndex;
  165.44 +import org.netbeans.modules.python.source.PythonAstUtils;
  165.45 +import org.openide.filesystems.FileObject;
  165.46 +import org.python.antlr.PythonTree;
  165.47 +
  165.48 +/**
  165.49 + * Elements representing information coming from the persistent index
  165.50 + *
  165.51 + * @author Tor Norbye
  165.52 + */
  165.53 +public class IndexedElement extends Element {
  165.54 +    public static final EnumSet<Modifier> PRIVATE_MODIFIERS = EnumSet.of(Modifier.PRIVATE);
  165.55 +    public static final EnumSet<Modifier> PROTECTED_MODIFIERS = EnumSet.of(Modifier.PROTECTED);
  165.56 +    public static final EnumSet<Modifier> STATIC_MODIFIERS = EnumSet.of(Modifier.STATIC);
  165.57 +    public static final EnumSet<Modifier> PRIVATE_STATIC_MODIFIERS = EnumSet.of(Modifier.STATIC, Modifier.PRIVATE);
  165.58 +    public static final EnumSet<Modifier> PROTECTED_STATIC_MODIFIERS = EnumSet.of(Modifier.STATIC, Modifier.PROTECTED);
  165.59 +    public static final Set<Modifier> PUBLIC_MODIFIERS = Collections.emptySet();
  165.60 +
  165.61 +    // Plan: Stash a single item for class entries so I can search by document for the class.
  165.62 +    // Add more types into the types
  165.63 +    /** This method is documented */
  165.64 +    public static final int DOCUMENTED = 1 << 0;
  165.65 +    /** This method is private */
  165.66 +    public static final int PRIVATE = 1 << 2;
  165.67 +    /** This is a function, not a property */
  165.68 +    public static final int FUNCTION = 1 << 3;
  165.69 +    /** This element is "static" (e.g. it's a classvar for fields, class method for methods etc) */
  165.70 +    public static final int STATIC = 1 << 4;
  165.71 +    /** This element is deliberately not documented (rdoc :nodoc:) */
  165.72 +    public static final int NODOC = 1 << 5;
  165.73 +    /** This is a global variable */
  165.74 +    public static final int GLOBAL = 1 << 6;
  165.75 +    /** This is a constructor */
  165.76 +    public static final int CONSTRUCTOR = 1 << 7;
  165.77 +    /** This is a deprecated */
  165.78 +    public static final int DEPRECATED = 1 << 8;
  165.79 +    /** This is a documentation-only definition */
  165.80 +    public static final int DOC_ONLY = 1 << 9;
  165.81 +    /** This is a constant/final */
  165.82 +    public static final int FINAL = 1 << 10;
  165.83 +
  165.84 +    // Flags noting semicolon positions in attributes
  165.85 +    public static final int NAME_INDEX = 0;
  165.86 +    public static final int TYPE_INDEX = 1;
  165.87 +    public static final int FLAG_INDEX = 2;
  165.88 +    public static final int ARG_INDEX = 3;
  165.89 +//    public static final int IN_INDEX = 1;
  165.90 +//    public static final int CASE_SENSITIVE_INDEX = 2;
  165.91 +//    public static final int FLAG_INDEX = 3;
  165.92 +//    public static final int ARG_INDEX = 4;
  165.93 +//    public static final int NODE_INDEX = 5;
  165.94 +//    public static final int DOC_INDEX = 6;
  165.95 +//    public static final int BROWSER_INDEX = 7;
  165.96 +//    public static final int TYPE_INDEX = 8;
  165.97 +    protected final String name;
  165.98 +    protected final ElementKind kind;
  165.99 +    protected String url;
 165.100 +    protected FileObject fileObject;
 165.101 +    protected final String module;
 165.102 +    protected String rhs;
 165.103 +    protected boolean smart;
 165.104 +    protected boolean inherited;
 165.105 +    protected Set<Modifier> modifiers;
 165.106 +    protected PythonTree node;
 165.107 +    protected int flags;
 165.108 +    protected final String attributes;
 165.109 +    protected final String clz;
 165.110 +    protected int order;
 165.111 +
 165.112 +    public IndexedElement(String name, ElementKind kind, String url, String module, String clz, String attributes) {
 165.113 +        this.name = name;
 165.114 +        this.kind = kind;
 165.115 +        this.url = url;
 165.116 +        this.module = module;
 165.117 +        this.clz = clz;
 165.118 +        this.attributes = attributes;
 165.119 +
 165.120 +    // Should be IndexedMethod:
 165.121 +    //assert !((!(this instanceof IndexedMethod)) && (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR)) : this;
 165.122 +    }
 165.123 +
 165.124 +    public static IndexedElement create(String signature, String module, String url, String clz) {
 165.125 +        int semi = signature.indexOf(';');
 165.126 +        assert semi != -1;
 165.127 +
 165.128 +        String name = signature.substring(0, semi);
 165.129 +        int flags = IndexedElement.decode(signature, semi + 3, 0);
 165.130 +
 165.131 +        char type = signature.charAt(semi + 1);
 165.132 +        ElementKind kind;
 165.133 +        switch (type) {
 165.134 +        case 'C':
 165.135 +            kind = ElementKind.CLASS;
 165.136 +            break;
 165.137 +        case 'I':
 165.138 +            kind = ElementKind.MODULE;
 165.139 +            break;
 165.140 +        case 'D':
 165.141 +            kind = ElementKind.VARIABLE;
 165.142 +            break;
 165.143 +        case 'A':
 165.144 +            kind = ElementKind.ATTRIBUTE;
 165.145 +            break;
 165.146 +        case 'F':
 165.147 +        case 'M':
 165.148 +        case 'c': {
 165.149 +            kind = type == 'c' ? ElementKind.CONSTRUCTOR : ElementKind.METHOD;
 165.150 +            IndexedMethod method = new IndexedMethod(name, kind, url, module, clz, signature);
 165.151 +            method.flags = flags;
 165.152 +            return method;
 165.153 +        }
 165.154 +        default:
 165.155 +            kind = ElementKind.OTHER;
 165.156 +            break;
 165.157 +        }
 165.158 +
 165.159 +        IndexedElement element = new IndexedElement(name, kind, url, module, clz, signature);
 165.160 +        element.flags = flags;
 165.161 +        return element;
 165.162 +    }
 165.163 +
 165.164 +    @Override
 165.165 +    public boolean equals(Object obj) {
 165.166 +        if (obj == null) {
 165.167 +            return false;
 165.168 +        }
 165.169 +        if (getClass() != obj.getClass()) {
 165.170 +            return false;
 165.171 +        }
 165.172 +        final IndexedElement other = (IndexedElement)obj;
 165.173 +        if (this.name != other.name && (this.name == null || !this.name.equals(other.name))) {
 165.174 +            return false;
 165.175 +        }
 165.176 +        if (this.module != other.module && (this.module == null || !this.module.equals(other.module))) {
 165.177 +            return false;
 165.178 +        }
 165.179 +        if (this.kind != other.kind) {
 165.180 +            return false;
 165.181 +        }
 165.182 +        return true;
 165.183 +    }
 165.184 +
 165.185 +    public String getModule() {
 165.186 +        return module;
 165.187 +    }
 165.188 +
 165.189 +    @Override
 165.190 +    public int hashCode() {
 165.191 +        int hash = 3;
 165.192 +        hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0);
 165.193 +        hash = 67 * hash + (this.kind != null ? this.kind.hashCode() : 0);
 165.194 +        return hash;
 165.195 +    }
 165.196 +
 165.197 +    @Override
 165.198 +    public String getName() {
 165.199 +        return name;
 165.200 +    }
 165.201 +
 165.202 +    @Override
 165.203 +    public ElementKind getKind() {
 165.204 +        return kind;
 165.205 +    }
 165.206 +
 165.207 +    public String getFilenameUrl() {
 165.208 +        return url;
 165.209 +    }
 165.210 +
 165.211 +    @Override
 165.212 +    public FileObject getFileObject() {
 165.213 +        if ((fileObject == null) && (url != null)) {
 165.214 +            fileObject = PythonIndex.getFileObject(url);
 165.215 +
 165.216 +            if (fileObject == null) {
 165.217 +                // Don't try again
 165.218 +                url = null;
 165.219 +            }
 165.220 +        }
 165.221 +
 165.222 +        return fileObject;
 165.223 +    }
 165.224 +
 165.225 +    public void setFlags(int flags) {
 165.226 +        this.flags = flags;
 165.227 +    }
 165.228 +
 165.229 +    public void setInherited(boolean inherited) {
 165.230 +        this.inherited = inherited;
 165.231 +    }
 165.232 +
 165.233 +    public boolean isInherited() {
 165.234 +        return inherited;
 165.235 +    }
 165.236 +
 165.237 +    public String getType() {
 165.238 +        return null;
 165.239 +    }
 165.240 +
 165.241 +    public String getOrigin() {
 165.242 +        return module;
 165.243 +    }
 165.244 +
 165.245 +    public boolean isSmart() {
 165.246 +        return smart;
 165.247 +    }
 165.248 +
 165.249 +    public void setSmart(boolean smart) {
 165.250 +        this.smart = smart;
 165.251 +    }
 165.252 +
 165.253 +    public String getRhs() {
 165.254 +        if (rhs == null) {
 165.255 +            rhs = module;
 165.256 +            if (rhs.equals("stub_missing")) { // NOI18N
 165.257 +                rhs = "<i>builtin</i>";
 165.258 +            }
 165.259 +        }
 165.260 +        return rhs;
 165.261 +    }
 165.262 +
 165.263 +    public void setRhs(String rhs) {
 165.264 +        this.rhs = rhs;
 165.265 +    }
 165.266 +
 165.267 +    @Override
 165.268 +    public String getIn() {
 165.269 +        return module;
 165.270 +    }
 165.271 +
 165.272 +    public String getSignature() {
 165.273 +        if (clz != null) {
 165.274 +            return clz + "." + name;
 165.275 +        }
 165.276 +
 165.277 +        return name;
 165.278 +    }
 165.279 +
 165.280 +    public String getClz() {
 165.281 +        return clz;
 165.282 +    }
 165.283 +
 165.284 +    public int getOrder() {
 165.285 +        return order;
 165.286 +    }
 165.287 +
 165.288 +    public void setOrder(int order) {
 165.289 +        this.order = order;
 165.290 +    }
 165.291 +
 165.292 +    public static Set<Modifier> getModifiersForName(String name, boolean isPrivate, boolean isProtected, boolean isStatic) {
 165.293 +        Set<Modifier> modifiers;
 165.294 +
 165.295 +        // Private variables: start with __ but doesn't end with __
 165.296 +        // Section 9.6 Private Variables - http://docs.python.org/tut/node11.html
 165.297 +        if (name != null && name.startsWith("__") && !name.endsWith("__")) { // NOI18N
 165.298 +            isPrivate = true;
 165.299 +        } else if (name != null && name.startsWith("_") && !name.endsWith("_")) { // NOI18N
 165.300 +            // From PEP8: Single_leading_underscore: weak "internal use" indicator
 165.301 +            // (e.g. "from M import *" does not import objects whose name
 165.302 +            // starts with an underscore).
 165.303 +            // The protected modifier might work well to visually indicate this.
 165.304 +            isProtected = true;
 165.305 +        }
 165.306 +        if (isPrivate) {
 165.307 +            if (isStatic) {
 165.308 +                modifiers = PRIVATE_STATIC_MODIFIERS;
 165.309 +            } else {
 165.310 +                modifiers = PRIVATE_MODIFIERS;
 165.311 +            }
 165.312 +        } else if (isProtected) {
 165.313 +            if (isStatic) {
 165.314 +                modifiers = PROTECTED_STATIC_MODIFIERS;
 165.315 +            } else {
 165.316 +                modifiers = PROTECTED_MODIFIERS;
 165.317 +            }
 165.318 +        } else {
 165.319 +            if (isStatic) {
 165.320 +                modifiers = STATIC_MODIFIERS;
 165.321 +            } else {
 165.322 +                modifiers = PUBLIC_MODIFIERS;
 165.323 +            }
 165.324 +        }
 165.325 +
 165.326 +        return modifiers;
 165.327 +    }
 165.328 +
 165.329 +    @Override
 165.330 +    public Set<Modifier> getModifiers() {
 165.331 +        if (modifiers == null) {
 165.332 +            modifiers = getModifiersForName(name, isPrivate(), false, isStatic());
 165.333 +        }
 165.334 +
 165.335 +        return modifiers;
 165.336 +    }
 165.337 +
 165.338 +    public PythonTree getNode() {
 165.339 +        if (node == null) {
 165.340 +            node = PythonAstUtils.getForeignNode(this, null);
 165.341 +        }
 165.342 +        return node;
 165.343 +    }
 165.344 +
 165.345 +    @Override
 165.346 +    public String toString() {
 165.347 +        return "IndexedElement:" + name + "," + kind + "," + rhs;
 165.348 +    }
 165.349 +
 165.350 +    protected int getAttributeSection(int section) {
 165.351 +        assert section != 0; // Obtain directly, and logic below (+1) is wrong
 165.352 +        int attributeIndex = 0;
 165.353 +        for (int i = 0; i < section; i++) {
 165.354 +            attributeIndex = attributes.indexOf(';', attributeIndex + 1);
 165.355 +        }
 165.356 +
 165.357 +        assert attributeIndex != -1;
 165.358 +        return attributeIndex + 1;
 165.359 +    }
 165.360 +
 165.361 +    /** Return a string (suitable for persistence) encoding the given flags */
 165.362 +    public static String encode(int flags) {
 165.363 +        return Integer.toString(flags, 16);
 165.364 +    }
 165.365 +
 165.366 +    /** Return flag corresponding to the given encoding chars */
 165.367 +    public static int decode(String s, int startIndex, int defaultValue) {
 165.368 +        int value = 0;
 165.369 +        for (int i = startIndex, n = s.length(); i < n; i++) {
 165.370 +            char c = s.charAt(i);
 165.371 +            if (c == ';') {
 165.372 +                if (i == startIndex) {
 165.373 +                    return defaultValue;
 165.374 +                }
 165.375 +                break;
 165.376 +            }
 165.377 +
 165.378 +            value = value << 4;
 165.379 +
 165.380 +            if (c > '9') {
 165.381 +                value += c - 'a' + 10;
 165.382 +            } else {
 165.383 +                value += c - '0';
 165.384 +            }
 165.385 +        }
 165.386 +
 165.387 +        return value;
 165.388 +    }
 165.389 +
 165.390 +    public static int getFlags(AstElement element) {
 165.391 +        // Return the flags corresponding to the given AST element
 165.392 +        int value = 0;
 165.393 +
 165.394 +        ElementKind k = element.getKind();
 165.395 +        if (k == ElementKind.CONSTRUCTOR) {
 165.396 +            value = value | CONSTRUCTOR;
 165.397 +        }
 165.398 +        if (k == ElementKind.METHOD || k == ElementKind.CONSTRUCTOR) {
 165.399 +            value = value | FUNCTION;
 165.400 +        } else if (k == ElementKind.GLOBAL) {
 165.401 +            value = value | GLOBAL;
 165.402 +        }
 165.403 +        if (element.getModifiers().contains(Modifier.STATIC)) {
 165.404 +            value = value | STATIC;
 165.405 +        }
 165.406 +        if (element.getModifiers().contains(Modifier.DEPRECATED)) {
 165.407 +            value = value | DEPRECATED;
 165.408 +        }
 165.409 +        if (element.getModifiers().contains(Modifier.PRIVATE)) {
 165.410 +            value = value | PRIVATE;
 165.411 +        }
 165.412 +
 165.413 +        return value;
 165.414 +    }
 165.415 +
 165.416 +    public boolean isDocumented() {
 165.417 +        return (flags & DOCUMENTED) != 0;
 165.418 +    }
 165.419 +
 165.420 +    public boolean isPublic() {
 165.421 +        return (flags & PRIVATE) == 0;
 165.422 +    }
 165.423 +
 165.424 +    public boolean isPrivate() {
 165.425 +        return (flags & PRIVATE) != 0;
 165.426 +    }
 165.427 +
 165.428 +    public boolean isFunction() {
 165.429 +        return (flags & FUNCTION) != 0;
 165.430 +    }
 165.431 +
 165.432 +    public boolean isStatic() {
 165.433 +        return (flags & STATIC) != 0;
 165.434 +    }
 165.435 +
 165.436 +    public boolean isNoDoc() {
 165.437 +        return (flags & NODOC) != 0;
 165.438 +    }
 165.439 +
 165.440 +    public boolean isFinal() {
 165.441 +        return (flags & FINAL) != 0;
 165.442 +    }
 165.443 +
 165.444 +    public boolean isConstructor() {
 165.445 +        return (flags & CONSTRUCTOR) != 0;
 165.446 +    }
 165.447 +
 165.448 +    public boolean isDeprecated() {
 165.449 +        return (flags & DEPRECATED) != 0;
 165.450 +    }
 165.451 +
 165.452 +    public boolean isDocOnly() {
 165.453 +        return (flags & DOC_ONLY) != 0;
 165.454 +    }
 165.455 +
 165.456 +    public static String decodeFlags(int flags) {
 165.457 +        StringBuilder sb = new StringBuilder();
 165.458 +        if ((flags & DOCUMENTED) != 0) {
 165.459 +            sb.append("|DOCUMENTED");
 165.460 +        }
 165.461 +
 165.462 +        if ((flags & PRIVATE) != 0) {
 165.463 +            sb.append("|PRIVATE");
 165.464 +        }
 165.465 +
 165.466 +        if ((flags & CONSTRUCTOR) != 0) {
 165.467 +            sb.append("|CONSTRUCTOR");
 165.468 +        } else if ((flags & FUNCTION) != 0) {
 165.469 +            sb.append("|FUNCTION");
 165.470 +        } else if ((flags & GLOBAL) != 0) {
 165.471 +            sb.append("|GLOBAL");
 165.472 +        }
 165.473 +
 165.474 +        if ((flags & STATIC) != 0) {
 165.475 +            sb.append("|STATIC");
 165.476 +        }
 165.477 +
 165.478 +        if ((flags & NODOC) != 0) {
 165.479 +            sb.append("|NODOC");
 165.480 +        }
 165.481 +
 165.482 +        if ((flags & DEPRECATED) != 0) {
 165.483 +            sb.append("|DEPRECATED");
 165.484 +        }
 165.485 +
 165.486 +        if ((flags & DOC_ONLY) != 0) {
 165.487 +            sb.append("|DOC_ONLY");
 165.488 +        }
 165.489 +
 165.490 +        if ((flags & FINAL) != 0) {
 165.491 +            sb.append("|FINAL");
 165.492 +        }
 165.493 +
 165.494 +        if (sb.length() > 0) {
 165.495 +            sb.append("|");
 165.496 +        }
 165.497 +        return sb.toString();
 165.498 +    }
 165.499 +
 165.500 +    // For testsuite
 165.501 +    public static int stringToFlags(String string) {
 165.502 +        int flags = 0;
 165.503 +        if (string.contains("|DOCUMENTED")) {
 165.504 +            flags |= DOCUMENTED;
 165.505 +        }
 165.506 +        if (string.contains("|PRIVATE")) {
 165.507 +            flags |= PRIVATE;
 165.508 +        }
 165.509 +        if (string.contains("|DEPRECATED")) {
 165.510 +            flags |= DEPRECATED;
 165.511 +        }
 165.512 +        if (string.contains("|CONSTRUCTOR")) {
 165.513 +            flags |= CONSTRUCTOR;
 165.514 +        }
 165.515 +//        if (string.indexOf("|PROTECTED") != -1) {
 165.516 +//            flags |= PROTECTED;
 165.517 +//        }
 165.518 +//        if (string.indexOf("|TOPLEVEL") != -1) {
 165.519 +//            flags |= TOPLEVEL;
 165.520 +//        }
 165.521 +        if (string.contains("|STATIC")) {
 165.522 +            flags |= STATIC;
 165.523 +        }
 165.524 +        if (string.contains("|NODOC")) {
 165.525 +            flags |= NODOC;
 165.526 +        }
 165.527 +
 165.528 +        return flags;
 165.529 +    }
 165.530 +}
   166.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   166.2 +++ b/python.source/src/org/netbeans/modules/python/source/elements/IndexedMethod.java	Sun Sep 13 11:47:42 2015 +0200
   166.3 @@ -0,0 +1,88 @@
   166.4 +/*
   166.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   166.6 + *
   166.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   166.8 + *
   166.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  166.10 + * Other names may be trademarks of their respective owners.
  166.11 + *
  166.12 + * The contents of this file are subject to the terms of either the GNU
  166.13 + * General Public License Version 2 only ("GPL") or the Common
  166.14 + * Development and Distribution License("CDDL") (collectively, the
  166.15 + * "License"). You may not use this file except in compliance with the
  166.16 + * License. You can obtain a copy of the License at
  166.17 + * http://www.netbeans.org/cddl-gplv2.html
  166.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  166.19 + * specific language governing permissions and limitations under the
  166.20 + * License.  When distributing the software, include this License Header
  166.21 + * Notice in each file and include the License file at
  166.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  166.23 + * particular file as subject to the "Classpath" exception as provided
  166.24 + * by Oracle in the GPL Version 2 section of the License file that
  166.25 + * accompanied this code. If applicable, add the following below the
  166.26 + * License Header, with the fields enclosed by brackets [] replaced by
  166.27 + * your own identifying information:
  166.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  166.29 + *
  166.30 + * Contributor(s):
  166.31 + *
  166.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  166.33 + */
  166.34 +package org.netbeans.modules.python.source.elements;
  166.35 +
  166.36 +import org.netbeans.modules.csl.api.ElementKind;
  166.37 +
  166.38 +/**
  166.39 + *
  166.40 + * @author Tor Norbye
  166.41 + */
  166.42 +public class IndexedMethod extends IndexedElement {
  166.43 +    private String[] params;
  166.44 +
  166.45 +    public IndexedMethod(String name, ElementKind kind, String url, String module, String clz, String signature) {
  166.46 +        super(name, kind, url, module, clz, signature);
  166.47 +    }
  166.48 +
  166.49 +    public String[] getParams() {
  166.50 +        if (params == null) {
  166.51 +            //int argsBegin = name.length()+3;
  166.52 +            int argsBegin = getAttributeSection(IndexedElement.ARG_INDEX);
  166.53 +            int argsEnd = attributes.indexOf(';', argsBegin);
  166.54 +            assert argsEnd != -1 : attributes;
  166.55 +            if (argsEnd > argsBegin) {
  166.56 +                String paramString = attributes.substring(argsBegin, argsEnd);
  166.57 +                params = paramString.split(",");
  166.58 +            } else {
  166.59 +                params = new String[0];
  166.60 +            }
  166.61 +        }
  166.62 +
  166.63 +        return params;
  166.64 +    }
  166.65 +
  166.66 +    @Override
  166.67 +    public boolean equals(Object obj) {
  166.68 +        if (obj == null) {
  166.69 +            return false;
  166.70 +        }
  166.71 +        if (getClass() != obj.getClass()) {
  166.72 +            return false;
  166.73 +        }
  166.74 +        final IndexedMethod other = (IndexedMethod)obj;
  166.75 +        if (this.attributes != other.attributes && (this.attributes == null || !this.attributes.equals(other.attributes))) {
  166.76 +            return false;
  166.77 +        }
  166.78 +        if (this.clz != other.clz && (this.clz == null || !this.clz.equals(other.clz))) {
  166.79 +            return false;
  166.80 +        }
  166.81 +        return true;
  166.82 +    }
  166.83 +
  166.84 +    @Override
  166.85 +    public int hashCode() {
  166.86 +        int hash = 7;
  166.87 +        hash = 53 * hash + (this.attributes != null ? this.attributes.hashCode() : 0);
  166.88 +        hash = 53 * hash + (this.clz != null ? this.clz.hashCode() : 0);
  166.89 +        return hash;
  166.90 +    }
  166.91 +}
   167.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   167.2 +++ b/python.source/src/org/netbeans/modules/python/source/elements/IndexedPackage.java	Sun Sep 13 11:47:42 2015 +0200
   167.3 @@ -0,0 +1,106 @@
   167.4 +/*
   167.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   167.6 + *
   167.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   167.8 + *
   167.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  167.10 + * Other names may be trademarks of their respective owners.
  167.11 + *
  167.12 + * The contents of this file are subject to the terms of either the GNU
  167.13 + * General Public License Version 2 only ("GPL") or the Common
  167.14 + * Development and Distribution License("CDDL") (collectively, the
  167.15 + * "License"). You may not use this file except in compliance with the
  167.16 + * License. You can obtain a copy of the License at
  167.17 + * http://www.netbeans.org/cddl-gplv2.html
  167.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  167.19 + * specific language governing permissions and limitations under the
  167.20 + * License.  When distributing the software, include this License Header
  167.21 + * Notice in each file and include the License file at
  167.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  167.23 + * particular file as subject to the "Classpath" exception as provided
  167.24 + * by Oracle in the GPL Version 2 section of the License file that
  167.25 + * accompanied this code. If applicable, add the following below the
  167.26 + * License Header, with the fields enclosed by brackets [] replaced by
  167.27 + * your own identifying information:
  167.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  167.29 + *
  167.30 + * If you wish your version of this file to be governed by only the CDDL
  167.31 + * or only the GPL Version 2, indicate your decision by adding
  167.32 + * "[Contributor] elects to include this software in this distribution
  167.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  167.34 + * single choice of license, a recipient has the option to distribute
  167.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  167.36 + * to extend the choice of license to its licensees as provided above.
  167.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  167.38 + * Version 2 license, then the option applies only if the new code is
  167.39 + * made subject to such option by the copyright holder.
  167.40 + *
  167.41 + * Contributor(s):
  167.42 + *
  167.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  167.44 + */
  167.45 +package org.netbeans.modules.python.source.elements;
  167.46 +
  167.47 +import java.util.Collections;
  167.48 +import java.util.Set;
  167.49 +import org.netbeans.modules.csl.api.ElementKind;
  167.50 +import org.netbeans.modules.csl.api.Modifier;
  167.51 +
  167.52 +/**
  167.53 + *
  167.54 + * @author Tor Norbye
  167.55 + */
  167.56 +public class IndexedPackage extends IndexedElement {
  167.57 +    private String pkg;
  167.58 +    private boolean hasMore;
  167.59 +
  167.60 +    public IndexedPackage(String name, String pkg, String url, boolean hasMore) {
  167.61 +        super(name, ElementKind.PACKAGE, url, null, null, null);
  167.62 +        this.pkg = pkg;
  167.63 +        this.hasMore = hasMore;
  167.64 +    }
  167.65 +
  167.66 +    @Override
  167.67 +    public Set<Modifier> getModifiers() {
  167.68 +        return Collections.emptySet();
  167.69 +    }
  167.70 +
  167.71 +    public String getPkg() {
  167.72 +        return pkg;
  167.73 +    }
  167.74 +
  167.75 +    public boolean hasMore() {
  167.76 +        return hasMore;
  167.77 +    }
  167.78 +
  167.79 +    @Override
  167.80 +    public boolean equals(Object obj) {
  167.81 +        if (obj == null) {
  167.82 +            return false;
  167.83 +        }
  167.84 +        if (getClass() != obj.getClass()) {
  167.85 +            return false;
  167.86 +        }
  167.87 +        final IndexedPackage other = (IndexedPackage)obj;
  167.88 +
  167.89 +        // Side effect:
  167.90 +        // If any element thinks we have more
  167.91 +        if (other.hasMore) {
  167.92 +            this.hasMore = other.hasMore;
  167.93 +        } else if (this.hasMore) {
  167.94 +            other.hasMore = this.hasMore;
  167.95 +        }
  167.96 +
  167.97 +        if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
  167.98 +            return false;
  167.99 +        }
 167.100 +        return true;
 167.101 +    }
 167.102 +
 167.103 +    @Override
 167.104 +    public int hashCode() {
 167.105 +        int hash = 7;
 167.106 +        hash = 73 * hash + (this.name != null ? this.name.hashCode() : 0);
 167.107 +        return hash;
 167.108 +    }
 167.109 +}
   168.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   168.2 +++ b/python.source/src/org/netbeans/modules/python/source/impl/PythonProjectSourceLevelQuery.java	Sun Sep 13 11:47:42 2015 +0200
   168.3 @@ -0,0 +1,29 @@
   168.4 +/*
   168.5 + * To change this license header, choose License Headers in Project Properties.
   168.6 + * To change this template file, choose Tools | Templates
   168.7 + * and open the template in the editor.
   168.8 + */
   168.9 +package org.netbeans.modules.python.source.impl;
  168.10 +
  168.11 +import org.netbeans.modules.python.source.queries.SourceLevelQueryImplementation;
  168.12 +import org.netbeans.api.project.FileOwnerQuery;
  168.13 +import org.netbeans.api.project.Project;
  168.14 +import org.openide.filesystems.FileObject;
  168.15 +import org.openide.util.lookup.ServiceProvider;
  168.16 +
  168.17 +@ServiceProvider(service = SourceLevelQueryImplementation.class, position = 400)
  168.18 +public class PythonProjectSourceLevelQuery implements SourceLevelQueryImplementation {
  168.19 +
  168.20 +    @Override
  168.21 +    public Result getSourceLevel(FileObject pythonFile) {
  168.22 +        final Project project = FileOwnerQuery.getOwner(pythonFile);
  168.23 +        if (project != null) {
  168.24 +            SourceLevelQueryImplementation impl = project.getLookup().lookup(SourceLevelQueryImplementation.class);
  168.25 +            if (impl != null) {
  168.26 +                return impl.getSourceLevel(pythonFile);
  168.27 +            }
  168.28 +        }
  168.29 +        return null;
  168.30 +    }
  168.31 +
  168.32 +}
   169.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   169.2 +++ b/python.source/src/org/netbeans/modules/python/source/impl/QuerySupportFactory.java	Sun Sep 13 11:47:42 2015 +0200
   169.3 @@ -0,0 +1,80 @@
   169.4 +/*
   169.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   169.6 + *
   169.7 + * Copyright 2015 Oracle and/or its affiliates. All rights reserved.
   169.8 + *
   169.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  169.10 + * Other names may be trademarks of their respective owners.
  169.11 + *
  169.12 + * The contents of this file are subject to the terms of either the GNU
  169.13 + * General Public License Version 2 only ("GPL") or the Common
  169.14 + * Development and Distribution License("CDDL") (collectively, the
  169.15 + * "License"). You may not use this file except in compliance with the
  169.16 + * License. You can obtain a copy of the License at
  169.17 + * http://www.netbeans.org/cddl-gplv2.html
  169.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  169.19 + * specific language governing permissions and limitations under the
  169.20 + * License.  When distributing the software, include this License Header
  169.21 + * Notice in each file and include the License file at
  169.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  169.23 + * particular file as subject to the "Classpath" exception as provided
  169.24 + * by Oracle in the GPL Version 2 section of the License file that
  169.25 + * accompanied this code. If applicable, add the following below the
  169.26 + * License Header, with the fields enclosed by brackets [] replaced by
  169.27 + * your own identifying information:
  169.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  169.29 + *
  169.30 + * If you wish your version of this file to be governed by only the CDDL
  169.31 + * or only the GPL Version 2, indicate your decision by adding
  169.32 + * "[Contributor] elects to include this software in this distribution
  169.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  169.34 + * single choice of license, a recipient has the option to distribute
  169.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  169.36 + * to extend the choice of license to its licensees as provided above.
  169.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  169.38 + * Version 2 license, then the option applies only if the new code is
  169.39 + * made subject to such option by the copyright holder.
  169.40 + *
  169.41 + * Contributor(s):
  169.42 + *
  169.43 + * Portions Copyrighted 2015 Sun Microsystems, Inc.
  169.44 + */
  169.45 +package org.netbeans.modules.python.source.impl;
  169.46 +
  169.47 +import java.io.IOException;
  169.48 +import java.util.Collection;
  169.49 +import java.util.Collections;
  169.50 +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
  169.51 +import org.netbeans.modules.python.source.PythonIndexer;
  169.52 +import org.openide.filesystems.FileObject;
  169.53 +import org.openide.util.Exceptions;
  169.54 +
  169.55 +/**
  169.56 + *
  169.57 + * @author Ralph Ruijs
  169.58 + */
  169.59 +public final class QuerySupportFactory {
  169.60 +
  169.61 +    
  169.62 +    public static QuerySupport getQuerySupport(final Collection<FileObject> roots) {
  169.63 +        try {
  169.64 +            return QuerySupport.forRoots(PythonIndexer.NAME,
  169.65 +                    PythonIndexer.VERSION,
  169.66 +                    roots.toArray(new FileObject[roots.size()]));
  169.67 +        } catch (IOException ex) {
  169.68 +            Exceptions.printStackTrace(ex);
  169.69 +        }
  169.70 +        return null;
  169.71 +    }
  169.72 +    
  169.73 +    public static QuerySupport getQuerySupport(final FileObject source) {
  169.74 +        return getQuerySupport(QuerySupport.findRoots(source,
  169.75 +                null,
  169.76 +                null,
  169.77 +                Collections.<String>emptySet()));
  169.78 +    }
  169.79 +
  169.80 +    private QuerySupportFactory() {
  169.81 +    }
  169.82 +    
  169.83 +}
   170.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   170.2 +++ b/python.source/src/org/netbeans/modules/python/source/layer.xml	Sun Sep 13 11:47:42 2015 +0200
   170.3 @@ -0,0 +1,71 @@
   170.4 +<?xml version="1.0" encoding="UTF-8"?>
   170.5 +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
   170.6 +<filesystem>
   170.7 +    <folder name="CslPlugins">
   170.8 +        <folder name="text">
   170.9 +            <folder name="x-python">
  170.10 +                <file name="structure.instance">
  170.11 +                    <attr name="instanceClass" stringvalue="org.netbeans.modules.python.source.PythonStructureScanner"/>
  170.12 +                </file>
  170.13 +            </folder>
  170.14 +        </folder>
  170.15 +    </folder>
  170.16 +    <folder name="Editors">
  170.17 +        <folder name="text">
  170.18 +            <folder name="x-python">
  170.19 +                <file name="language.instance">
  170.20 +                    <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.source.lexer.PythonTokenId.language"/>
  170.21 +                    <attr name="instanceOf" stringvalue="org.netbeans.api.lexer.Language"/>
  170.22 +                </file>
  170.23 +            </folder>
  170.24 +        </folder>
  170.25 +    </folder>
  170.26 +    <folder name="OptionsDialog">
  170.27 +        <folder name="PreviewExamples">
  170.28 +            <folder name="text">
  170.29 +                <file name="x-python" url="PythonExample.py"/>
  170.30 +            </folder>
  170.31 +        </folder>
  170.32 +        <folder name="Editor">
  170.33 +            <folder name="Formatting">
  170.34 +                <attr name="position" intvalue="0"/>
  170.35 +                <folder name="text">
  170.36 +                    <folder name="x-python">
  170.37 +                        <file name="Imports.instance">
  170.38 +                            <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  170.39 +                            <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.source.ui.FmtImports.getController"/>
  170.40 +                            <attr name="position" intvalue="150"/>
  170.41 +                        </file>
  170.42 +                      <!-- Not yet implemented
  170.43 +                      <file name="TabsAndIndents.instance">
  170.44 +                          <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  170.45 +                          <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.source.ui.FmtTabsIndents.getController"/>
  170.46 +                          <attr name="position" intvalue="100"/>
  170.47 +                      </file>
  170.48 +                      <file name="Alignment.instance">
  170.49 +                          <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  170.50 +                          <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.source.ui.FmtAlignment.getController"/>
  170.51 +                          <attr name="position" intvalue="200"/>
  170.52 +                      </file>
  170.53 +                      <file name="Wrapping.instance">
  170.54 +                          <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  170.55 +                          <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.source.ui.FmtWrapping.getController"/>
  170.56 +                          <attr name="position" intvalue="400"/>
  170.57 +                      </file>
  170.58 +                      <file name="BlankLines.instance">
  170.59 +                          <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  170.60 +                          <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.source.ui.FmtBlankLines.getController"/>
  170.61 +                          <attr name="position" intvalue="500"/>
  170.62 +                      </file>
  170.63 +                      -->
  170.64 +                        <file name="Spaces.instance">
  170.65 +                            <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  170.66 +                            <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.source.ui.FmtSpaces.getController"/>
  170.67 +                            <attr name="position" intvalue="600"/>
  170.68 +                        </file>
  170.69 +                    </folder>
  170.70 +                </folder>
  170.71 +            </folder>
  170.72 +        </folder>
  170.73 +    </folder>
  170.74 +</filesystem>
   171.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   171.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/Call.java	Sun Sep 13 11:47:42 2015 +0200
   171.3 @@ -0,0 +1,322 @@
   171.4 +/*
   171.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   171.6 + *
   171.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   171.8 + *
   171.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  171.10 + * Other names may be trademarks of their respective owners.
  171.11 + *
  171.12 + * The contents of this file are subject to the terms of either the GNU
  171.13 + * General Public License Version 2 only ("GPL") or the Common
  171.14 + * Development and Distribution License("CDDL") (collectively, the
  171.15 + * "License"). You may not use this file except in compliance with the
  171.16 + * License. You can obtain a copy of the License at
  171.17 + * http://www.netbeans.org/cddl-gplv2.html
  171.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  171.19 + * specific language governing permissions and limitations under the
  171.20 + * License.  When distributing the software, include this License Header
  171.21 + * Notice in each file and include the License file at
  171.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  171.23 + * particular file as subject to the "Classpath" exception as provided
  171.24 + * by Oracle in the GPL Version 2 section of the License file that
  171.25 + * accompanied this code. If applicable, add the following below the
  171.26 + * License Header, with the fields enclosed by brackets [] replaced by
  171.27 + * your own identifying information:
  171.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  171.29 + *
  171.30 + * Contributor(s):
  171.31 + *
  171.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  171.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  171.34 + * Microsystems, Inc. All Rights Reserved.
  171.35 + *
  171.36 + * If you wish your version of this file to be governed by only the CDDL
  171.37 + * or only the GPL Version 2, indicate your decision by adding
  171.38 + * "[Contributor] elects to include this software in this distribution
  171.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  171.40 + * single choice of license, a recipient has the option to distribute
  171.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  171.42 + * to extend the choice of license to its licensees as provided above.
  171.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  171.44 + * Version 2 license, then the option applies only if the new code is
  171.45 + * made subject to such option by the copyright holder.
  171.46 + */
  171.47 +package org.netbeans.modules.python.source.lexer;
  171.48 +
  171.49 +import javax.swing.text.BadLocationException;
  171.50 +import javax.swing.text.Document;
  171.51 +import org.netbeans.api.annotations.common.NonNull;
  171.52 +
  171.53 +import org.netbeans.api.lexer.Token;
  171.54 +import org.netbeans.api.lexer.TokenHierarchy;
  171.55 +import org.netbeans.api.lexer.TokenId;
  171.56 +import org.netbeans.api.lexer.TokenSequence;
  171.57 +import org.netbeans.editor.BaseDocument;
  171.58 +import org.netbeans.editor.Utilities;
  171.59 +import org.openide.util.Exceptions;
  171.60 +
  171.61 +/**
  171.62 + * Class which represents a Call in the source
  171.63 + */
  171.64 +public class Call {
  171.65 +    public static final Call LOCAL = new Call(null, null, false, false);
  171.66 +    public static final Call NONE = new Call(null, null, false, false);
  171.67 +    public static final Call UNKNOWN = new Call(null, null, false, false);
  171.68 +    private final String type;
  171.69 +    private final String lhs;
  171.70 +    private final boolean isStatic;
  171.71 +    private final boolean methodExpected;
  171.72 +
  171.73 +    public Call(String type, String lhs, boolean isStatic, boolean methodExpected) {
  171.74 +        super();
  171.75 +        this.type = type;
  171.76 +        this.lhs = lhs;
  171.77 +        this.methodExpected = methodExpected;
  171.78 +        if (lhs == null) {
  171.79 +            lhs = type;
  171.80 +        }
  171.81 +        this.isStatic = isStatic;
  171.82 +    }
  171.83 +
  171.84 +    public String getType() {
  171.85 +        return type;
  171.86 +    }
  171.87 +
  171.88 +    public String getLhs() {
  171.89 +        return lhs;
  171.90 +    }
  171.91 +
  171.92 +    public boolean isStatic() {
  171.93 +        return isStatic;
  171.94 +    }
  171.95 +
  171.96 +    public boolean isSimpleIdentifier() {
  171.97 +        if (lhs == null) {
  171.98 +            return false;
  171.99 +        }
 171.100 +        // TODO - replace with the new PythonUtil validations
 171.101 +        for (int i = 0, n = lhs.length(); i < n; i++) {
 171.102 +            char c = lhs.charAt(i);
 171.103 +            if (Character.isJavaIdentifierPart(c)) {
 171.104 +                continue;
 171.105 +            }
 171.106 +            return false;
 171.107 +        }
 171.108 +        return true;
 171.109 +    }
 171.110 +
 171.111 +    @Override
 171.112 +    public String toString() {
 171.113 +        if (this == LOCAL) {
 171.114 +            return "LOCAL";
 171.115 +        } else if (this == NONE) {
 171.116 +            return "NONE";
 171.117 +        } else if (this == UNKNOWN) {
 171.118 +            return "UNKNOWN";
 171.119 +        } else {
 171.120 +            return "Call(" + type + "," + lhs + "," + isStatic + ")";
 171.121 +        }
 171.122 +    }
 171.123 +
 171.124 +    /** foo.| or foo.b|  -> we're expecting a method call. For Foo:: we don't know. */
 171.125 +    public boolean isMethodExpected() {
 171.126 +        return this.methodExpected;
 171.127 +    }
 171.128 +
 171.129 +    /**
 171.130 +     * Determine whether the given offset corresponds to a method call on another
 171.131 +     * object. This would happen in these cases:
 171.132 +     *    Foo::|, Foo::Bar::|, Foo.|, Foo.x|, foo.|, foo.x|
 171.133 +     * and not here:
 171.134 +     *   |, Foo|, foo|
 171.135 +     * The method returns the left hand side token, if any, such as "Foo", Foo::Bar",
 171.136 +     * and "foo". If not, it will return null.
 171.137 +     * Note that "self" and "super" are possible return values for the lhs, which mean
 171.138 +     * that you don't have a call on another object. Clients of this method should
 171.139 +     * handle that return value properly (I could return null here, but clients probably
 171.140 +     * want to distinguish self and super in this case so it's useful to return the info.)
 171.141 +     *
 171.142 +     * This method will also try to be smart such that if you have a block or array
 171.143 +     * call, it will return the relevant classnames (e.g. for [1,2].x| it returns "Array").
 171.144 +     */
 171.145 +    @SuppressWarnings("unchecked")
 171.146 +    @NonNull
 171.147 +    public static Call getCallType(BaseDocument doc, TokenHierarchy<Document> th, int offset) {
 171.148 +        TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(th, offset);
 171.149 +
 171.150 +        if (ts == null) {
 171.151 +            return Call.NONE;
 171.152 +        }
 171.153 +
 171.154 +        ts.move(offset);
 171.155 +
 171.156 +        boolean methodExpected = false;
 171.157 +
 171.158 +        if (!ts.moveNext() && !ts.movePrevious()) {
 171.159 +            return Call.NONE;
 171.160 +        }
 171.161 +
 171.162 +        if (ts.offset() == offset) {
 171.163 +            // We're looking at the offset to the RIGHT of the caret
 171.164 +            // position, which could be whitespace, e.g.
 171.165 +            //  "foo.x| " <-- looking at the whitespace
 171.166 +            ts.movePrevious();
 171.167 +        }
 171.168 +
 171.169 +        Token<? extends PythonTokenId> token = ts.token();
 171.170 +
 171.171 +        if (token != null) {
 171.172 +            TokenId id = token.id();
 171.173 +
 171.174 +            if (id == PythonTokenId.WHITESPACE) {
 171.175 +                return Call.LOCAL;
 171.176 +            }
 171.177 +
 171.178 +            // See if we're in the identifier - "x" in "foo.x"
 171.179 +            // I could also be a keyword in case the prefix happens to currently
 171.180 +            // match a keyword, such as "next"
 171.181 +            // However, if we're at the end of the document, x. will lex . as an
 171.182 +            // identifier of text ".", so handle this case specially
 171.183 +            if ((id == PythonTokenId.IDENTIFIER)/* || (id == PythonTokenId.CONSTANT)*/ ||
 171.184 +                    id.primaryCategory().equals("keyword")) {
 171.185 +                String tokenText = token.text().toString();
 171.186 +
 171.187 +                if (".".equals(tokenText)) {
 171.188 +                    // Special case - continue - we'll handle this part next
 171.189 +                    methodExpected = true;
 171.190 +                } else {
 171.191 +                    methodExpected = true;
 171.192 +
 171.193 +                    if (Character.isUpperCase(tokenText.charAt(0))) {
 171.194 +                        methodExpected = false;
 171.195 +                    }
 171.196 +
 171.197 +                    if (!ts.movePrevious()) {
 171.198 +                        return Call.LOCAL;
 171.199 +                    }
 171.200 +                }
 171.201 +
 171.202 +                token = ts.token();
 171.203 +                id = token.id();
 171.204 +            }
 171.205 +
 171.206 +            // If we're not in the identifier we need to be in the dot (in "foo.x").
 171.207 +            // I can't just check for tokens DOT and COLON3 because for unparseable source
 171.208 +            // (like "File.|") the lexer will return the "." as an identifier.
 171.209 +            if (id == PythonTokenId.DOT) {
 171.210 +                methodExpected = true;
 171.211 +            } else if (id == PythonTokenId.IDENTIFIER) {
 171.212 +                String t = token.text().toString();
 171.213 +
 171.214 +                if (t.equals(".")) {
 171.215 +                    methodExpected = true;
 171.216 +                } else {
 171.217 +                    return Call.LOCAL;
 171.218 +                }
 171.219 +            } else {
 171.220 +                return Call.LOCAL;
 171.221 +            }
 171.222 +
 171.223 +            int lastSeparatorOffset = ts.offset();
 171.224 +            int beginOffset = lastSeparatorOffset;
 171.225 +            int lineStart = 0;
 171.226 +
 171.227 +            try {
 171.228 +                if (offset > doc.getLength()) {
 171.229 +                    offset = doc.getLength();
 171.230 +                }
 171.231 +
 171.232 +                lineStart = Utilities.getRowStart(doc, offset);
 171.233 +            } catch (BadLocationException ble) {
 171.234 +                Exceptions.printStackTrace(ble);
 171.235 +            }
 171.236 +
 171.237 +            // Find the beginning of the expression. We'll go past keywords, identifiers
 171.238 +            // and dots or double-colons
 171.239 +            while (ts.movePrevious()) {
 171.240 +                // If we get to the previous line we're done
 171.241 +                if (ts.offset() < lineStart) {
 171.242 +                    break;
 171.243 +                }
 171.244 +
 171.245 +                token = ts.token();
 171.246 +                id = token.id();
 171.247 +
 171.248 +                String tokenText = null;
 171.249 +                if (id == PythonTokenId.ANY_KEYWORD || id == PythonTokenId.IDENTIFIER) {
 171.250 +                    tokenText = token.text().toString();
 171.251 +                }
 171.252 +
 171.253 +                if (id == PythonTokenId.WHITESPACE) {
 171.254 +                    break;
 171.255 +                } else if (id == PythonTokenId.RBRACKET) {
 171.256 +                    return new Call("ListType", null, false, methodExpected);
 171.257 +                } else if (id == PythonTokenId.RBRACE) {
 171.258 +                    return new Call("DictType", null, false, methodExpected);
 171.259 +                } else if ((id == PythonTokenId.STRING_END)/* || (id == PythonTokenId.QUOTED_STRING_END)*/) {
 171.260 +                    return new Call("StringType", null, false, methodExpected);
 171.261 +                } else if ((id == PythonTokenId.IDENTIFIER) && "True".equals(tokenText)) { // NOI18N
 171.262 +                    return new Call("BooleanType", null, false, methodExpected);
 171.263 +                } else if ((id == PythonTokenId.IDENTIFIER) && "False".equals(tokenText)) { // NOI18N
 171.264 +                    return new Call("BooleanType", null, false, methodExpected);
 171.265 +                } else if (((id == PythonTokenId.IDENTIFIER)) ||
 171.266 +                        id.primaryCategory().equals("keyword") || (id == PythonTokenId.DOT)) {
 171.267 +
 171.268 +                    // We're building up a potential expression such as "Test::Unit" so continue looking
 171.269 +                    beginOffset = ts.offset();
 171.270 +
 171.271 +                    continue;
 171.272 +                } else if ((id == PythonTokenId.LPAREN) || (id == PythonTokenId.LBRACE) ||
 171.273 +                        (id == PythonTokenId.LBRACKET)) {
 171.274 +                    // It's an expression for example within a parenthesis, e.g.
 171.275 +                    // yield(^File.join())
 171.276 +                    // in this case we can do top level completion
 171.277 +                    // TODO: There are probably more valid contexts here
 171.278 +                    break;
 171.279 +                } else if (id == PythonTokenId.ANY_OPERATOR) {
 171.280 +                    break;
 171.281 +                } else {
 171.282 +                    // Something else - such as "getFoo().x|" - at this point we don't know the type
 171.283 +                    // so we'll just return unknown
 171.284 +                    return Call.UNKNOWN;
 171.285 +                }
 171.286 +            }
 171.287 +
 171.288 +            if (beginOffset < lastSeparatorOffset) {
 171.289 +                try {
 171.290 +                    String lhs = doc.getText(beginOffset, lastSeparatorOffset - beginOffset);
 171.291 +
 171.292 +                    if (lhs.equals("super") || lhs.equals("self")) { // NOI18N
 171.293 +
 171.294 +                        return new Call(lhs, lhs, false, true);
 171.295 +                    } else if (Character.isUpperCase(lhs.charAt(0))) {
 171.296 +
 171.297 +//                        // Detect constructor calls of the form String.new.^
 171.298 +//                        if (lhs.endsWith(".new")) { // NOI18N
 171.299 +//                            // See if it looks like a type prior to that
 171.300 +//                            String type = lhs.substring(0, lhs.length()-4); // 4=".new".length()
 171.301 +//                            if (PythonUtils.isValidPythonModuleName(type)) {
 171.302 +//                                return new Call(type, lhs, false, methodExpected);
 171.303 +//                            }
 171.304 +//                        }
 171.305 +
 171.306 +                        String type = null;
 171.307 +//                        if (PythonUtils.isValidPythonModuleName(lhs)) {
 171.308 +                        type = lhs;
 171.309 +//                        }
 171.310 +
 171.311 +                        return new Call(type, lhs, true, methodExpected);
 171.312 +                    } else {
 171.313 +                        return new Call(null, lhs, false, methodExpected);
 171.314 +                    }
 171.315 +                } catch (BadLocationException ble) {
 171.316 +                    Exceptions.printStackTrace(ble);
 171.317 +                }
 171.318 +            } else {
 171.319 +                return Call.UNKNOWN;
 171.320 +            }
 171.321 +        }
 171.322 +
 171.323 +        return Call.LOCAL;
 171.324 +    }
 171.325 +}
   172.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   172.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/PythonCommentLexer.java	Sun Sep 13 11:47:42 2015 +0200
   172.3 @@ -0,0 +1,229 @@
   172.4 +/*
   172.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   172.6 + *
   172.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   172.8 + *
   172.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  172.10 + * Other names may be trademarks of their respective owners.
  172.11 + *
  172.12 + * The contents of this file are subject to the terms of either the GNU
  172.13 + * General Public License Version 2 only ("GPL") or the Common
  172.14 + * Development and Distribution License("CDDL") (collectively, the
  172.15 + * "License"). You may not use this file except in compliance with the
  172.16 + * License. You can obtain a copy of the License at
  172.17 + * http://www.netbeans.org/cddl-gplv2.html
  172.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  172.19 + * specific language governing permissions and limitations under the
  172.20 + * License.  When distributing the software, include this License Header
  172.21 + * Notice in each file and include the License file at
  172.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  172.23 + * particular file as subject to the "Classpath" exception as provided
  172.24 + * by Oracle in the GPL Version 2 section of the License file that
  172.25 + * accompanied this code. If applicable, add the following below the
  172.26 + * License Header, with the fields enclosed by brackets [] replaced by
  172.27 + * your own identifying information:
  172.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  172.29 + *
  172.30 + * Contributor(s):
  172.31 + *
  172.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  172.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  172.34 + * Microsystems, Inc. All Rights Reserved.
  172.35 + *
  172.36 + * If you wish your version of this file to be governed by only the CDDL
  172.37 + * or only the GPL Version 2, indicate your decision by adding
  172.38 + * "[Contributor] elects to include this software in this distribution
  172.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  172.40 + * single choice of license, a recipient has the option to distribute
  172.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  172.42 + * to extend the choice of license to its licensees as provided above.
  172.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  172.44 + * Version 2 license, then the option applies only if the new code is
  172.45 + * made subject to such option by the copyright holder.
  172.46 + */
  172.47 +package org.netbeans.modules.python.source.lexer;
  172.48 +
  172.49 +import org.netbeans.api.lexer.Token;
  172.50 +import org.netbeans.spi.lexer.Lexer;
  172.51 +import org.netbeans.spi.lexer.LexerInput;
  172.52 +import org.netbeans.spi.lexer.LexerRestartInfo;
  172.53 +import org.netbeans.spi.lexer.TokenFactory;
  172.54 +
  172.55 +/**
  172.56 + * A lexer for python comments.
  172.57 + *
  172.58 + * Highlights TODO items and certain keywords (like @-param and @-type (without -)).
  172.59 + *
  172.60 + * @author Tor Norbye
  172.61 + */
  172.62 +public class PythonCommentLexer implements Lexer<PythonCommentTokenId> {
  172.63 +    private static final int EOF = LexerInput.EOF;
  172.64 +    private final LexerInput input;
  172.65 +    private final TokenFactory<PythonCommentTokenId> tokenFactory;
  172.66 +    private final boolean substituting;
  172.67 +
  172.68 +    private static enum State {
  172.69 +        INIT,
  172.70 +        /** We've just seen @type */
  172.71 +        SEEN_TYPE_KEY,
  172.72 +        /** We've just seen @type< > */
  172.73 +        SEEN_TYPE_WS,
  172.74 +        /** We've just seen @type <varname> */
  172.75 +        SEEN_NAME,
  172.76 +        /** We've just seen @type varname< > */
  172.77 +        SEEN_NAME_WS
  172.78 +    };
  172.79 +    private State state;
  172.80 +
  172.81 +    /**
  172.82 +     * A Lexer for Python strings
  172.83 +     * @param substituting If true, handle substitution rules for double quoted strings, otherwise
  172.84 +     *    single quoted strings.
  172.85 +     */
  172.86 +    public PythonCommentLexer(LexerRestartInfo<PythonCommentTokenId> info, boolean substituting) {
  172.87 +        this.input = info.input();
  172.88 +        this.tokenFactory = info.tokenFactory();
  172.89 +        this.substituting = substituting;
  172.90 +        state = (State)info.state();
  172.91 +        if (state == null) {
  172.92 +            state = State.INIT;
  172.93 +        }
  172.94 +    }
  172.95 +
  172.96 +    @Override
  172.97 +    public Object state() {
  172.98 +        return state;
  172.99 +    }
 172.100 +
 172.101 +    @Override
 172.102 +    public Token<PythonCommentTokenId> nextToken() {
 172.103 +        switch (state) {
 172.104 +        case SEEN_NAME:
 172.105 +        case SEEN_TYPE_KEY:
 172.106 +            while (true) {
 172.107 +                int ch = input.read();
 172.108 +                if (ch == ':' && state == State.SEEN_NAME && input.readLength() == 1) {
 172.109 +                    continue;
 172.110 +                }
 172.111 +                if (ch == EOF || !Character.isWhitespace(ch)) {
 172.112 +                    if (ch != EOF) {
 172.113 +                        input.backup(1);
 172.114 +                    }
 172.115 +                    if (input.readLength() > 0) {
 172.116 +                        state = (state == State.SEEN_TYPE_KEY) ? State.SEEN_TYPE_WS : State.SEEN_NAME_WS;
 172.117 +                        return tokenFactory.createToken(PythonCommentTokenId.SEPARATOR,
 172.118 +                                input.readLength());
 172.119 +                    } else {
 172.120 +                        return null;
 172.121 +                    }
 172.122 +                }
 172.123 +            }
 172.124 +
 172.125 +        case SEEN_NAME_WS:
 172.126 +        case SEEN_TYPE_WS:
 172.127 +            while (true) {
 172.128 +                int ch = input.read();
 172.129 +                if (ch == EOF || Character.isWhitespace(ch) || ch == ':') {
 172.130 +                    if (ch != EOF) {
 172.131 +                        input.backup(1);
 172.132 +                    }
 172.133 +                    if (input.readLength() > 0) {
 172.134 +                        State nextState;
 172.135 +                        PythonCommentTokenId id;
 172.136 +                        if (state == State.SEEN_TYPE_WS) {
 172.137 +                            nextState = State.SEEN_NAME;
 172.138 +                            id = PythonCommentTokenId.VARNAME;
 172.139 +                        } else {
 172.140 +                            nextState = State.INIT;
 172.141 +                            id = PythonCommentTokenId.TYPE;
 172.142 +                        }
 172.143 +                        state = nextState;
 172.144 +                        return tokenFactory.createToken(id, input.readLength());
 172.145 +                    } else if (ch == EOF) {
 172.146 +                        return null;
 172.147 +                    } else {
 172.148 +                        // Error - : without an actual var name
 172.149 +                        state = State.INIT;
 172.150 +                        return nextToken(); // recurse
 172.151 +                    }
 172.152 +                }
 172.153 +            }
 172.154 +        default:
 172.155 +        case INIT: {
 172.156 +
 172.157 +            int last = EOF;
 172.158 +            while (true) {
 172.159 +                int ch = input.read();
 172.160 +
 172.161 +                switch (ch) {
 172.162 +                case EOF:
 172.163 +                    if (input.readLength() > 0) {
 172.164 +                        return tokenFactory.createToken(PythonCommentTokenId.TEXT,
 172.165 +                                input.readLength());
 172.166 +                    } else {
 172.167 +                        return null;
 172.168 +                    }
 172.169 +
 172.170 +                case '@': {
 172.171 +                    // Is it "@type"
 172.172 +                    int initialReadLength = input.readLength();
 172.173 +                    if (input.read() == 't' && input.read() == 'y' && input.read() == 'p' && input.read() == 'e') {
 172.174 +                        if (input.readLength() > 5) {
 172.175 +                            input.backup(5);
 172.176 +                            // Finish this token such that we can do a dedicated token for the @type item.
 172.177 +                            return tokenFactory.createToken(PythonCommentTokenId.TEXT,
 172.178 +                                    input.readLength());
 172.179 +                        }
 172.180 +                        state = State.SEEN_TYPE_KEY;
 172.181 +                        return tokenFactory.createToken(PythonCommentTokenId.TYPEKEY,
 172.182 +                                input.readLength());
 172.183 +                    }
 172.184 +                    if (input.readLength() > initialReadLength) {
 172.185 +                        input.backup(input.readLength() - initialReadLength);
 172.186 +                    } else {
 172.187 +                        return tokenFactory.createToken(PythonCommentTokenId.TEXT,
 172.188 +                                input.readLength());
 172.189 +                    }
 172.190 +                }
 172.191 +                break;
 172.192 +
 172.193 +                case 'T': {
 172.194 +                    if (last == EOF || !Character.isLetter(last)) {
 172.195 +                        // Is it "\wTODO\w" ?
 172.196 +                        int initialReadLength = input.readLength();
 172.197 +                        if (input.read() == 'O' && input.read() == 'D' && input.read() == 'O') {
 172.198 +                            int peek = input.read();
 172.199 +                            input.backup(1);
 172.200 +                            if (peek == EOF || !Character.isLetter(peek)) {
 172.201 +                                if (input.readLength() > 4) {
 172.202 +                                    input.backup(4);
 172.203 +                                    // Finish this token such that we can do a dedicated token for the @type item.
 172.204 +                                    return tokenFactory.createToken(PythonCommentTokenId.TEXT,
 172.205 +                                            input.readLength());
 172.206 +                                }
 172.207 +                                return tokenFactory.createToken(PythonCommentTokenId.TODO,
 172.208 +                                        input.readLength());
 172.209 +                            }
 172.210 +                        }
 172.211 +                        if (input.readLength() > initialReadLength) {
 172.212 +                            input.backup(input.readLength() - initialReadLength);
 172.213 +                        } else {
 172.214 +                            return tokenFactory.createToken(PythonCommentTokenId.TEXT,
 172.215 +                                    input.readLength());
 172.216 +                        }
 172.217 +                    }
 172.218 +                }
 172.219 +                break;
 172.220 +                }
 172.221 +
 172.222 +                last = ch;
 172.223 +            }
 172.224 +
 172.225 +        }
 172.226 +        }
 172.227 +    }
 172.228 +
 172.229 +    @Override
 172.230 +    public void release() {
 172.231 +    }
 172.232 +}
   173.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   173.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/PythonCommentTokenId.java	Sun Sep 13 11:47:42 2015 +0200
   173.3 @@ -0,0 +1,120 @@
   173.4 +/*
   173.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   173.6 + *
   173.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   173.8 + *
   173.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  173.10 + * Other names may be trademarks of their respective owners.
  173.11 + *
  173.12 + * The contents of this file are subject to the terms of either the GNU
  173.13 + * General Public License Version 2 only ("GPL") or the Common
  173.14 + * Development and Distribution License("CDDL") (collectively, the
  173.15 + * "License"). You may not use this file except in compliance with the
  173.16 + * License. You can obtain a copy of the License at
  173.17 + * http://www.netbeans.org/cddl-gplv2.html
  173.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  173.19 + * specific language governing permissions and limitations under the
  173.20 + * License.  When distributing the software, include this License Header
  173.21 + * Notice in each file and include the License file at
  173.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  173.23 + * particular file as subject to the "Classpath" exception as provided
  173.24 + * by Oracle in the GPL Version 2 section of the License file that
  173.25 + * accompanied this code. If applicable, add the following below the
  173.26 + * License Header, with the fields enclosed by brackets [] replaced by
  173.27 + * your own identifying information:
  173.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  173.29 + *
  173.30 + * Contributor(s):
  173.31 + *
  173.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  173.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  173.34 + * Microsystems, Inc. All Rights Reserved.
  173.35 + *
  173.36 + * If you wish your version of this file to be governed by only the CDDL
  173.37 + * or only the GPL Version 2, indicate your decision by adding
  173.38 + * "[Contributor] elects to include this software in this distribution
  173.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  173.40 + * single choice of license, a recipient has the option to distribute
  173.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  173.42 + * to extend the choice of license to its licensees as provided above.
  173.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  173.44 + * Version 2 license, then the option applies only if the new code is
  173.45 + * made subject to such option by the copyright holder.
  173.46 + */
  173.47 +package org.netbeans.modules.python.source.lexer;
  173.48 +
  173.49 +import java.util.Collection;
  173.50 +import java.util.EnumSet;
  173.51 +import java.util.Map;
  173.52 +
  173.53 +import org.netbeans.api.lexer.InputAttributes;
  173.54 +import org.netbeans.api.lexer.Language;
  173.55 +import org.netbeans.api.lexer.LanguagePath;
  173.56 +import org.netbeans.api.lexer.Token;
  173.57 +import org.netbeans.api.lexer.TokenId;
  173.58 +import org.netbeans.spi.lexer.LanguageEmbedding;
  173.59 +import org.netbeans.spi.lexer.LanguageHierarchy;
  173.60 +import org.netbeans.spi.lexer.Lexer;
  173.61 +import org.netbeans.spi.lexer.LexerRestartInfo;
  173.62 +
  173.63 +/**
  173.64 + *
  173.65 + * @author Tor Norbye
  173.66 + */
  173.67 +public enum PythonCommentTokenId implements TokenId {
  173.68 +    TEXT("comment"),
  173.69 +    KEYWORD("comment"),
  173.70 +    SEPARATOR("comment"),
  173.71 +    TYPEKEY("comment"),
  173.72 +    VARNAME("comment"),
  173.73 +    TYPE("comment"),
  173.74 +    TODO("comment");
  173.75 +    private final String primaryCategory;
  173.76 +
  173.77 +    PythonCommentTokenId() {
  173.78 +        this(null);
  173.79 +    }
  173.80 +
  173.81 +    PythonCommentTokenId(String primaryCategory) {
  173.82 +        this.primaryCategory = primaryCategory;
  173.83 +    }
  173.84 +
  173.85 +    @Override
  173.86 +    public String primaryCategory() {
  173.87 +        return primaryCategory;
  173.88 +    }
  173.89 +    public static final Language<PythonCommentTokenId> language =
  173.90 +            new LanguageHierarchy<PythonCommentTokenId>() {
  173.91 +                @Override
  173.92 +                protected Collection<PythonCommentTokenId> createTokenIds() {
  173.93 +                    return EnumSet.allOf(PythonCommentTokenId.class);
  173.94 +                }
  173.95 +
  173.96 +                @Override
  173.97 +                protected Map<String, Collection<PythonCommentTokenId>> createTokenCategories() {
  173.98 +                    return null; // no extra categories
  173.99 +                }
 173.100 +
 173.101 +                @Override
 173.102 +                protected Lexer<PythonCommentTokenId> createLexer(
 173.103 +                        LexerRestartInfo<PythonCommentTokenId> info) {
 173.104 +                    return new PythonCommentLexer(info, true);
 173.105 +                }
 173.106 +
 173.107 +                @Override
 173.108 +                protected LanguageEmbedding<?> embedding(
 173.109 +                        Token<PythonCommentTokenId> token, LanguagePath languagePath,
 173.110 +                        InputAttributes inputAttributes) {
 173.111 +                    return null; // No embedding
 173.112 +                }
 173.113 +
 173.114 +                @Override
 173.115 +                public String mimeType() {
 173.116 +                    return "text/x-python-comment"; // NOI18N
 173.117 +                }
 173.118 +            }.language();
 173.119 +
 173.120 +    public static Language<PythonCommentTokenId> language() {
 173.121 +        return language;
 173.122 +    }
 173.123 +}
   174.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   174.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/PythonLexer.java	Sun Sep 13 11:47:42 2015 +0200
   174.3 @@ -0,0 +1,928 @@
   174.4 +/*
   174.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   174.6 + *
   174.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   174.8 + *
   174.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  174.10 + * Other names may be trademarks of their respective owners.
  174.11 + *
  174.12 + * The contents of this file are subject to the terms of either the GNU
  174.13 + * General Public License Version 2 only ("GPL") or the Common
  174.14 + * Development and Distribution License("CDDL") (collectively, the
  174.15 + * "License"). You may not use this file except in compliance with the
  174.16 + * License. You can obtain a copy of the License at
  174.17 + * http://www.netbeans.org/cddl-gplv2.html
  174.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  174.19 + * specific language governing permissions and limitations under the
  174.20 + * License.  When distributing the software, include this License Header
  174.21 + * Notice in each file and include the License file at
  174.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  174.23 + * particular file as subject to the "Classpath" exception as provided
  174.24 + * by Oracle in the GPL Version 2 section of the License file that
  174.25 + * accompanied this code. If applicable, add the following below the
  174.26 + * License Header, with the fields enclosed by brackets [] replaced by
  174.27 + * your own identifying information:
  174.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  174.29 + *
  174.30 + * Contributor(s):
  174.31 + *
  174.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  174.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  174.34 + * Microsystems, Inc. All Rights Reserved.
  174.35 + *
  174.36 + * If you wish your version of this file to be governed by only the CDDL
  174.37 + * or only the GPL Version 2, indicate your decision by adding
  174.38 + * "[Contributor] elects to include this software in this distribution
  174.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  174.40 + * single choice of license, a recipient has the option to distribute
  174.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  174.42 + * to extend the choice of license to its licensees as provided above.
  174.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  174.44 + * Version 2 license, then the option applies only if the new code is
  174.45 + * made subject to such option by the copyright holder.
  174.46 + */
  174.47 +package org.netbeans.modules.python.source.lexer;
  174.48 +
  174.49 +import org.netbeans.api.lexer.Token;
  174.50 +import org.netbeans.api.lexer.TokenUtilities;
  174.51 +import org.netbeans.spi.lexer.Lexer;
  174.52 +import org.netbeans.spi.lexer.LexerInput;
  174.53 +import org.netbeans.spi.lexer.LexerRestartInfo;
  174.54 +import org.netbeans.spi.lexer.TokenFactory;
  174.55 +
  174.56 +/**
  174.57 + * Lexer for Python.
  174.58 + *
  174.59 + * This is a hand written lexer for Python which recognizes the logical token types
  174.60 + * we care about within the IDE support.
  174.61 + *
  174.62 + * Initially, we were using Jython's lexer directly here. However, that had some
  174.63 + * problems:
  174.64 + *
  174.65 + * <ul>
  174.66 + *   <li>
  174.67 + *     In the IDE, we have to support incremental parsing. Not only is this a must
  174.68 + *     from a user performance perspective (typing a keystroke near the bottom of a
  174.69 + *     2,000 line file shouldn't cause complete re-lexing of the entire document), but
  174.70 + *     the NetBeans APIs require it; they restart the lexer on the nearest token
  174.71 + *     boundary.
  174.72 + *     ANTLR doesn't support incremental lexing. I looked into what it would take
  174.73 + *     to patch it to do so (as I have done for JRuby in the Ruby support), but
  174.74 + *     it (a) wasn't trivial, and (b) would require a LOT of data to be stored for
  174.75 + *     every token boundary.
  174.76 + *   </li>
  174.77 + *   <li>
  174.78 + *     Similarly, we need to put our lexer on top of a LexerInput, and it is not
  174.79 + *     particularly compatible with the way ANTLR handles input. We had an
  174.80 + *     adapter class for this which was jumping through various hoops to expose
  174.81 + *     the LexerInput as ANTLR input. However, it had some severe problems with
  174.82 + *     large inputs.
  174.83 + *   </li>
  174.84 + *   <li>
  174.85 + *     We need slightly different token divisions. For example, for matching bracket
  174.86 + *     purposes, we'd like to have strings split into string delimiters and the
  174.87 + *     string contents. Similarly, Jython did some things like coalesce all whitespace
  174.88 + *     around a newline into that newline token which causes some complications
  174.89 + *     for our token analysis.
  174.90 + *   </li>
  174.91 + *   <li>
  174.92 + *     For Ruby, I decided to use the JRuby lexer because JRuby lexing is very
  174.93 + *     difficult. They have a huge complicated class to do the lexing - and there's
  174.94 + *     no Ruby language spec.  Python on the other hand seems to have a very simple
  174.95 + *     lexing model, and a clear spec and grammar, so I don't feel worried that
  174.96 + *     our custom Python lexer is going to have a lot of corner case bugs.
  174.97 + *   </li>
  174.98 + * </ul>
  174.99 + *
 174.100 + * @author Tor Norbye
 174.101 + */
 174.102 +public final class PythonLexer implements Lexer<PythonTokenId> {
 174.103 +    public static final String COMMENT_CAT = "comment";
 174.104 +    public static final String KEYWORD_CAT = "keyword"; // NOI18N
 174.105 +    public static final String STRING_CAT = "string"; // NOI18N
 174.106 +    public static final String WHITESPACE_CAT = "whitespace"; // NOI18N
 174.107 +    public static final String OPERATOR_CAT = "operator"; // NOI18N
 174.108 +    public static final String SEPARATOR_CAT = "separator"; // NOI18N
 174.109 +    public static final String ERROR_CAT = "error"; // NOI18N
 174.110 +    public static final String NUMBER_CAT = "number"; // NOI18N
 174.111 +    public static final String IDENTIFIER_CAT = "identifier"; // NOI18N
 174.112 +    private static final int EOF = LexerInput.EOF;
 174.113 +    private final LexerInput input;
 174.114 +    private final TokenFactory<PythonTokenId> tokenFactory;
 174.115 +
 174.116 +    // Lexer state - preserved per token boundary
 174.117 +    private enum State {
 174.118 +        /** Normal state, same state as on entry into a Python file */
 174.119 +        INIT,
 174.120 +        /** We've processed the beginning string delimiter of a double-quoted short string */
 174.121 +        BEGIN_SHORTSTRING_DOUBLE,
 174.122 +        /** We've processed the beginning string delimiter of a single-quoted short string */
 174.123 +        BEGIN_SHORTSTRING_SINGLE,
 174.124 +        /** We've processed the beginning string delimiter of a double-quoted long string */
 174.125 +        BEGIN_LONGSTRING_DOUBLE,
 174.126 +        /** We've processed the beginning string delimiter of a singl-quoted long string */
 174.127 +        BEGIN_LONGSTRING_SINGLE,
 174.128 +        /** We've processed the string content in a double-quoted short string */
 174.129 +        END_SHORTSTRING_DOUBLE,
 174.130 +        /** We've processed the string content in a single-quoted short string */
 174.131 +        END_SHORTSTRING_SINGLE,
 174.132 +        /** We've processed the string content in a double-quoted long string */
 174.133 +        END_LONGSTRING_DOUBLE,
 174.134 +        /** We've processed the string content in a single-quoted long string */
 174.135 +        END_LONGSTRING_SINGLE,
 174.136 +    };
 174.137 +    private State state;
 174.138 +
 174.139 +    public PythonLexer(LexerRestartInfo<PythonTokenId> info) {
 174.140 +        this.input = info.input();
 174.141 +        this.tokenFactory = info.tokenFactory();
 174.142 +
 174.143 +        state = (State)info.state();
 174.144 +        if (state == null) {
 174.145 +            state = State.INIT;
 174.146 +        }
 174.147 +    }
 174.148 +
 174.149 +    @Override
 174.150 +    public Object state() {
 174.151 +        return state;
 174.152 +    }
 174.153 +
 174.154 +    private Token<PythonTokenId> createToken(PythonTokenId id, int tokenLength) {
 174.155 +        String fixedText = id.fixedText();
 174.156 +        return (fixedText != null) ? tokenFactory.getFlyweightToken(id, fixedText)
 174.157 +                : tokenFactory.createToken(id, tokenLength);
 174.158 +    }
 174.159 +
 174.160 +    @SuppressWarnings("fallthrough")
 174.161 +    @Override
 174.162 +    public Token<PythonTokenId> nextToken() {
 174.163 +        switch (state) {
 174.164 +        case INIT: {
 174.165 +            int ch = input.read();
 174.166 +            switch (ch) {
 174.167 +            case EOF:
 174.168 +                return null;
 174.169 +
 174.170 +            // Newline
 174.171 +            case '\n':
 174.172 +                assert input.readLength() == 1;
 174.173 +                return createToken(PythonTokenId.NEWLINE, 1);
 174.174 +
 174.175 +            // Whitespace
 174.176 +            case ' ':
 174.177 +            case '\t': {
 174.178 +                for (; ch != EOF; ch = input.read()) {
 174.179 +                    if (ch != ' ' && ch != '\t') {
 174.180 +                        break;
 174.181 +                    }
 174.182 +                }
 174.183 +                input.backup(1);
 174.184 +                return createToken(PythonTokenId.WHITESPACE, input.readLength());
 174.185 +            }
 174.186 +
 174.187 +            // Comment
 174.188 +            case '#': {
 174.189 +                ch = input.read();
 174.190 +                while (ch != EOF && ch != '\n') {
 174.191 +                    ch = input.read();
 174.192 +                }
 174.193 +                input.backup(1);
 174.194 +                return createToken(PythonTokenId.COMMENT, input.readLength());
 174.195 +            }
 174.196 +
 174.197 +            case '.': {
 174.198 +                assert input.readLength() == 1;
 174.199 +                int peek = input.read();
 174.200 +                input.backup(1);
 174.201 +                if (!Character.isDigit(peek)) {
 174.202 +                    return createToken(PythonTokenId.DOT, 1);
 174.203 +                } // else: Fallthrough to process the number!!
 174.204 +            } // FALLTHROUGH
 174.205 +            // FALLTHROUGH!!!!
 174.206 +
 174.207 +            // Number (integer, float, complex)
 174.208 +            case '0':
 174.209 +            case '1':
 174.210 +            case '2':
 174.211 +            case '3':
 174.212 +            case '4':
 174.213 +            case '5':
 174.214 +            case '6':
 174.215 +            case '7':
 174.216 +            case '8':
 174.217 +            case '9': {
 174.218 +                if (ch == '0') {
 174.219 +                    int peek = input.read();
 174.220 +                    if (peek == 'x' || peek == 'X') {
 174.221 +                        // Hex
 174.222 +                        ch = input.read();
 174.223 +                        while (ch != EOF) {
 174.224 +                            if (!(Character.isDigit(ch) ||
 174.225 +                                    (ch >= 'a' && ch <= 'f') ||
 174.226 +                                    (ch >= 'A' && ch <= 'F'))) {
 174.227 +                                break;
 174.228 +                            }
 174.229 +                            ch = input.read();
 174.230 +                        }
 174.231 +                        if (ch != 'l' && (ch != 'L')) {
 174.232 +                            input.backup(1);
 174.233 +                        }
 174.234 +                        return createToken(PythonTokenId.INT_LITERAL, input.readLength());
 174.235 +                    }
 174.236 +                    input.backup(1);
 174.237 +                }
 174.238 +                boolean isFloat = false;
 174.239 +                digitLoop:
 174.240 +                for (; ch != EOF; ch = input.read()) {
 174.241 +                    switch (ch) {
 174.242 +                    case '0':
 174.243 +                    case '1':
 174.244 +                    case '2':
 174.245 +                    case '3':
 174.246 +                    case '4':
 174.247 +                    case '5':
 174.248 +                    case '6':
 174.249 +                    case '7':
 174.250 +                    case '8':
 174.251 +                    case '9':
 174.252 +                        continue;
 174.253 +                    case '.':
 174.254 +                        isFloat = true;
 174.255 +                        continue;
 174.256 +                    case 'e': // Exponent
 174.257 +                    case 'E': {
 174.258 +                        int peek = input.read();
 174.259 +                        if (peek != '+' && peek != '-') {
 174.260 +                            input.backup(1);
 174.261 +                        }
 174.262 +                        ch = input.read();
 174.263 +                        while (ch != EOF) {
 174.264 +                            if (!Character.isDigit(ch)) {
 174.265 +                                break;
 174.266 +                            }
 174.267 +                            ch = input.read();
 174.268 +                        }
 174.269 +                        if (ch != 'j' && ch != 'J') {
 174.270 +                            input.backup(1);
 174.271 +                        }
 174.272 +                        return createToken(PythonTokenId.FLOAT_LITERAL, input.readLength());
 174.273 +                    }
 174.274 +                    case 'j': // Imaginary
 174.275 +                    case 'J':
 174.276 +                        isFloat = true;
 174.277 +                        break digitLoop;
 174.278 +                    case 'l': // Long
 174.279 +                    case 'L':
 174.280 +                        break digitLoop;
 174.281 +                    case EOF:
 174.282 +                    default:
 174.283 +                        input.backup(1);
 174.284 +                        break digitLoop;
 174.285 +
 174.286 +                    }
 174.287 +                }
 174.288 +
 174.289 +                return createToken(isFloat ? PythonTokenId.FLOAT_LITERAL : PythonTokenId.INT_LITERAL, input.readLength());
 174.290 +            }
 174.291 +
 174.292 +            // Operators and delimiters
 174.293 +            case '+': // +,+=
 174.294 +                if (input.read() != '=') {
 174.295 +                    input.backup(1);
 174.296 +                }
 174.297 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 174.298 +            case '-': // -,-=
 174.299 +                if (input.read() != '=') {
 174.300 +                    input.backup(1);
 174.301 +                }
 174.302 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 174.303 +            case '*': { // *,**,*=, **=
 174.304 +                int peek = input.read();
 174.305 +                if (peek == '=') {
 174.306 +                    // No need to back up, include it
 174.307 +                } else if (peek == '*') {
 174.308 +                    peek = input.read();
 174.309 +                    if (peek != '=') {
 174.310 +                        input.backup(1);
 174.311 +                    }
 174.312 +                } else {
 174.313 +                    input.backup(1);
 174.314 +                }
 174.315 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 174.316 +            }
 174.317 +            case '/': {
 174.318 +                // Look for /,//, /=, //=
 174.319 +                int peek = input.read();
 174.320 +                if (peek == '=') {
 174.321 +                    // No need to back up, include it
 174.322 +                } else if (peek == '/') {
 174.323 +                    peek = input.read();
 174.324 +                    if (peek != '=') {
 174.325 +                        input.backup(1);
 174.326 +                    }
 174.327 +                } else {
 174.328 +                    input.backup(1);
 174.329 +                }
 174.330 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 174.331 +            }
 174.332 +            case '%': { // Look for %,   %=
 174.333 +                if (input.read() != '=') {
 174.334 +                    input.backup(1);
 174.335 +                }
 174.336 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 174.337 +            }
 174.338 +            case '<': {
 174.339 +                // Look for <, <<, <=, <>, <<=
 174.340 +                int peek = input.read();
 174.341 +                if (peek == '=') {
 174.342 +                    // No need to back up, include it
 174.343 +                } else if (peek == '<') {
 174.344 +                    peek = input.read();
 174.345 +                    if (peek != '=') {
 174.346 +                        input.backup(1);
 174.347 +                    }
 174.348 +                } else if (peek != '>') {
 174.349 +                    input.backup(1);
 174.350 +                }
 174.351 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 174.352 +            }
 174.353 +            case '>': {
 174.354 +                // Look for >, >>, >=, >>=
 174.355 +                int peek = input.read();
 174.356 +                if (peek == '=') {
 174.357 +                    // No need to back up, include it
 174.358 +                } else if (peek == '>') {
 174.359 +                    peek = input.read();
 174.360 +                    if (peek != '=') {
 174.361 +                        input.backup(1);
 174.362 +                    }
 174.363 +                } else {
 174.364 +                    input.backup(1);
 174.365 +                }
 174.366 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 174.367 +            }
 174.368 +            case '&': { // Look for &,&=
 174.369 +                if (input.read() != '=') {
 174.370 +                    input.backup(1);
 174.371 +                }
 174.372 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 174.373 +            }
 174.374 +            case '|': { // Look for |, |=
 174.375 +                if (input.read() != '=') {
 174.376 +                    input.backup(1);
 174.377 +                }
 174.378 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 174.379 +            }
 174.380 +            case '^': { // ^,^=
 174.381 +                if (input.read() != '=') {
 174.382 +                    input.backup(1);
 174.383 +                }
 174.384 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 174.385 +            }
 174.386 +            case '=': {
 174.387 +                // Look for =,==
 174.388 +                if (input.read() != '=') {
 174.389 +                    input.backup(1);
 174.390 +                }
 174.391 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 174.392 +            }
 174.393 +            case '!': {
 174.394 +                // Look for !=
 174.395 +                if (input.read() != '=') {
 174.396 +                    input.backup(1);
 174.397 +                }
 174.398 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 174.399 +            }
 174.400 +            case '~':
 174.401 +            case '`':
 174.402 +            case ';':
 174.403 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 174.404 +
 174.405 +            case ':':
 174.406 +                assert input.readLength() == 1;
 174.407 +                return createToken(PythonTokenId.COLON, 1);
 174.408 +            case '(':
 174.409 +                assert input.readLength() == 1;
 174.410 +                return createToken(PythonTokenId.LPAREN, 1);
 174.411 +            case ')':
 174.412 +                assert input.readLength() == 1;
 174.413 +                return createToken(PythonTokenId.RPAREN, 1);
 174.414 +            case '[':
 174.415 +                assert input.readLength() == 1;
 174.416 +                return createToken(PythonTokenId.LBRACKET, 1);
 174.417 +            case ']':
 174.418 +                assert input.readLength() == 1;
 174.419 +                return createToken(PythonTokenId.RBRACKET, 1);
 174.420 +            case '{':
 174.421 +                assert input.readLength() == 1;
 174.422 +                return createToken(PythonTokenId.LBRACE, 1);
 174.423 +            case '}':
 174.424 +                assert input.readLength() == 1;
 174.425 +                return createToken(PythonTokenId.RBRACE, 1);
 174.426 +            case ',':
 174.427 +                assert input.readLength() == 1;
 174.428 +                return createToken(PythonTokenId.COMMA, 1);
 174.429 +            case '\\':
 174.430 +                assert input.readLength() == 1;
 174.431 +                return createToken(PythonTokenId.ESC, 1);
 174.432 +
 174.433 +            case '$':
 174.434 +            case '?':
 174.435 +                assert input.readLength() == 1;
 174.436 +                return createToken(PythonTokenId.ERROR, 1);
 174.437 +
 174.438 +            // String?
 174.439 +            case '\'':
 174.440 +            case '"': {
 174.441 +                int peek = input.read();
 174.442 +                if (peek != ch) {
 174.443 +                    input.backup(1);
 174.444 +                    assert input.readLength() == 1;
 174.445 +                    state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
 174.446 +                    return createToken(PythonTokenId.STRING_BEGIN, 1);
 174.447 +                }
 174.448 +                // We've seen two quotes... it's either an empty string,
 174.449 +                // or the beginning of a longstring
 174.450 +                int peek2 = input.read();
 174.451 +                if (peek2 == peek) {
 174.452 +                    // It's a longstring!
 174.453 +                    assert input.readLength() == 3;
 174.454 +                    state = (ch == '"') ? State.BEGIN_LONGSTRING_DOUBLE : State.BEGIN_LONGSTRING_SINGLE;
 174.455 +                    return createToken(PythonTokenId.STRING_BEGIN, 3);
 174.456 +                } else {
 174.457 +                    input.backup(2);
 174.458 +                    assert input.readLength() == 1;
 174.459 +                    state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
 174.460 +                    return createToken(PythonTokenId.STRING_BEGIN, 1);
 174.461 +                }
 174.462 +            }
 174.463 +            case '@': { // Decorator
 174.464 +                // Identifier or keyword?
 174.465 +                ch = input.read();
 174.466 +                if (Character.isJavaIdentifierStart(ch)) {
 174.467 +                    while (ch != EOF && Character.isJavaIdentifierPart(ch) && ch != '$') {
 174.468 +                        ch = input.read();
 174.469 +                    }
 174.470 +                    input.backup(1);
 174.471 +
 174.472 +                    return createToken(PythonTokenId.DECORATOR, input.readLength());
 174.473 +                }
 174.474 +                input.backup(1); // Remove the peeked char
 174.475 +
 174.476 +                assert input.readLength() == 1;
 174.477 +                return createToken(PythonTokenId.DECORATOR, 1);
 174.478 +            }
 174.479 +
 174.480 +            case 'r':
 174.481 +            case 'R':
 174.482 +            case 'u':
 174.483 +            case 'U': {
 174.484 +                // Digest the "u" and the "r" and position the input
 174.485 +                // before the following ' or "
 174.486 +                boolean isStringPrefix = false;
 174.487 +                int peek = input.read();
 174.488 +                if (ch == 'r' || ch == 'R') {
 174.489 +                    if (peek == '\'' || peek == '"') {
 174.490 +                        isStringPrefix = true;
 174.491 +                    }
 174.492 +                    input.backup(1);
 174.493 +                } else {
 174.494 +                    assert ch == 'u' || ch == 'U';
 174.495 +                    if (peek == 'r' || peek == 'R') {
 174.496 +                        int peek2 = input.read();
 174.497 +                        if (peek2 == '\'' || peek2 == '"') {
 174.498 +                            isStringPrefix = true;
 174.499 +                        }
 174.500 +                        input.backup(1);
 174.501 +                    } else if (peek == '\'' || peek == '"') {
 174.502 +                        isStringPrefix = true;
 174.503 +                        input.backup(1);
 174.504 +                    }
 174.505 +                    if (!isStringPrefix) {
 174.506 +                        input.backup(1);
 174.507 +                    }
 174.508 +                }
 174.509 +                if (isStringPrefix) {
 174.510 +                    ch = input.read();
 174.511 +                    assert ch == '\'' || ch == '"';
 174.512 +
 174.513 +                    peek = input.read();
 174.514 +                    if (peek != ch) {
 174.515 +                        input.backup(1);
 174.516 +                        state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
 174.517 +                        return createToken(PythonTokenId.STRING_BEGIN, input.readLength());
 174.518 +                    }
 174.519 +                    // We've seen two quotes... it's either an empty string,
 174.520 +                    // or the beginning of a longstring
 174.521 +                    int peek2 = input.read();
 174.522 +                    if (peek2 == peek) {
 174.523 +                        // It's a longstring!
 174.524 +                        state = (ch == '"') ? State.BEGIN_LONGSTRING_DOUBLE : State.BEGIN_LONGSTRING_SINGLE;
 174.525 +                        return createToken(PythonTokenId.STRING_BEGIN, input.readLength());
 174.526 +                    } else {
 174.527 +                        input.backup(2);
 174.528 +                        state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
 174.529 +                        return createToken(PythonTokenId.STRING_BEGIN, input.readLength());
 174.530 +                    }
 174.531 +                }// else: FALLTHROUGH!!! The "u" or "r" is probably an identifier prefix!!
 174.532 +            }
 174.533 +            // Fallthrough...
 174.534 +
 174.535 +            default: {
 174.536 +                // Identifier or keyword?
 174.537 +                if (Character.isJavaIdentifierStart(ch)) {
 174.538 +                    while (ch != EOF && Character.isJavaIdentifierPart(ch) && ch != '$') {
 174.539 +                        ch = input.read();
 174.540 +                    }
 174.541 +                    input.backup(1);
 174.542 +
 174.543 +                    // See if it's a keyword
 174.544 +                    PythonTokenId pid = getKeywordToken(input.readText());
 174.545 +                    if (pid != null) {
 174.546 +                        return createToken(pid, input.readLength());
 174.547 +                    } else {
 174.548 +                        return createToken(PythonTokenId.IDENTIFIER, input.readLength());
 174.549 +                    }
 174.550 +                }
 174.551 +
 174.552 +                assert input.readLength() == 1;
 174.553 +                return createToken(PythonTokenId.ANY_OPERATOR, 1);
 174.554 +            }
 174.555 +            }
 174.556 +        }
 174.557 +
 174.558 +        case BEGIN_LONGSTRING_SINGLE:
 174.559 +        case BEGIN_LONGSTRING_DOUBLE: {
 174.560 +            // In a long string. Look for the end.
 174.561 +            int ch = input.read();
 174.562 +            if (ch == EOF) {
 174.563 +                return null;
 174.564 +            }
 174.565 +            int term = (state == State.BEGIN_LONGSTRING_DOUBLE) ? '"' : '\'';
 174.566 +            while (ch != EOF) {
 174.567 +                if (ch == '\\') {
 174.568 +                    // It's an escape - read escaped char
 174.569 +                    input.read();
 174.570 +                } else if (ch == term) {
 174.571 +                    int peek = input.read();
 174.572 +                    if (peek == term) {
 174.573 +                        int peek2 = input.read();
 174.574 +                        if (peek2 == term) {
 174.575 +                            // Found the end
 174.576 +                            if (input.readLength() == 3) {
 174.577 +                                // Empty string - go straight to closed state
 174.578 +                                state = State.INIT;
 174.579 +                                return createToken(PythonTokenId.STRING_END, input.readLength());
 174.580 +                            }
 174.581 +                            input.backup(3);
 174.582 +                            if (state == State.BEGIN_LONGSTRING_DOUBLE) {
 174.583 +                                state = State.END_LONGSTRING_DOUBLE;
 174.584 +                            } else {
 174.585 +                                assert state == State.BEGIN_LONGSTRING_SINGLE;
 174.586 +                                state = State.END_LONGSTRING_SINGLE;
 174.587 +                            }
 174.588 +                            return createToken(PythonTokenId.STRING_LITERAL, input.readLength());
 174.589 +                        }
 174.590 +                        input.backup(1);
 174.591 +                    }
 174.592 +                    input.backup(1);
 174.593 +                }
 174.594 +                ch = input.read();
 174.595 +            }
 174.596 +            // Literal not terminated
 174.597 +            state = State.INIT;
 174.598 +            return createToken(PythonTokenId.ERROR, input.readLength());
 174.599 +        }
 174.600 +        case BEGIN_SHORTSTRING_SINGLE:
 174.601 +        case BEGIN_SHORTSTRING_DOUBLE: {
 174.602 +            // In a short string. Look for the end.
 174.603 +            int ch = input.read();
 174.604 +            if (ch == EOF) {
 174.605 +                return null;
 174.606 +            }
 174.607 +            int term = (state == State.BEGIN_SHORTSTRING_DOUBLE) ? '"' : '\'';
 174.608 +            while (ch != EOF) {
 174.609 +                if (ch == '\\') {
 174.610 +                    // It's an escape - read escaped char
 174.611 +                    input.read();
 174.612 +                } else if (ch == '\n') {
 174.613 +                    // Literal not terminated
 174.614 +                    state = State.INIT;
 174.615 +                    return createToken(PythonTokenId.ERROR, input.readLength());
 174.616 +                } else if (ch == term) {
 174.617 +                    if (input.readLength() == 1) {
 174.618 +                        // It's an empty string! Skip straight to the end state
 174.619 +                        state = State.INIT;
 174.620 +                        return createToken(PythonTokenId.STRING_END, input.readLength());
 174.621 +                    }
 174.622 +                    input.backup(1);
 174.623 +                    if (state == State.BEGIN_SHORTSTRING_DOUBLE) {
 174.624 +                        state = State.END_SHORTSTRING_DOUBLE;
 174.625 +                    } else {
 174.626 +                        assert state == State.BEGIN_SHORTSTRING_SINGLE;
 174.627 +                        state = State.END_SHORTSTRING_SINGLE;
 174.628 +                    }
 174.629 +                    return createToken(PythonTokenId.STRING_LITERAL, input.readLength());
 174.630 +                }
 174.631 +                ch = input.read();
 174.632 +            }
 174.633 +            // Literal not terminated
 174.634 +            state = State.INIT;
 174.635 +            return createToken(PythonTokenId.ERROR, input.readLength());
 174.636 +        }
 174.637 +
 174.638 +        case END_LONGSTRING_SINGLE:
 174.639 +        case END_LONGSTRING_DOUBLE: {
 174.640 +            // In a long string. Look for the end.
 174.641 +            int ch = input.read();
 174.642 +            if (ch == EOF) {
 174.643 +                return null;
 174.644 +            }
 174.645 +            int term = (state == State.END_LONGSTRING_DOUBLE) ? '"' : '\'';
 174.646 +            while (ch != EOF) {
 174.647 +                if (ch == term) {
 174.648 +                    int peek = input.read();
 174.649 +                    if (peek == term) {
 174.650 +                        int peek2 = input.read();
 174.651 +                        if (peek2 == term) {
 174.652 +                            // Found the end
 174.653 +                            state = State.INIT;
 174.654 +                            return createToken(PythonTokenId.STRING_END, input.readLength());
 174.655 +                        }
 174.656 +                        input.backup(1);
 174.657 +                    }
 174.658 +                    input.backup(1);
 174.659 +                }
 174.660 +                ch = input.read();
 174.661 +            }
 174.662 +            // Literal not terminated
 174.663 +            state = State.INIT;
 174.664 +            return createToken(PythonTokenId.ERROR, input.readLength());
 174.665 +        }
 174.666 +        case END_SHORTSTRING_SINGLE:
 174.667 +        case END_SHORTSTRING_DOUBLE: {
 174.668 +            // In a short string. Look for the end.
 174.669 +            int ch = input.read();
 174.670 +            if (ch == EOF) {
 174.671 +                return null;
 174.672 +            }
 174.673 +            int term = (state == State.END_SHORTSTRING_DOUBLE) ? '"' : '\'';
 174.674 +            if (ch == term) {
 174.675 +                state = State.INIT;
 174.676 +                return createToken(PythonTokenId.STRING_END, input.readLength());
 174.677 +            }
 174.678 +            state = State.INIT;
 174.679 +            return createToken(PythonTokenId.ERROR, input.readLength());
 174.680 +        }
 174.681 +
 174.682 +        default:
 174.683 +            assert false : state;
 174.684 +        }
 174.685 +
 174.686 +        return null;
 174.687 +    }
 174.688 +
 174.689 +    @Override
 174.690 +    public void release() {
 174.691 +    }
 174.692 +
 174.693 +    private PythonTokenId getKeywordToken(CharSequence s) {
 174.694 +        int length = s.length();
 174.695 +        if (length < 2) {
 174.696 +            return null;
 174.697 +        }
 174.698 +
 174.699 +        if (s.toString().endsWith("Error")) {
 174.700 +            return PythonTokenId.ERROR;
 174.701 +        }
 174.702 +
 174.703 +        char c1 = s.charAt(0);
 174.704 +        char c2 = s.charAt(1);
 174.705 +
 174.706 +        switch (c1) {
 174.707 +        case 'a': // and, as, assert, async, await
 174.708 +            switch (c2) {
 174.709 +            case 'n': // and
 174.710 +                if (TokenUtilities.textEquals(s, "and")) { // NOI18N
 174.711 +                    return PythonTokenId.ANY_KEYWORD;
 174.712 +                }
 174.713 +                break;
 174.714 +            case 's':  // as, assert, async
 174.715 +                if (length == 2) { // as
 174.716 +                    return PythonTokenId.ANY_KEYWORD;
 174.717 +                }
 174.718 +                if (length == 6 && TokenUtilities.textEquals(s, "assert")) { // NOI18N
 174.719 +                    return PythonTokenId.ANY_KEYWORD;
 174.720 +                }
 174.721 +                if (length == 5 && TokenUtilities.textEquals(s, "async")) { // NOI18N
 174.722 +                    return PythonTokenId.ANY_KEYWORD;
 174.723 +                }
 174.724 +                break;
 174.725 +            case 'w': // await
 174.726 +                if (length == 5 && TokenUtilities.textEquals(s, "await")) { // NOI18N
 174.727 +                    return PythonTokenId.ANY_KEYWORD;
 174.728 +                }
 174.729 +            }
 174.730 +            break;
 174.731 +        case 'b': // break, bytes
 174.732 +            if (length == 5 && TokenUtilities.textEquals(s, "break")) { // NOI18N
 174.733 +                return PythonTokenId.ANY_KEYWORD;
 174.734 +            } else if (length == 5 && TokenUtilities.textEquals(s, "bytes")) { // NOI18N
 174.735 +                return PythonTokenId.STD_SYMBOLS;
 174.736 +            }
 174.737 +            break;
 174.738 +        case 'c': // class, continue
 174.739 +            switch (c2) {
 174.740 +            case 'l': // class
 174.741 +                if (length == 5 && TokenUtilities.textEquals(s, "class")) { // NOI18N
 174.742 +                    return PythonTokenId.CLASS;
 174.743 +                }
 174.744 +                break;
 174.745 +            case 'o':  // continue
 174.746 +                if (length == 8 && TokenUtilities.textEquals(s, "continue")) { // NOI18N
 174.747 +                    return PythonTokenId.ANY_KEYWORD;
 174.748 +                }
 174.749 +                break;
 174.750 +            }
 174.751 +            break;
 174.752 +        case 'd': // def, del
 174.753 +            if (c2 == 'e' && length == 3) { // def, del
 174.754 +                char c3 = s.charAt(2);
 174.755 +                if (c3 == 'f') { // def
 174.756 +                    return PythonTokenId.DEF;
 174.757 +                } else if (c3 == 'l') { // del
 174.758 +                    return PythonTokenId.ANY_KEYWORD;
 174.759 +                }
 174.760 +            }
 174.761 +            break;
 174.762 +        case 'e': // elif, else, except, exec
 174.763 +            switch (c2) {
 174.764 +            case 'l': // elif, else
 174.765 +                if (length == 4) {
 174.766 +                    if (TokenUtilities.textEquals(s, "elif")) { // NOI18N
 174.767 +                        return PythonTokenId.ELIF;
 174.768 +                    }
 174.769 +                    if (TokenUtilities.textEquals(s, "else")) { // NOI18N
 174.770 +                        return PythonTokenId.ELSE;
 174.771 +                    }
 174.772 +                }
 174.773 +                break;
 174.774 +            case 'n': // enumerate
 174.775 +                if (length == 9 && TokenUtilities.textEquals(s, "enumerate")) { // NOI18N
 174.776 +                    return PythonTokenId.STD_SYMBOLS;
 174.777 +                }
 174.778 +            case 'x': // except, exec
 174.779 +                if (length == 4 && TokenUtilities.textEquals(s, "exec")) { // NOI18N
 174.780 +                    return PythonTokenId.ANY_KEYWORD;
 174.781 +                }
 174.782 +                if (length == 6 && TokenUtilities.textEquals(s, "except")) { // NOI18N
 174.783 +                    return PythonTokenId.EXCEPT;
 174.784 +                }
 174.785 +                break;
 174.786 +            }
 174.787 +            break;
 174.788 +        case 'f': // finally,for,from
 174.789 +            switch (c2) {
 174.790 +            case 'i': // finally
 174.791 +                if (length == 7 && TokenUtilities.textEquals(s, "finally")) { // NOI18N
 174.792 +                    return PythonTokenId.FINALLY;
 174.793 +                }
 174.794 +                break;
 174.795 +            case 'o': // for
 174.796 +                if (length == 3 && TokenUtilities.textEquals(s, "for")) { // NOI18N
 174.797 +                    return PythonTokenId.ANY_KEYWORD;
 174.798 +                }
 174.799 +                break;
 174.800 +            case 'r': // from
 174.801 +                if (length == 4 && TokenUtilities.textEquals(s, "from")) { // NOI18N
 174.802 +                    return PythonTokenId.FROM;
 174.803 +                }
 174.804 +                break;
 174.805 +            case 'l':
 174.806 +                if (length == 5 && TokenUtilities.textEquals(s, "float")) {
 174.807 +                    return PythonTokenId.STD_SYMBOLS;
 174.808 +                }
 174.809 +            }
 174.810 +            break;
 174.811 +        case 'g': // global
 174.812 +            if (length == 6 && TokenUtilities.textEquals(s, "global")) { // NOI18N
 174.813 +                return PythonTokenId.ANY_KEYWORD;
 174.814 +            }
 174.815 +            break;
 174.816 +        case 'i': // if,import,in,is, int
 174.817 +            if (length == 2) {
 174.818 +                switch (c2) {
 174.819 +                case 'f': // if
 174.820 +                    return PythonTokenId.IF;
 174.821 +                case 'n': // in
 174.822 +                    if (length == 2 && TokenUtilities.textEquals(s, "in")) { //NOI18N
 174.823 +                        return PythonTokenId.ANY_KEYWORD;
 174.824 +                    }
 174.825 +                case 's': // is
 174.826 +                    return PythonTokenId.ANY_KEYWORD;
 174.827 +                }
 174.828 +            } else if (c2 == 'm' && length == 6 && TokenUtilities.textEquals(s, "import")) { // NOI18N
 174.829 +                // import
 174.830 +                return PythonTokenId.IMPORT;
 174.831 +            } else if (length == 3 && TokenUtilities.textEquals(s, "int")) { // NOI18N
 174.832 +                return PythonTokenId.STD_SYMBOLS;
 174.833 +            } else if (length == 10 && TokenUtilities.textEquals(s, "isinstance")) { // NOI18N
 174.834 +                return PythonTokenId.STD_SYMBOLS;
 174.835 +            }
 174.836 +            break;
 174.837 +        case 'l': // lambda, len, list
 174.838 +            if (length == 6 && TokenUtilities.textEquals(s, "lambda")) { // NOI18N
 174.839 +                return PythonTokenId.ANY_KEYWORD;
 174.840 +            } else if (length == 3 && TokenUtilities.textEquals(s, "len")) { // NOI18N
 174.841 +                return PythonTokenId.STD_SYMBOLS;
 174.842 +            } else if (length == 4 && TokenUtilities.textEquals(s, "list")) { // NOI18N
 174.843 +                return PythonTokenId.STD_SYMBOLS;
 174.844 +            }
 174.845 +            break;
 174.846 +        case 'n': // not
 174.847 +            if (length == 3 && TokenUtilities.textEquals(s, "not")) { // NOI18N
 174.848 +                return PythonTokenId.ANY_KEYWORD;
 174.849 +            }
 174.850 +            break;
 174.851 +        case 'o': // or, object
 174.852 +            if (length == 2 && TokenUtilities.textEquals(s, "or")) { // NOI18N
 174.853 +                return PythonTokenId.ANY_KEYWORD;
 174.854 +            } else if (length == 6 && TokenUtilities.textEquals(s, "object")) { // NOI18N
 174.855 +                return PythonTokenId.STD_SYMBOLS;
 174.856 +            }
 174.857 +            break;
 174.858 +        case 'p': // pass,print
 174.859 +            if (c2 == 'a') { // pass
 174.860 +                if (length == 4 && TokenUtilities.textEquals(s, "pass")) { // NOI18N
 174.861 +                    return PythonTokenId.PASS;
 174.862 +                }
 174.863 +            } else if (c2 == 'r') { // print
 174.864 +                if (length == 5 && TokenUtilities.textEquals(s, "print")) { // NOI18N
 174.865 +                    return PythonTokenId.ANY_KEYWORD;
 174.866 +                }
 174.867 +            }
 174.868 +            break;
 174.869 +        case 'r': // raise,return
 174.870 +            if (c2 == 'a') { // raise
 174.871 +                if (length == 5 && TokenUtilities.textEquals(s, "raise")) { // NOI18N
 174.872 +                    return PythonTokenId.RAISE;
 174.873 +                }
 174.874 +            } else if (c2 == 'e') { // return
 174.875 +                if (length == 6 && TokenUtilities.textEquals(s, "return")) { // NOI18N
 174.876 +                    return PythonTokenId.RETURN;
 174.877 +                }
 174.878 +            }
 174.879 +            break;
 174.880 +        case 's': // self, set, str, super
 174.881 +            if (length == 4 && TokenUtilities.textEquals(s, "self")) { // NOI18N
 174.882 +                return PythonTokenId.ANY_KEYWORD;
 174.883 +            } else if (length == 3 && TokenUtilities.textEquals(s, "set")) { // NOI18N
 174.884 +                return PythonTokenId.STD_SYMBOLS;
 174.885 +            } else if (length == 3 && TokenUtilities.textEquals(s, "str")) { // NOI18N
 174.886 +                return PythonTokenId.STD_SYMBOLS;
 174.887 +            } else if (length == 5 && TokenUtilities.textEquals(s, "super")) { // NOI18N
 174.888 +                return PythonTokenId.ANY_KEYWORD;
 174.889 +            }
 174.890 +        case 't': // try, tuple, type
 174.891 +            if (length == 3 && TokenUtilities.textEquals(s, "try")) { // NOI18N
 174.892 +                return PythonTokenId.TRY;
 174.893 +            } else if (length == 5 && TokenUtilities.textEquals(s, "tuple")) { // NOI18N
 174.894 +                return PythonTokenId.STD_SYMBOLS;
 174.895 +            } else if (length == 4 && TokenUtilities.textEquals(s, "type")) { // NOI18N
 174.896 +                return PythonTokenId.STD_SYMBOLS;
 174.897 +            }
 174.898 +            break;
 174.899 +        case 'w': // while,with
 174.900 +            if (c2 == 'h') { // while
 174.901 +                if (length == 5 && TokenUtilities.textEquals(s, "while")) { // NOI18N
 174.902 +                    return PythonTokenId.ANY_KEYWORD;
 174.903 +                }
 174.904 +            } else if (c2 == 'i') { // with
 174.905 +                if (length == 4 && TokenUtilities.textEquals(s, "with")) { // NOI18N
 174.906 +                    return PythonTokenId.ANY_KEYWORD;
 174.907 +                }
 174.908 +            }
 174.909 +            break;
 174.910 +        case 'y': // yield
 174.911 +            if (length == 5 && TokenUtilities.textEquals(s, "yield")) { // NOI18N
 174.912 +                return PythonTokenId.ANY_KEYWORD;
 174.913 +            }
 174.914 +            break;
 174.915 +        case 'F': // False
 174.916 +            if (length == 5 && TokenUtilities.textEquals(s, "False")) { // NOI18N
 174.917 +                return PythonTokenId.FALSE;
 174.918 +            }
 174.919 +        case 'N': // None
 174.920 +            if (length == 4 && TokenUtilities.textEquals(s, "None")) { // NOI18N
 174.921 +                return PythonTokenId.NONE;
 174.922 +            }
 174.923 +        case 'T': // True
 174.924 +            if (length == 4 && TokenUtilities.textEquals(s, "True")) { // NOI18N
 174.925 +                return PythonTokenId.TRUE;
 174.926 +            }
 174.927 +        }
 174.928 +
 174.929 +        return null;
 174.930 +    }
 174.931 +}
   175.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   175.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/PythonLexerUtils.java	Sun Sep 13 11:47:42 2015 +0200
   175.3 @@ -0,0 +1,558 @@
   175.4 +/*
   175.5 + * To change this template, choose Tools | Templates
   175.6 + * and open the template in the editor.
   175.7 + */
   175.8 +package org.netbeans.modules.python.source.lexer;
   175.9 +
  175.10 +import java.util.Arrays;
  175.11 +import java.util.List;
  175.12 +import java.util.regex.Matcher;
  175.13 +import java.util.regex.Pattern;
  175.14 +import javax.swing.text.BadLocationException;
  175.15 +import javax.swing.text.Document;
  175.16 +import org.netbeans.api.lexer.Token;
  175.17 +import org.netbeans.api.lexer.TokenHierarchy;
  175.18 +import org.netbeans.api.lexer.TokenId;
  175.19 +import org.netbeans.api.lexer.TokenSequence;
  175.20 +import org.netbeans.editor.BaseDocument;
  175.21 +import org.netbeans.editor.Utilities;
  175.22 +import org.netbeans.modules.csl.api.OffsetRange;
  175.23 +import org.netbeans.modules.python.source.PythonParserResult;
  175.24 +import org.openide.filesystems.FileUtil;
  175.25 +import org.openide.loaders.DataObject;
  175.26 +import org.openide.util.Exceptions;
  175.27 +import org.python.antlr.PythonTree;
  175.28 +
  175.29 +/**
  175.30 + * Utility functions around the Python lexer
  175.31 + * 
  175.32 + * @author Tor Norbye
  175.33 + */
  175.34 +public class PythonLexerUtils {
  175.35 +    /**
  175.36 +     * Try to produce a more accurate location for the given name in the given import statement, located
  175.37 +     * at the lexRange provided
  175.38 +     */
  175.39 +    public static OffsetRange getImportNameOffset(BaseDocument doc, OffsetRange lexRange, PythonTree node, String name) {
  175.40 +        int docLength = doc.getLength();
  175.41 +        int start = Math.min(docLength, lexRange.getStart());
  175.42 +        int end = Math.min(docLength, lexRange.getEnd());
  175.43 +        try {
  175.44 +            String s = doc.getText(start, end - start);
  175.45 +
  175.46 +            Pattern p = Pattern.compile(".*import\\s+\\b(" + name + ")\\b.*");
  175.47 +            Matcher m = p.matcher(s);
  175.48 +            if (m.matches()) {
  175.49 +                int offset = start + m.start(1);
  175.50 +                return new OffsetRange(offset, offset + name.length());
  175.51 +            }
  175.52 +
  175.53 +            // Lame
  175.54 +            int searchIndex = s.indexOf("import ");
  175.55 +            if (searchIndex == -1) {
  175.56 +                searchIndex = 0;
  175.57 +            } else {
  175.58 +                searchIndex += 7;
  175.59 +            }
  175.60 +            int match = s.indexOf(name, searchIndex + 7);
  175.61 +            if (match != -1) {
  175.62 +                int offset = start + match;
  175.63 +                return new OffsetRange(offset, offset + name.length());
  175.64 +            }
  175.65 +
  175.66 +        // Give up - use the whole range
  175.67 +        } catch (BadLocationException ex) {
  175.68 +            Exceptions.printStackTrace(ex);
  175.69 +        }
  175.70 +
  175.71 +        return lexRange;
  175.72 +    }
  175.73 +
  175.74 +    /** For a possibly generated offset in an AST, return the corresponding lexing/true document offset */
  175.75 +    public static int getLexerOffset(PythonParserResult result, int astOffset) {
  175.76 +        return result.getSnapshot().getOriginalOffset(astOffset);
  175.77 +    }
  175.78 +
  175.79 +    public static OffsetRange getLexerOffsets(PythonParserResult result, OffsetRange astRange) {
  175.80 +        if (result != null) {
  175.81 +            int rangeStart = astRange.getStart();
  175.82 +            int start = result.getSnapshot().getOriginalOffset(rangeStart);
  175.83 +            if (start == rangeStart) {
  175.84 +                return astRange;
  175.85 +            } else if (start == -1) {
  175.86 +                return OffsetRange.NONE;
  175.87 +            } else {
  175.88 +                // Assumes the translated range maintains size
  175.89 +                return new OffsetRange(start, start + astRange.getLength());
  175.90 +            }
  175.91 +        }
  175.92 +
  175.93 +        return astRange;
  175.94 +    }
  175.95 +
  175.96 +    /**
  175.97 +     * Narrow a given lexical offset range to the closest AST-relevant offsets.
  175.98 +     * This means it will pass over things like comments and whitespace.
  175.99 +     * @param doc The document containing the range
 175.100 +     * @param range The start/end lexical range we want to narrow
 175.101 +     * @return An OffsetRange where the offsets begin and end at AST-relevant tokens
 175.102 +     */
 175.103 +    public static OffsetRange narrow(BaseDocument doc, OffsetRange range, boolean skipComments) {
 175.104 +        try {
 175.105 +            doc.readLock(); // For token hiearchy use
 175.106 +            // For token hiearchy use
 175.107 +            int start = range.getStart();
 175.108 +            TokenSequence<? extends PythonTokenId> ts = getPythonSequence(doc, start);
 175.109 +            if (ts != null) {
 175.110 +                int delta = ts.move(start);
 175.111 +                while (ts.moveNext()) {
 175.112 +                    Token<? extends PythonTokenId> token = ts.token();
 175.113 +                    PythonTokenId id = token.id();
 175.114 +                    if (id != PythonTokenId.NEWLINE && (!skipComments || id != PythonTokenId.COMMENT) && id != PythonTokenId.WHITESPACE) {
 175.115 +                        if (delta != 0) {
 175.116 +                            return OffsetRange.NONE;
 175.117 +                        }
 175.118 +                        start = ts.offset();
 175.119 +                        break;
 175.120 +                    } else {
 175.121 +                        delta = 0;
 175.122 +                    }
 175.123 +                }
 175.124 +            }
 175.125 +            int end = range.getEnd();
 175.126 +            ts = getPositionedSequence(doc, end);
 175.127 +            if (ts != null) {
 175.128 +                int delta = ts.move(end);
 175.129 +                while (delta > 0 ? ts.moveNext() : ts.movePrevious()) {
 175.130 +                    Token<? extends PythonTokenId> token = ts.token();
 175.131 +                    PythonTokenId id = token.id();
 175.132 +                    if (id != PythonTokenId.NEWLINE && (!skipComments || id != PythonTokenId.COMMENT) && id != PythonTokenId.WHITESPACE) {
 175.133 +                        if (delta != 0) {
 175.134 +                            return OffsetRange.NONE;
 175.135 +                        }
 175.136 +                        end = ts.offset() + token.length();
 175.137 +                        break;
 175.138 +                    } else {
 175.139 +                        delta = 0;
 175.140 +                    }
 175.141 +                }
 175.142 +            }
 175.143 +
 175.144 +            if (end < start) {
 175.145 +                return OffsetRange.NONE;
 175.146 +            }
 175.147 +
 175.148 +            return new OffsetRange(start, end);
 175.149 +        } finally {
 175.150 +            doc.readUnlock();
 175.151 +        }
 175.152 +    }
 175.153 +
 175.154 +    /** Find the ruby token sequence (in case it's embedded in something else at the top level */
 175.155 +    @SuppressWarnings("unchecked")
 175.156 +    public static TokenSequence<? extends PythonTokenId> getPythonSequence(BaseDocument doc, int offset) {
 175.157 +        TokenHierarchy<Document> th = TokenHierarchy.get((Document)doc);
 175.158 +        return getPythonSequence(th, offset);
 175.159 +    }
 175.160 +
 175.161 +    @SuppressWarnings("unchecked")
 175.162 +    public static TokenSequence<? extends PythonTokenId> getPythonSequence(TokenHierarchy<Document> th, int offset) {
 175.163 +        TokenSequence<? extends PythonTokenId> ts = th.tokenSequence(PythonTokenId.language());
 175.164 +
 175.165 +        if (ts == null) {
 175.166 +            // Possibly an embedding scenario such as an RHTML file
 175.167 +            // First try with backward bias true
 175.168 +            List<TokenSequence<?>> list = th.embeddedTokenSequences(offset, true);
 175.169 +
 175.170 +            for (TokenSequence t : list) {
 175.171 +                if (t.language() == PythonTokenId.language()) {
 175.172 +                    ts = t;
 175.173 +
 175.174 +                    break;
 175.175 +                }
 175.176 +            }
 175.177 +
 175.178 +            if (ts == null) {
 175.179 +                list = th.embeddedTokenSequences(offset, false);
 175.180 +
 175.181 +                for (TokenSequence t : list) {
 175.182 +                    if (t.language() == PythonTokenId.language()) {
 175.183 +                        ts = t;
 175.184 +
 175.185 +                        break;
 175.186 +                    }
 175.187 +                }
 175.188 +            }
 175.189 +        }
 175.190 +
 175.191 +        return ts;
 175.192 +    }
 175.193 +
 175.194 +    public static TokenSequence<? extends PythonTokenId> getPositionedSequence(BaseDocument doc, int offset) {
 175.195 +        return getPositionedSequence(doc, offset, true);
 175.196 +    }
 175.197 +
 175.198 +    public static TokenSequence<? extends PythonTokenId> getPositionedSequence(BaseDocument doc, int offset, boolean lookBack) {
 175.199 +        TokenSequence<? extends PythonTokenId> ts = getPythonSequence(doc, offset);
 175.200 +
 175.201 +        if (ts != null) {
 175.202 +            try {
 175.203 +                ts.move(offset);
 175.204 +            } catch (AssertionError e) {
 175.205 +                DataObject dobj = (DataObject)doc.getProperty(Document.StreamDescriptionProperty);
 175.206 +
 175.207 +                if (dobj != null) {
 175.208 +                    Exceptions.attachMessage(e, FileUtil.getFileDisplayName(dobj.getPrimaryFile()));
 175.209 +                }
 175.210 +
 175.211 +                throw e;
 175.212 +            }
 175.213 +
 175.214 +            if (!lookBack && !ts.moveNext()) {
 175.215 +                return null;
 175.216 +            } else if (lookBack && !ts.moveNext() && !ts.movePrevious()) {
 175.217 +                return null;
 175.218 +            }
 175.219 +
 175.220 +            /* TODO - allow Python inside strings
 175.221 +            if (ts.token().id() == PythonTokenId.STRING_LITERAL) {
 175.222 +            TokenSequence<? extends PythonStringTokenId> ets = ts.embedded(PythonStringTokenId.language());
 175.223 +            if (ets != null) {
 175.224 +            ets.move(offset);
 175.225 +            if ((!lookBack && ets.moveNext()) || (lookBack && ets.movePrevious())) {
 175.226 +            TokenSequence<?extends PythonTokenId> epts = ets.embedded(PythonTokenId.language());
 175.227 +            if (epts != null) {
 175.228 +            epts.move(offset);
 175.229 +            if (!lookBack && !epts.moveNext()) {
 175.230 +            return null;
 175.231 +            } else if (lookBack && !epts.moveNext() && !epts.movePrevious()) {
 175.232 +            return null;
 175.233 +            }
 175.234 +            return epts;
 175.235 +            }
 175.236 +            }
 175.237 +            }
 175.238 +            }
 175.239 +             */
 175.240 +
 175.241 +            return ts;
 175.242 +        }
 175.243 +
 175.244 +        return null;
 175.245 +    }
 175.246 +
 175.247 +    public static Token<? extends PythonTokenId> getToken(BaseDocument doc, int offset) {
 175.248 +        TokenSequence<? extends PythonTokenId> ts = getPositionedSequence(doc, offset);
 175.249 +
 175.250 +        if (ts != null) {
 175.251 +            return ts.token();
 175.252 +        }
 175.253 +
 175.254 +        return null;
 175.255 +    }
 175.256 +
 175.257 +    public static char getTokenChar(BaseDocument doc, int offset) {
 175.258 +        Token<? extends PythonTokenId> token = getToken(doc, offset);
 175.259 +
 175.260 +        if (token != null) {
 175.261 +            String text = token.text().toString();
 175.262 +
 175.263 +            if (text.length() > 0) { // Usually true, but I could have gotten EOF right?
 175.264 +
 175.265 +                return text.charAt(0);
 175.266 +            }
 175.267 +        }
 175.268 +
 175.269 +        return 0;
 175.270 +    }
 175.271 +
 175.272 +    public static Token<? extends PythonTokenId> findNextNonWsNonComment(TokenSequence<? extends PythonTokenId> ts) {
 175.273 +        return findNext(ts, Arrays.asList(PythonTokenId.WHITESPACE, PythonTokenId.NEWLINE, PythonTokenId.COMMENT));
 175.274 +    }
 175.275 +
 175.276 +    public static Token<? extends PythonTokenId> findPreviousNonWsNonComment(TokenSequence<? extends PythonTokenId> ts) {
 175.277 +        return findPrevious(ts, Arrays.asList(PythonTokenId.WHITESPACE, PythonTokenId.NEWLINE, PythonTokenId.COMMENT));
 175.278 +    }
 175.279 +
 175.280 +    public static Token<? extends PythonTokenId> findNext(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> ignores) {
 175.281 +        if (ignores.contains(ts.token().id())) {
 175.282 +            while (ts.moveNext() && ignores.contains(ts.token().id())) {
 175.283 +            }
 175.284 +        }
 175.285 +        return ts.token();
 175.286 +    }
 175.287 +
 175.288 +    public static Token<? extends PythonTokenId> findNextIncluding(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> includes) {
 175.289 +        while (ts.moveNext() && !includes.contains(ts.token().id())) {
 175.290 +        }
 175.291 +        return ts.token();
 175.292 +    }
 175.293 +
 175.294 +    public static Token<? extends PythonTokenId> findPreviousIncluding(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> includes) {
 175.295 +        while (ts.movePrevious() && !includes.contains(ts.token().id())) {
 175.296 +        }
 175.297 +        return ts.token();
 175.298 +    }
 175.299 +
 175.300 +    public static Token<? extends PythonTokenId> findPrevious(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> ignores) {
 175.301 +        if (ignores.contains(ts.token().id())) {
 175.302 +            while (ts.movePrevious() && ignores.contains(ts.token().id())) {
 175.303 +            }
 175.304 +        }
 175.305 +        return ts.token();
 175.306 +    }
 175.307 +
 175.308 +    static boolean skipParenthesis(TokenSequence<? extends PythonTokenId> ts) {
 175.309 +        return skipParenthesis(ts, false);
 175.310 +    }
 175.311 +
 175.312 +    /**
 175.313 +     * Tries to skip parenthesis
 175.314 +     */
 175.315 +    public static boolean skipParenthesis(TokenSequence<? extends PythonTokenId> ts, boolean back) {
 175.316 +        int balance = 0;
 175.317 +
 175.318 +        Token<? extends PythonTokenId> token = ts.token();
 175.319 +        if (token == null) {
 175.320 +            return false;
 175.321 +        }
 175.322 +
 175.323 +        TokenId id = token.id();
 175.324 +
 175.325 +        if (id == PythonTokenId.WHITESPACE || id == PythonTokenId.NEWLINE) {
 175.326 +            while ((back ? ts.movePrevious() : ts.moveNext()) && (ts.token().id() == PythonTokenId.WHITESPACE || ts.token().id() == PythonTokenId.NEWLINE)) {
 175.327 +            }
 175.328 +        }
 175.329 +
 175.330 +        // if current token is not left parenthesis
 175.331 +        if (ts.token().id() != (back ? PythonTokenId.RPAREN : PythonTokenId.LPAREN)) {
 175.332 +            return false;
 175.333 +        }
 175.334 +
 175.335 +        do {
 175.336 +            token = ts.token();
 175.337 +            id = token.id();
 175.338 +
 175.339 +            if (id == (back ? PythonTokenId.RPAREN : PythonTokenId.LPAREN)) {
 175.340 +                balance++;
 175.341 +            } else if (id == (back ? PythonTokenId.LPAREN : PythonTokenId.RPAREN)) {
 175.342 +                if (balance == 0) {
 175.343 +                    return false;
 175.344 +                } else if (balance == 1) {
 175.345 +                    //int length = ts.offset() + token.length();
 175.346 +                    if (back) {
 175.347 +                        ts.movePrevious();
 175.348 +                    } else {
 175.349 +                        ts.moveNext();
 175.350 +                    }
 175.351 +                    return true;
 175.352 +                }
 175.353 +
 175.354 +                balance--;
 175.355 +            }
 175.356 +        } while (back ? ts.movePrevious() : ts.moveNext());
 175.357 +
 175.358 +        return false;
 175.359 +    }
 175.360 +
 175.361 +    /** Search forwards in the token sequence until a token of type <code>down</code> is found */
 175.362 +    public static OffsetRange findFwd(BaseDocument doc, TokenSequence<? extends PythonTokenId> ts, TokenId up,
 175.363 +            TokenId down) {
 175.364 +        int balance = 0;
 175.365 +
 175.366 +        while (ts.moveNext()) {
 175.367 +            Token<? extends PythonTokenId> token = ts.token();
 175.368 +            TokenId id = token.id();
 175.369 +
 175.370 +            if (id == up) {
 175.371 +                balance++;
 175.372 +            } else if (id == down) {
 175.373 +                if (balance == 0) {
 175.374 +                    return new OffsetRange(ts.offset(), ts.offset() + token.length());
 175.375 +                }
 175.376 +
 175.377 +                balance--;
 175.378 +            }
 175.379 +        }
 175.380 +
 175.381 +        return OffsetRange.NONE;
 175.382 +    }
 175.383 +
 175.384 +    /** Search backwards in the token sequence until a token of type <code>up</code> is found */
 175.385 +    public static OffsetRange findBwd(BaseDocument doc, TokenSequence<? extends PythonTokenId> ts, TokenId up,
 175.386 +            TokenId down) {
 175.387 +        int balance = 0;
 175.388 +
 175.389 +        while (ts.movePrevious()) {
 175.390 +            Token<? extends PythonTokenId> token = ts.token();
 175.391 +            TokenId id = token.id();
 175.392 +
 175.393 +            if (id == up) {
 175.394 +                if (balance == 0) {
 175.395 +                    return new OffsetRange(ts.offset(), ts.offset() + token.length());
 175.396 +                }
 175.397 +
 175.398 +                balance++;
 175.399 +            } else if (id == down) {
 175.400 +                balance--;
 175.401 +            }
 175.402 +        }
 175.403 +
 175.404 +        return OffsetRange.NONE;
 175.405 +    }
 175.406 +
 175.407 +    /** Compute the balance of begin/end tokens on the line */
 175.408 +    public static int getLineBalance(BaseDocument doc, int offset, TokenId up, TokenId down) {
 175.409 +        try {
 175.410 +            int begin = Utilities.getRowStart(doc, offset);
 175.411 +            int end = Utilities.getRowEnd(doc, offset);
 175.412 +
 175.413 +            TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(doc, begin);
 175.414 +            if (ts == null) {
 175.415 +                return 0;
 175.416 +            }
 175.417 +
 175.418 +            ts.move(begin);
 175.419 +
 175.420 +            if (!ts.moveNext()) {
 175.421 +                return 0;
 175.422 +            }
 175.423 +
 175.424 +            int balance = 0;
 175.425 +
 175.426 +            do {
 175.427 +                Token<? extends PythonTokenId> token = ts.token();
 175.428 +                TokenId id = token.id();
 175.429 +
 175.430 +                if (id == up) {
 175.431 +                    balance++;
 175.432 +                } else if (id == down) {
 175.433 +                    balance--;
 175.434 +                }
 175.435 +            } while (ts.moveNext() && (ts.offset() <= end));
 175.436 +
 175.437 +            return balance;
 175.438 +        } catch (BadLocationException ble) {
 175.439 +            Exceptions.printStackTrace(ble);
 175.440 +
 175.441 +            return 0;
 175.442 +        }
 175.443 +    }
 175.444 +
 175.445 +    /**
 175.446 +     * The same as braceBalance but generalized to any pair of matching
 175.447 +     * tokens.
 175.448 +     * @param open the token that increses the count
 175.449 +     * @param close the token that decreses the count
 175.450 +     */
 175.451 +    public static int getTokenBalance(BaseDocument doc, TokenId open, TokenId close, int offset)
 175.452 +            throws BadLocationException {
 175.453 +        TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(doc, 0);
 175.454 +        if (ts == null) {
 175.455 +            return 0;
 175.456 +        }
 175.457 +
 175.458 +        // XXX Why 0? Why not offset?
 175.459 +        ts.moveIndex(0);
 175.460 +
 175.461 +        if (!ts.moveNext()) {
 175.462 +            return 0;
 175.463 +        }
 175.464 +
 175.465 +        int balance = 0;
 175.466 +
 175.467 +        do {
 175.468 +            Token t = ts.token();
 175.469 +
 175.470 +            if (t.id() == open) {
 175.471 +                balance++;
 175.472 +            } else if (t.id() == close) {
 175.473 +                balance--;
 175.474 +            }
 175.475 +        } while (ts.moveNext());
 175.476 +
 175.477 +        return balance;
 175.478 +    }
 175.479 +
 175.480 +    /**
 175.481 +     * Return true iff the line for the given offset is a JavaScript comment line.
 175.482 +     * This will return false for lines that contain comments (even when the
 175.483 +     * offset is within the comment portion) but also contain code.
 175.484 +     */
 175.485 +    public static boolean isCommentOnlyLine(BaseDocument doc, int offset)
 175.486 +            throws BadLocationException {
 175.487 +        int begin = Utilities.getRowFirstNonWhite(doc, offset);
 175.488 +
 175.489 +        if (begin == -1) {
 175.490 +            return false; // whitespace only
 175.491 +        }
 175.492 +
 175.493 +        Token<? extends PythonTokenId> token = PythonLexerUtils.getToken(doc, begin);
 175.494 +        if (token != null) {
 175.495 +            return token.id() == PythonTokenId.COMMENT;
 175.496 +        }
 175.497 +
 175.498 +        return false;
 175.499 +    }
 175.500 +
 175.501 +    /**
 175.502 +     * Back up to the first space character prior to the given offset - as long as
 175.503 +     * it's on the same line!  If there's only leading whitespace on the line up
 175.504 +     * to the lex offset, return the offset itself
 175.505 +     * @todo Rewrite this now that I have a separate newline token, EOL, that I can
 175.506 +     *   break on - no need to call Utilities.getRowStart.
 175.507 +     */
 175.508 +    public static int findSpaceBegin(BaseDocument doc, int lexOffset) {
 175.509 +        TokenSequence ts = getPythonSequence(doc, lexOffset);
 175.510 +        if (ts == null) {
 175.511 +            return lexOffset;
 175.512 +        }
 175.513 +        boolean allowPrevLine = false;
 175.514 +        int lineStart;
 175.515 +        try {
 175.516 +            lineStart = Utilities.getRowStart(doc, Math.min(lexOffset, doc.getLength()));
 175.517 +            int prevLast = lineStart - 1;
 175.518 +            if (lineStart > 0) {
 175.519 +                prevLast = Utilities.getRowLastNonWhite(doc, lineStart - 1);
 175.520 +                if (prevLast != -1) {
 175.521 +                    char c = doc.getText(prevLast, 1).charAt(0);
 175.522 +                    if (c == ',') {
 175.523 +                        // Arglist continuation? // TODO : check lexing
 175.524 +                        allowPrevLine = true;
 175.525 +                    }
 175.526 +                }
 175.527 +            }
 175.528 +            if (!allowPrevLine) {
 175.529 +                int firstNonWhite = Utilities.getRowFirstNonWhite(doc, lineStart);
 175.530 +                if (lexOffset <= firstNonWhite || firstNonWhite == -1) {
 175.531 +                    return lexOffset;
 175.532 +                }
 175.533 +            } else {
 175.534 +                // Make lineStart so small that Math.max won't cause any problems
 175.535 +                int firstNonWhite = Utilities.getRowFirstNonWhite(doc, lineStart);
 175.536 +                if (prevLast >= 0 && (lexOffset <= firstNonWhite || firstNonWhite == -1)) {
 175.537 +                    return prevLast + 1;
 175.538 +                }
 175.539 +                lineStart = 0;
 175.540 +            }
 175.541 +        } catch (BadLocationException ble) {
 175.542 +            Exceptions.printStackTrace(ble);
 175.543 +            return lexOffset;
 175.544 +        }
 175.545 +        ts.move(lexOffset);
 175.546 +        if (ts.moveNext()) {
 175.547 +            if (lexOffset > ts.offset()) {
 175.548 +                // We're in the middle of a token
 175.549 +                return Math.max((ts.token().id() == PythonTokenId.WHITESPACE) ? ts.offset() : lexOffset, lineStart);
 175.550 +            }
 175.551 +            while (ts.movePrevious()) {
 175.552 +                Token token = ts.token();
 175.553 +                if (token.id() != PythonTokenId.WHITESPACE) {
 175.554 +                    return Math.max(ts.offset() + token.length(), lineStart);
 175.555 +                }
 175.556 +            }
 175.557 +        }
 175.558 +
 175.559 +        return lexOffset;
 175.560 +    }
 175.561 +}
   176.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   176.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/PythonStringLexer.java	Sun Sep 13 11:47:42 2015 +0200
   176.3 @@ -0,0 +1,292 @@
   176.4 +/*
   176.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   176.6 + *
   176.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   176.8 + *
   176.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  176.10 + * Other names may be trademarks of their respective owners.
  176.11 + *
  176.12 + * The contents of this file are subject to the terms of either the GNU
  176.13 + * General Public License Version 2 only ("GPL") or the Common
  176.14 + * Development and Distribution License("CDDL") (collectively, the
  176.15 + * "License"). You may not use this file except in compliance with the
  176.16 + * License. You can obtain a copy of the License at
  176.17 + * http://www.netbeans.org/cddl-gplv2.html
  176.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  176.19 + * specific language governing permissions and limitations under the
  176.20 + * License.  When distributing the software, include this License Header
  176.21 + * Notice in each file and include the License file at
  176.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  176.23 + * particular file as subject to the "Classpath" exception as provided
  176.24 + * by Oracle in the GPL Version 2 section of the License file that
  176.25 + * accompanied this code. If applicable, add the following below the
  176.26 + * License Header, with the fields enclosed by brackets [] replaced by
  176.27 + * your own identifying information:
  176.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  176.29 + *
  176.30 + * Contributor(s):
  176.31 + *
  176.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  176.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  176.34 + * Microsystems, Inc. All Rights Reserved.
  176.35 + *
  176.36 + * If you wish your version of this file to be governed by only the CDDL
  176.37 + * or only the GPL Version 2, indicate your decision by adding
  176.38 + * "[Contributor] elects to include this software in this distribution
  176.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  176.40 + * single choice of license, a recipient has the option to distribute
  176.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  176.42 + * to extend the choice of license to its licensees as provided above.
  176.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  176.44 + * Version 2 license, then the option applies only if the new code is
  176.45 + * made subject to such option by the copyright holder.
  176.46 + */
  176.47 +package org.netbeans.modules.python.source.lexer;
  176.48 +
  176.49 +import org.netbeans.api.lexer.Token;
  176.50 +import org.netbeans.spi.lexer.Lexer;
  176.51 +import org.netbeans.spi.lexer.LexerInput;
  176.52 +import org.netbeans.spi.lexer.LexerRestartInfo;
  176.53 +import org.netbeans.spi.lexer.TokenFactory;
  176.54 +
  176.55 +/**
  176.56 + * A lexer for python strings. Highlights escape sequences, and recognizes
  176.57 + * doctest sections and highlights these as well.
  176.58 + *   http://docs.python.org/lib/module-doctest.html
  176.59 + *
  176.60 + * @todo Track whether strings are raw or not, and don't do escape sequence
  176.61 + *  highlighting in raw strings
  176.62 + *
  176.63 + * @author Tor Norbye
  176.64 + */
  176.65 +public class PythonStringLexer implements Lexer<PythonStringTokenId> {
  176.66 +    private static final int EOF = LexerInput.EOF;
  176.67 +    private final LexerInput input;
  176.68 +    private final TokenFactory<PythonStringTokenId> tokenFactory;
  176.69 +    private final boolean substituting;
  176.70 +
  176.71 +    /**
  176.72 +     * A Lexer for Python strings
  176.73 +     * @param substituting If true, handle substitution rules for double quoted strings, otherwise
  176.74 +     *    single quoted strings.
  176.75 +     */
  176.76 +    public PythonStringLexer(LexerRestartInfo<PythonStringTokenId> info, boolean substituting) {
  176.77 +        this.input = info.input();
  176.78 +        this.tokenFactory = info.tokenFactory();
  176.79 +        this.substituting = substituting;
  176.80 +        assert (info.state() == null); // passed argument always null
  176.81 +    }
  176.82 +
  176.83 +    @Override
  176.84 +    public Object state() {
  176.85 +        return null;
  176.86 +    }
  176.87 +
  176.88 +    @Override
  176.89 +    public Token<PythonStringTokenId> nextToken() {
  176.90 +        boolean inWord = false;
  176.91 +        while (true) {
  176.92 +            int ch = input.read();
  176.93 +
  176.94 +            switch (ch) {
  176.95 +            case EOF:
  176.96 +
  176.97 +                if (input.readLength() > 0) {
  176.98 +                    return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
  176.99 +                            input.readLength());
 176.100 +                } else {
 176.101 +                    return null;
 176.102 +                }
 176.103 +
 176.104 +            case '>':
 176.105 +                // Look for doctest:  \n, whitespace, >>>{embedded python}\n
 176.106 +                int initialReadLength = input.readLength();
 176.107 +                input.read();
 176.108 +                if (ch == '>') {
 176.109 +                    ch = input.read();
 176.110 +                    if (ch == '>') {
 176.111 +                        if (input.readLength() > 3) {
 176.112 +                            input.backup(3);
 176.113 +                            // Finish this token such that we can do a dedicated token for the ">>>" line.
 176.114 +                            return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
 176.115 +                                    input.readLength());
 176.116 +                        }
 176.117 +                        // Find end...
 176.118 +                        boolean nonempty = false;
 176.119 +                        while (true) {
 176.120 +                            ch = input.read();
 176.121 +                            if (ch == EOF) {
 176.122 +                                break;
 176.123 +                            } else if (ch == '\n') {
 176.124 +                                if (nonempty) {
 176.125 +                                    input.backup(1); // Don't include the \n
 176.126 +                                    return tokenFactory.createToken(PythonStringTokenId.EMBEDDED_PYTHON,
 176.127 +                                            input.readLength());
 176.128 +
 176.129 +                                }
 176.130 +                                break;
 176.131 +                            } else if (!Character.isWhitespace(ch)) {
 176.132 +                                nonempty = true;
 176.133 +                            }
 176.134 +                        }
 176.135 +                    }
 176.136 +                }
 176.137 +                if (input.readLength() > initialReadLength) {
 176.138 +                    input.backup(input.readLength() - initialReadLength);
 176.139 +                } else {
 176.140 +                    return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
 176.141 +                            input.readLength());
 176.142 +                }
 176.143 +                break;
 176.144 +
 176.145 +            case '\\':
 176.146 +
 176.147 +                if (input.readLength() > 1) { // already read some text
 176.148 +                    input.backup(1);
 176.149 +
 176.150 +                    return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
 176.151 +                            input.readLength());
 176.152 +                }
 176.153 +
 176.154 +                ch = input.read();
 176.155 +                if (ch == EOF) {
 176.156 +                    return tokenFactory.createToken(PythonStringTokenId.STRING_INVALID,
 176.157 +                            input.readLength());
 176.158 +                } else {
 176.159 +                    return tokenFactory.createToken(PythonStringTokenId.STRING_ESCAPE,
 176.160 +                            input.readLength());
 176.161 +                }
 176.162 +
 176.163 +            case 'f': // ftp:
 176.164 +            case 'm': // mailto:
 176.165 +            case 'w': // www.
 176.166 +            case 'h': { // http links. TODO: link:, ftp:, mailto:, and www.
 176.167 +
 176.168 +                if (inWord) {
 176.169 +                    break;
 176.170 +                }
 176.171 +
 176.172 +                int originalLength = input.readLength();
 176.173 +                boolean foundLinkBegin = false;
 176.174 +
 176.175 +                if (ch == 'h') { // http:
 176.176 +
 176.177 +                    if (input.read() == 't') {
 176.178 +                        if (input.read() == 't') {
 176.179 +                            if (input.read() == 'p') {
 176.180 +                                int r = input.read();
 176.181 +                                if (r == ':') {
 176.182 +                                    foundLinkBegin = true;
 176.183 +                                } else if (r == 's') {
 176.184 +                                    if (input.read() == ':') {
 176.185 +                                        foundLinkBegin = true;
 176.186 +                                    } else {
 176.187 +                                        input.backup(5);
 176.188 +                                    }
 176.189 +                                } else {
 176.190 +                                    input.backup(4);
 176.191 +                                }
 176.192 +                            } else {
 176.193 +                                input.backup(3);
 176.194 +                            }
 176.195 +                        } else {
 176.196 +                            input.backup(2);
 176.197 +                        }
 176.198 +                    } else {
 176.199 +                        input.backup(1);
 176.200 +                    }
 176.201 +                } else if (ch == 'f') { // ftp:
 176.202 +
 176.203 +                    if (input.read() == 't') {
 176.204 +                        if (input.read() == 'p') {
 176.205 +                            if (input.read() == ':') {
 176.206 +                                foundLinkBegin = true;
 176.207 +                            } else {
 176.208 +                                input.backup(3);
 176.209 +                            }
 176.210 +                        } else {
 176.211 +                            input.backup(2);
 176.212 +                        }
 176.213 +                    } else {
 176.214 +                        input.backup(1);
 176.215 +                    }
 176.216 +                } else if (ch == 'm') { // mailto:
 176.217 +
 176.218 +                    if (input.read() == 'a') {
 176.219 +                        if (input.read() == 'i') {
 176.220 +                            if (input.read() == 'l') {
 176.221 +                                if (input.read() == 't') {
 176.222 +                                    if (input.read() == 'o') {
 176.223 +                                        if (input.read() == ':') {
 176.224 +                                            foundLinkBegin = true;
 176.225 +                                        } else {
 176.226 +                                            input.backup(6);
 176.227 +                                        }
 176.228 +                                    } else {
 176.229 +                                        input.backup(5);
 176.230 +                                    }
 176.231 +                                } else {
 176.232 +                                    input.backup(4);
 176.233 +                                }
 176.234 +                            } else {
 176.235 +                                input.backup(3);
 176.236 +                            }
 176.237 +                        } else {
 176.238 +                            input.backup(2);
 176.239 +                        }
 176.240 +                    } else {
 176.241 +                        input.backup(1);
 176.242 +                    }
 176.243 +                } else if (ch == 'w') { // www.
 176.244 +
 176.245 +                    if (input.read() == 'w') {
 176.246 +                        if (input.read() == 'w') {
 176.247 +                            if (input.read() == '.') {
 176.248 +                                foundLinkBegin = true;
 176.249 +                            } else {
 176.250 +                                input.backup(3);
 176.251 +                            }
 176.252 +                        } else {
 176.253 +                            input.backup(2);
 176.254 +                        }
 176.255 +                    } else {
 176.256 +                        input.backup(1);
 176.257 +                    }
 176.258 +                }
 176.259 +
 176.260 +                if (foundLinkBegin) {
 176.261 +                    while (ch != EOF) {
 176.262 +                        ch = input.read();
 176.263 +
 176.264 +                        if ((ch == ']') || (ch == ')') || Character.isWhitespace(ch) ||
 176.265 +                                (ch == '\'') || (ch == '"')) {
 176.266 +                            input.backup(1);
 176.267 +
 176.268 +                            break;
 176.269 +                        }
 176.270 +                    }
 176.271 +
 176.272 +                    if (originalLength > 1) {
 176.273 +                        input.backup(input.readLengthEOF() - originalLength + 1);
 176.274 +
 176.275 +                        return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
 176.276 +                                input.readLength());
 176.277 +                    }
 176.278 +
 176.279 +                    if (input.readLength() > 2) {
 176.280 +                        return tokenFactory.createToken(PythonStringTokenId.URL,
 176.281 +                                input.readLength());
 176.282 +                    }
 176.283 +                }
 176.284 +                break;
 176.285 +            }
 176.286 +            }
 176.287 +
 176.288 +            inWord = Character.isJavaIdentifierPart(ch);
 176.289 +        }
 176.290 +    }
 176.291 +
 176.292 +    @Override
 176.293 +    public void release() {
 176.294 +    }
 176.295 +}
   177.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   177.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/PythonStringTokenId.java	Sun Sep 13 11:47:42 2015 +0200
   177.3 @@ -0,0 +1,125 @@
   177.4 +/*
   177.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   177.6 + *
   177.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   177.8 + *
   177.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  177.10 + * Other names may be trademarks of their respective owners.
  177.11 + *
  177.12 + * The contents of this file are subject to the terms of either the GNU
  177.13 + * General Public License Version 2 only ("GPL") or the Common
  177.14 + * Development and Distribution License("CDDL") (collectively, the
  177.15 + * "License"). You may not use this file except in compliance with the
  177.16 + * License. You can obtain a copy of the License at
  177.17 + * http://www.netbeans.org/cddl-gplv2.html
  177.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  177.19 + * specific language governing permissions and limitations under the
  177.20 + * License.  When distributing the software, include this License Header
  177.21 + * Notice in each file and include the License file at
  177.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  177.23 + * particular file as subject to the "Classpath" exception as provided
  177.24 + * by Oracle in the GPL Version 2 section of the License file that
  177.25 + * accompanied this code. If applicable, add the following below the
  177.26 + * License Header, with the fields enclosed by brackets [] replaced by
  177.27 + * your own identifying information:
  177.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  177.29 + *
  177.30 + * Contributor(s):
  177.31 + *
  177.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  177.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  177.34 + * Microsystems, Inc. All Rights Reserved.
  177.35 + *
  177.36 + * If you wish your version of this file to be governed by only the CDDL
  177.37 + * or only the GPL Version 2, indicate your decision by adding
  177.38 + * "[Contributor] elects to include this software in this distribution
  177.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  177.40 + * single choice of license, a recipient has the option to distribute
  177.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  177.42 + * to extend the choice of license to its licensees as provided above.
  177.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  177.44 + * Version 2 license, then the option applies only if the new code is
  177.45 + * made subject to such option by the copyright holder.
  177.46 + */
  177.47 +package org.netbeans.modules.python.source.lexer;
  177.48 +
  177.49 +import java.util.Collection;
  177.50 +import java.util.EnumSet;
  177.51 +import java.util.Map;
  177.52 +
  177.53 +import org.netbeans.api.lexer.InputAttributes;
  177.54 +import org.netbeans.api.lexer.Language;
  177.55 +import org.netbeans.api.lexer.LanguagePath;
  177.56 +import org.netbeans.api.lexer.Token;
  177.57 +import org.netbeans.api.lexer.TokenId;
  177.58 +import org.netbeans.api.lexer.TokenUtilities;
  177.59 +import org.netbeans.spi.lexer.LanguageEmbedding;
  177.60 +import org.netbeans.spi.lexer.LanguageHierarchy;
  177.61 +import org.netbeans.spi.lexer.Lexer;
  177.62 +import org.netbeans.spi.lexer.LexerRestartInfo;
  177.63 +
  177.64 +/**
  177.65 + *
  177.66 + * @author Tor Norbye
  177.67 + */
  177.68 +public enum PythonStringTokenId implements TokenId {
  177.69 +    STRING_TEXT("string"),
  177.70 +    STRING_ESCAPE("string-escape"),
  177.71 +    STRING_INVALID("string-escape-invalid"),
  177.72 +    URL("url"),
  177.73 +    EMBEDDED_PYTHON("string");
  177.74 +    private final String primaryCategory;
  177.75 +
  177.76 +    PythonStringTokenId() {
  177.77 +        this(null);
  177.78 +    }
  177.79 +
  177.80 +    PythonStringTokenId(String primaryCategory) {
  177.81 +        this.primaryCategory = primaryCategory;
  177.82 +    }
  177.83 +
  177.84 +    @Override
  177.85 +    public String primaryCategory() {
  177.86 +        return primaryCategory;
  177.87 +    }
  177.88 +    public static final Language<PythonStringTokenId> language =
  177.89 +            new LanguageHierarchy<PythonStringTokenId>() {
  177.90 +                @Override
  177.91 +                protected Collection<PythonStringTokenId> createTokenIds() {
  177.92 +                    return EnumSet.allOf(PythonStringTokenId.class);
  177.93 +                }
  177.94 +
  177.95 +                @Override
  177.96 +                protected Map<String, Collection<PythonStringTokenId>> createTokenCategories() {
  177.97 +                    return null; // no extra categories
  177.98 +                }
  177.99 +
 177.100 +                @Override
 177.101 +                protected Lexer<PythonStringTokenId> createLexer(
 177.102 +                        LexerRestartInfo<PythonStringTokenId> info) {
 177.103 +                    return new PythonStringLexer(info, true);
 177.104 +                }
 177.105 +
 177.106 +                @Override
 177.107 +                protected LanguageEmbedding<?> embedding(
 177.108 +                        Token<PythonStringTokenId> token, LanguagePath languagePath,
 177.109 +                        InputAttributes inputAttributes) {
 177.110 +                    PythonStringTokenId id = token.id();
 177.111 +
 177.112 +                    if (id == EMBEDDED_PYTHON && token.text() != null) {
 177.113 +                        return LanguageEmbedding.create(PythonTokenId.language(), 3, 0); // 3: Exlude ">>>" prefix
 177.114 +                    }
 177.115 +
 177.116 +                    return null; // No embedding
 177.117 +                }
 177.118 +
 177.119 +                @Override
 177.120 +                public String mimeType() {
 177.121 +                    return "text/x-python-string"; // NOI18N
 177.122 +                }
 177.123 +            }.language();
 177.124 +
 177.125 +    public static Language<PythonStringTokenId> language() {
 177.126 +        return language;
 177.127 +    }
 177.128 +}
   178.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   178.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/PythonTokenId.java	Sun Sep 13 11:47:42 2015 +0200
   178.3 @@ -0,0 +1,206 @@
   178.4 +/*
   178.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   178.6 + *
   178.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   178.8 + *
   178.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  178.10 + * Other names may be trademarks of their respective owners.
  178.11 + *
  178.12 + * The contents of this file are subject to the terms of either the GNU
  178.13 + * General Public License Version 2 only ("GPL") or the Common
  178.14 + * Development and Distribution License("CDDL") (collectively, the
  178.15 + * "License"). You may not use this file except in compliance with the
  178.16 + * License. You can obtain a copy of the License at
  178.17 + * http://www.netbeans.org/cddl-gplv2.html
  178.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  178.19 + * specific language governing permissions and limitations under the
  178.20 + * License.  When distributing the software, include this License Header
  178.21 + * Notice in each file and include the License file at
  178.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  178.23 + * particular file as subject to the "Classpath" exception as provided
  178.24 + * by Oracle in the GPL Version 2 section of the License file that
  178.25 + * accompanied this code. If applicable, add the following below the
  178.26 + * License Header, with the fields enclosed by brackets [] replaced by
  178.27 + * your own identifying information:
  178.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  178.29 + *
  178.30 + * Contributor(s):
  178.31 + *
  178.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  178.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  178.34 + * Microsystems, Inc. All Rights Reserved.
  178.35 + *
  178.36 + * If you wish your version of this file to be governed by only the CDDL
  178.37 + * or only the GPL Version 2, indicate your decision by adding
  178.38 + * "[Contributor] elects to include this software in this distribution
  178.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  178.40 + * single choice of license, a recipient has the option to distribute
  178.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  178.42 + * to extend the choice of license to its licensees as provided above.
  178.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  178.44 + * Version 2 license, then the option applies only if the new code is
  178.45 + * made subject to such option by the copyright holder.
  178.46 + */
  178.47 +package org.netbeans.modules.python.source.lexer;
  178.48 +
  178.49 +import java.util.Collection;
  178.50 +import java.util.EnumSet;
  178.51 +import java.util.HashMap;
  178.52 +import java.util.Map;
  178.53 +import org.netbeans.api.lexer.InputAttributes;
  178.54 +import org.netbeans.api.lexer.Language;
  178.55 +import org.netbeans.api.lexer.LanguagePath;
  178.56 +import org.netbeans.api.lexer.Token;
  178.57 +import org.netbeans.api.lexer.TokenId;
  178.58 +import org.netbeans.modules.python.api.PythonMIMEResolver;
  178.59 +import org.netbeans.modules.python.source.PythonUtils;
  178.60 +import org.netbeans.spi.lexer.LanguageEmbedding;
  178.61 +import org.netbeans.spi.lexer.LanguageHierarchy;
  178.62 +import org.netbeans.spi.lexer.Lexer;
  178.63 +import org.netbeans.spi.lexer.LexerInput;
  178.64 +import org.netbeans.spi.lexer.LexerRestartInfo;
  178.65 +
  178.66 +import org.netbeans.spi.lexer.TokenFactory;
  178.67 +import org.openide.filesystems.FileObject;
  178.68 +import static org.netbeans.modules.python.source.lexer.PythonLexer.*;
  178.69 +
  178.70 +/**
  178.71 + * @todo add the rest of the tokens
  178.72 + *
  178.73 + * @author Martin Adamek
  178.74 + * @author alley
  178.75 + */
  178.76 +public enum PythonTokenId implements TokenId {
  178.77 +    ERROR(null, ERROR_CAT),
  178.78 +    IDENTIFIER(null, IDENTIFIER_CAT),
  178.79 +    INT_LITERAL(null, NUMBER_CAT),
  178.80 +    FLOAT_LITERAL(null, NUMBER_CAT),
  178.81 +    STRING_LITERAL(null, STRING_CAT),
  178.82 +    WHITESPACE(null, WHITESPACE_CAT),
  178.83 +    NEWLINE(null, WHITESPACE_CAT),
  178.84 +    DECORATOR(null, OPERATOR_CAT), // NOI18N
  178.85 +    //    CONTINUED_LINE(null, WHITESPACE_CAT), // NOI18N
  178.86 +    COMMENT(null, COMMENT_CAT),
  178.87 +    STD_SYMBOLS(null, KEYWORD_CAT), // NOI18N
  178.88 +    LPAREN("(", SEPARATOR_CAT), // NOI18N
  178.89 +    RPAREN(")", SEPARATOR_CAT), // NOI18N
  178.90 +    LBRACE("{", SEPARATOR_CAT), // NOI18N
  178.91 +    RBRACE("}", SEPARATOR_CAT), // NOI18N
  178.92 +    LBRACKET("[", SEPARATOR_CAT), // NOI18N
  178.93 +    RBRACKET("]", SEPARATOR_CAT), // NOI18N
  178.94 +    STRING_BEGIN(null, STRING_CAT),
  178.95 +    STRING_END(null, STRING_CAT),
  178.96 +    // Cheating: out of laziness just map all keywords returning from Jython
  178.97 +    // into a single KEYWORD token; eventually we will have separate tokens
  178.98 +    // for each here such that the various helper methods for formatting,
  178.99 +    // smart indent, brace matching etc. can refer to specific keywords
 178.100 +    ANY_KEYWORD(null, KEYWORD_CAT),
 178.101 +    ANY_OPERATOR(null, OPERATOR_CAT),
 178.102 +    DEF("def", KEYWORD_CAT), // NOI18N
 178.103 +    CLASS("class", KEYWORD_CAT), // NOI18N
 178.104 +    IF("if", KEYWORD_CAT), // NOI18N
 178.105 +    ELSE("else", KEYWORD_CAT), // NOI18N
 178.106 +    ELIF("elif", KEYWORD_CAT), // NOI18N
 178.107 +    RAISE("raise", KEYWORD_CAT), // NOI18N
 178.108 +    PASS("pass", KEYWORD_CAT), // NOI18N
 178.109 +    RETURN("return", KEYWORD_CAT), // NOI18N
 178.110 +    EXCEPT("except", KEYWORD_CAT), // NOI18N
 178.111 +    FINALLY("finally", KEYWORD_CAT), // NOI18N
 178.112 +    IMPORT("import", KEYWORD_CAT), // NOI18N
 178.113 +    FROM("from", KEYWORD_CAT), // NOI18N
 178.114 +    TRUE("True", KEYWORD_CAT), // NOI18N
 178.115 +    FALSE("False", KEYWORD_CAT), // NOI18N
 178.116 +    NONE("None", KEYWORD_CAT), // NOI18N
 178.117 +    TRY("try", KEYWORD_CAT), // NOI18N
 178.118 +    DOT(".", OPERATOR_CAT), // NOI18N
 178.119 +    COMMA(",", OPERATOR_CAT), // NOI18N
 178.120 +    COLON(":", OPERATOR_CAT), // NOI18N
 178.121 +    ESC("\\", OPERATOR_CAT), // NOI18N
 178.122 +
 178.123 +    // Non-unary operators which indicate a line continuation if used at the end of a line
 178.124 +    NONUNARY_OP(null, OPERATOR_CAT);
 178.125 +    private final String fixedText;
 178.126 +    private final String primaryCategory;
 178.127 +
 178.128 +    PythonTokenId(String fixedText, String primaryCategory) {
 178.129 +        this.fixedText = fixedText;
 178.130 +        this.primaryCategory = primaryCategory;
 178.131 +    }
 178.132 +
 178.133 +    @Override
 178.134 +    public String primaryCategory() {
 178.135 +        return primaryCategory;
 178.136 +    }
 178.137 +
 178.138 +    public String fixedText() {
 178.139 +        return fixedText;
 178.140 +    }
 178.141 +    private static final Language<PythonTokenId> language =
 178.142 +            new LanguageHierarchy<PythonTokenId>() {
 178.143 +                @Override
 178.144 +                protected String mimeType() {
 178.145 +                    return PythonMIMEResolver.PYTHON_MIME_TYPE;
 178.146 +                }
 178.147 +
 178.148 +                @Override
 178.149 +                protected Collection<PythonTokenId> createTokenIds() {
 178.150 +                    return EnumSet.allOf(PythonTokenId.class);
 178.151 +                }
 178.152 +
 178.153 +                @Override
 178.154 +                protected Map<String, Collection<PythonTokenId>> createTokenCategories() {
 178.155 +                    Map<String, Collection<PythonTokenId>> cats =
 178.156 +                            new HashMap<>();
 178.157 +                    return cats;
 178.158 +                }
 178.159 +
 178.160 +                @Override
 178.161 +                protected Lexer<PythonTokenId> createLexer(LexerRestartInfo<PythonTokenId> info) {
 178.162 +                    FileObject fileObject = (FileObject)info.getAttributeValue(FileObject.class);
 178.163 +                    final TokenFactory<PythonTokenId> tokenFactory = info.tokenFactory();
 178.164 +                    final LexerInput input = info.input();
 178.165 +                    // Lex .rst files just as literal strings
 178.166 +                    if (fileObject != null && PythonUtils.isRstFile(fileObject)) {
 178.167 +                        return new Lexer<PythonTokenId>() {
 178.168 +                            @Override
 178.169 +                            public Token<PythonTokenId> nextToken() {
 178.170 +                                if (input.read() == LexerInput.EOF) {
 178.171 +                                    return null;
 178.172 +                                }
 178.173 +                                while (input.read() != LexerInput.EOF) {
 178.174 +                                    ;
 178.175 +                                }
 178.176 +                                return tokenFactory.createToken(PythonTokenId.STRING_LITERAL, input.readLength());
 178.177 +                            }
 178.178 +
 178.179 +                            @Override
 178.180 +                            public Object state() {
 178.181 +                                return null;
 178.182 +                            }
 178.183 +
 178.184 +                            @Override
 178.185 +                            public void release() {
 178.186 +                            }
 178.187 +                        };
 178.188 +                    }
 178.189 +                    return new PythonLexer(info);
 178.190 +                }
 178.191 +
 178.192 +                @Override
 178.193 +                protected LanguageEmbedding<?> embedding(Token<PythonTokenId> token,
 178.194 +                        LanguagePath languagePath, InputAttributes inputAttributes) {
 178.195 +                    PythonTokenId id = token.id();
 178.196 +                    if (id == STRING_LITERAL) {
 178.197 +                        return LanguageEmbedding.create(PythonStringTokenId.language, 0, 0);
 178.198 +                    } else if (id == COMMENT) {
 178.199 +                        return LanguageEmbedding.create(PythonCommentTokenId.language(), 1, 0);
 178.200 +                    }
 178.201 +
 178.202 +                    return null; // No embedding
 178.203 +                }
 178.204 +            }.language();
 178.205 +
 178.206 +    public static Language<PythonTokenId> language() {
 178.207 +        return language;
 178.208 +    }
 178.209 +}
   179.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   179.2 +++ b/python.source/src/org/netbeans/modules/python/source/queries/DeprecationQuery.java	Sun Sep 13 11:47:42 2015 +0200
   179.3 @@ -0,0 +1,169 @@
   179.4 +/*
   179.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   179.6 + *
   179.7 + * Copyright 2015 Oracle and/or its affiliates. All rights reserved.
   179.8 + *
   179.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  179.10 + * Other names may be trademarks of their respective owners.
  179.11 + *
  179.12 + * The contents of this file are subject to the terms of either the GNU
  179.13 + * General Public License Version 2 only ("GPL") or the Common
  179.14 + * Development and Distribution License("CDDL") (collectively, the
  179.15 + * "License"). You may not use this file except in compliance with the
  179.16 + * License. You can obtain a copy of the License at
  179.17 + * http://www.netbeans.org/cddl-gplv2.html
  179.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  179.19 + * specific language governing permissions and limitations under the
  179.20 + * License.  When distributing the software, include this License Header
  179.21 + * Notice in each file and include the License file at
  179.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  179.23 + * particular file as subject to the "Classpath" exception as provided
  179.24 + * by Oracle in the GPL Version 2 section of the License file that
  179.25 + * accompanied this code. If applicable, add the following below the
  179.26 + * License Header, with the fields enclosed by brackets [] replaced by
  179.27 + * your own identifying information:
  179.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  179.29 + *
  179.30 + * If you wish your version of this file to be governed by only the CDDL
  179.31 + * or only the GPL Version 2, indicate your decision by adding
  179.32 + * "[Contributor] elects to include this software in this distribution
  179.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  179.34 + * single choice of license, a recipient has the option to distribute
  179.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  179.36 + * to extend the choice of license to its licensees as provided above.
  179.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  179.38 + * Version 2 license, then the option applies only if the new code is
  179.39 + * made subject to such option by the copyright holder.
  179.40 + *
  179.41 + * Contributor(s):
  179.42 + *
  179.43 + * Portions Copyrighted 2015 Sun Microsystems, Inc.
  179.44 + */
  179.45 +package org.netbeans.modules.python.source.queries;
  179.46 +
  179.47 +import java.util.HashMap;
  179.48 +import java.util.Map;
  179.49 +
  179.50 +/**
  179.51 + *
  179.52 + * @author Ralph Ruijs
  179.53 + */
  179.54 +public final class DeprecationQuery {
  179.55 +    private static final Map<String, String> DEPRECATED = new HashMap<>();
  179.56 +
  179.57 +
  179.58 +    static {
  179.59 +        for (String module : new String[]{"cl", "sv", "timing"}) {
  179.60 +            DEPRECATED.put(module, "Listed as obsolete in the library documentation");
  179.61 +        }
  179.62 +
  179.63 +        for (String module : new String[]{
  179.64 +                    "addpack", "cmp", "cmpcache", "codehack", "dircmp", "dump", "find", "fmt",
  179.65 +                    "grep", "lockfile", "newdir", "ni", "packmail", "Para", "poly",
  179.66 +                    "rand", "reconvert", "regex", "regsub", "statcache", "tb", "tzparse",
  179.67 +                    "util", "whatsound", "whrandom", "zmod"}) {
  179.68 +            DEPRECATED.put(module, "Obsolete module, removed in Python 2.5");
  179.69 +
  179.70 +        }
  179.71 +
  179.72 +        for (String module : new String[]{"gopherlib", "rgbimg", "macfs"}) {
  179.73 +            DEPRECATED.put(module, "Obsolete module, removed in Python 2.6");
  179.74 +        }
  179.75 +
  179.76 +        /*
  179.77 +        al.rst:    The :mod:`al` module has been deprecated for removal in Python 3.0.
  179.78 +        al.rst:   The :mod:`AL` module has been deprecated for removal in Python 3.0.
  179.79 +        bsddb.rst:    The :mod:`bsddb` module has been deprecated for removal in Python 3.0.
  179.80 +        cd.rst:    The :mod:`cd` module has been deprecated for removal in Python 3.0.
  179.81 +        dbhash.rst:    The :mod:`dbhash` module has been deprecated for removal in Python 3.0.
  179.82 +        fl.rst:    The :mod:`fl` module has been deprecated for removal in Python 3.0.
  179.83 +        fl.rst:    The :mod:`FL` module has been deprecated for removal in Python 3.0.
  179.84 +        fl.rst:    The :mod:`flp` module has been deprecated for removal in Python 3.0.
  179.85 +        fm.rst:   The :mod:`fm` module has been deprecated for removal in Python 3.0.
  179.86 +        gl.rst:    The :mod:`gl` module has been deprecated for removal in Python 3.0.
  179.87 +        gl.rst:    The :mod:`DEVICE` module has been deprecated for removal in Python 3.0.
  179.88 +        gl.rst:    The :mod:`GL` module has been deprecated for removal in Python 3.0.
  179.89 +        imgfile.rst:   The :mod:`imgfile` module has been deprecated for removal in Python 3.0.
  179.90 +        jpeg.rst:   The :mod:`jpeg` module has been deprecated for removal in Python 3.0.
  179.91 +        statvfs.rst:   The :mod:`statvfs` module has been deprecated for removal in Python 3.0.
  179.92 +        sunaudio.rst:   The :mod:`sunaudiodev` module has been deprecated for removal in Python 3.0.
  179.93 +        sunaudio.rst:   The :mod:`SUNAUDIODEV` module has been deprecated for removal in Python 3.0.
  179.94 +        tarfile.rst:      The :class:`TarFileCompat` class has been deprecated for removal in Python 3.0.
  179.95 +         */
  179.96 +
  179.97 +        DEPRECATED.put("posixfile",
  179.98 +                "Locking is better done by fcntl.lockf().");
  179.99 +
 179.100 +        DEPRECATED.put("gopherlib",
 179.101 +                "The gopher protocol is not in active use anymore.");
 179.102 +
 179.103 +        DEPRECATED.put("rgbimgmodule",
 179.104 +                "");
 179.105 +
 179.106 +        DEPRECATED.put("pre",
 179.107 +                "The underlying PCRE engine doesn't support Unicode, and has been unmaintained since Python 1.5.2.");
 179.108 +
 179.109 +        DEPRECATED.put("whrandom",
 179.110 +                "The module's default seed computation was inherently insecure; the random module should be used instead.");
 179.111 +
 179.112 +        DEPRECATED.put("rfc822",
 179.113 +                "Supplanted by Python 2.2's email package.");
 179.114 +
 179.115 +        DEPRECATED.put("mimetools",
 179.116 +                "Supplanted by Python 2.2's email package.");
 179.117 +
 179.118 +        DEPRECATED.put("MimeWriter",
 179.119 +                "Supplanted by Python 2.2's email package.");
 179.120 +
 179.121 +        DEPRECATED.put("mimify",
 179.122 +                "Supplanted by Python 2.2's email package.");
 179.123 +
 179.124 +        DEPRECATED.put("rotor",
 179.125 +                "Uses insecure algorithm.");
 179.126 +
 179.127 +        DEPRECATED.put("TERMIOS.py",
 179.128 +                "The constants in this file are now in the 'termios' module.");
 179.129 +
 179.130 +        DEPRECATED.put("statcache",
 179.131 +                "Using the cache can be fragile and error-prone; applications should just use os.stat() directly.");
 179.132 +
 179.133 +        DEPRECATED.put("mpz",
 179.134 +                "Third-party packages provide similiar features and wrap more of GMP's API.");
 179.135 +
 179.136 +
 179.137 +        DEPRECATED.put("xreadlines",
 179.138 +                "Using 'for line in file', introduced in 2.3, is preferable.");
 179.139 +
 179.140 +        DEPRECATED.put("multifile",
 179.141 +                "Supplanted by the email package.");
 179.142 +
 179.143 +        DEPRECATED.put("sets",
 179.144 +                "The built-in set/frozenset types, introduced in Python 2.4, supplant the module.");
 179.145 +
 179.146 +        DEPRECATED.put("buildtools",
 179.147 +                "");
 179.148 +
 179.149 +        DEPRECATED.put("cfmfile",
 179.150 +                "");
 179.151 +
 179.152 +        DEPRECATED.put("macfs",
 179.153 +                "");
 179.154 +
 179.155 +        DEPRECATED.put("md5",
 179.156 +                "Replaced by the 'hashlib' module.");
 179.157 +
 179.158 +        DEPRECATED.put("sha",
 179.159 +                "Replaced by the 'hashlib' module.");
 179.160 +    }
 179.161 +
 179.162 +    public static boolean isDeprecatedModule(String module) {
 179.163 +        return DEPRECATED.containsKey(module);
 179.164 +    }
 179.165 +    
 179.166 +    public static String getDeprecatedModuleDescription(String module) {
 179.167 +        return DEPRECATED.get(module);
 179.168 +    }
 179.169 +
 179.170 +    private DeprecationQuery() {
 179.171 +    }
 179.172 +}
   180.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   180.2 +++ b/python.source/src/org/netbeans/modules/python/source/scopes/ArgListCompiler.java	Sun Sep 13 11:47:42 2015 +0200
   180.3 @@ -0,0 +1,121 @@
   180.4 +// Copyright (c) Corporation for National Research Initiatives
   180.5 +package org.netbeans.modules.python.source.scopes;
   180.6 +
   180.7 +import java.util.ArrayList;
   180.8 +
   180.9 +import java.util.List;
  180.10 +import org.python.antlr.PythonTree;
  180.11 +import org.python.antlr.Visitor;
  180.12 +import org.python.antlr.ast.Assign;
  180.13 +import org.python.antlr.ast.Name;
  180.14 +import org.python.antlr.ast.Suite;
  180.15 +import org.python.antlr.ast.Tuple;
  180.16 +import org.python.antlr.ast.arguments;
  180.17 +import org.python.antlr.ast.expr_contextType;
  180.18 +import org.python.antlr.base.expr;
  180.19 +import org.python.antlr.base.stmt;
  180.20 +
  180.21 +/** Based on org.python.compiler.ArgListCompiler */
  180.22 +public class ArgListCompiler extends Visitor {
  180.23 +    public boolean arglist, keywordlist;
  180.24 +    public List<expr> defaults;
  180.25 +    public List<String> names;
  180.26 +    public ArrayList<PythonTree> nodes;
  180.27 +    public List<String> fpnames;
  180.28 +    public List<stmt> init_code;
  180.29 +    private SymbolTable symbolTable;
  180.30 +
  180.31 +    public ArgListCompiler(SymbolTable symbolTable) {
  180.32 +        this.symbolTable = symbolTable;
  180.33 +        arglist = keywordlist = false;
  180.34 +        defaults = null;
  180.35 +        names = new ArrayList<>();
  180.36 +        nodes = new ArrayList<>();
  180.37 +        fpnames = new ArrayList<>();
  180.38 +        init_code = new ArrayList<>();
  180.39 +    }
  180.40 +
  180.41 +    public void reset() {
  180.42 +        arglist = keywordlist = false;
  180.43 +        defaults = null;
  180.44 +        names.clear();
  180.45 +        nodes.clear();
  180.46 +        init_code.clear();
  180.47 +    }
  180.48 +
  180.49 +    public void appendInitCode(Suite node) {
  180.50 +        node.getInternalBody().addAll(0, init_code);
  180.51 +    }
  180.52 +
  180.53 +    public List<expr> getDefaults() {
  180.54 +        return defaults;
  180.55 +    }
  180.56 +
  180.57 +    public void visitArgs(arguments args) throws Exception {
  180.58 +        for (int i = 0; i < args.getInternalArgs().size(); i++) {
  180.59 +            expr node = args.getInternalArgs().get(i);
  180.60 +            String name = (String)visit(node);
  180.61 +            names.add(name);
  180.62 +            nodes.add(node);
  180.63 +            if (node instanceof Tuple) {
  180.64 +                List<expr> targets = new ArrayList<>();
  180.65 +                targets.add(node);
  180.66 +                Assign ass = new Assign(node,
  180.67 +                        targets,
  180.68 +                        new Name(node, name, expr_contextType.Load));
  180.69 +                init_code.add(ass);
  180.70 +            }
  180.71 +        }
  180.72 +        if (args.getInternalVararg() != null) {
  180.73 +            arglist = true;
  180.74 +            names.add(args.getInternalVararg());
  180.75 +            //nodes.add(null); // no corresponding node?
  180.76 +            nodes.add(args); // just use the corresponding args node instead
  180.77 +        }
  180.78 +        if (args.getInternalKwarg() != null) {
  180.79 +            keywordlist = true;
  180.80 +            names.add(args.getInternalKwarg());
  180.81 +            //nodes.add(null); // no corresponding node?
  180.82 +            nodes.add(args); // just use the corresponding args node instead
  180.83 +        }
  180.84 +
  180.85 +        defaults = args.getInternalDefaults();
  180.86 +        for (int i = 0; i < defaults.size(); i++) {
  180.87 +            if (defaults.get(i) == null) {
  180.88 +                symbolTable.error("non-default argument follows default argument", true,
  180.89 +                        args.getInternalArgs().get(args.getInternalArgs().size() - defaults.size() + i));
  180.90 +            }
  180.91 +        }
  180.92 +    }
  180.93 +
  180.94 +    @Override
  180.95 +    public Object visitName(Name node) throws Exception {
  180.96 +        //FIXME: do we need Store and Param, or just Param?
  180.97 +        if (node.getInternalCtx() != expr_contextType.Store && node.getInternalCtx() != expr_contextType.Param) {
  180.98 +            return null;
  180.99 +        }
 180.100 +
 180.101 +        if (fpnames.contains(node.getInternalId())) {
 180.102 +            symbolTable.error("duplicate argument name found: " +
 180.103 +                    node.getInternalId(), true, node);
 180.104 +        }
 180.105 +        fpnames.add(node.getInternalId());
 180.106 +        return node.getInternalId();
 180.107 +    }
 180.108 +
 180.109 +    @Override
 180.110 +    public Object visitTuple(Tuple node) throws Exception {
 180.111 +        StringBuffer name = new StringBuffer("(");
 180.112 +        List<expr> elts = node.getInternalElts();
 180.113 +        if (elts != null) {
 180.114 +            int n = elts.size();
 180.115 +            for (int i = 0; i < n - 1; i++) {
 180.116 +                name.append(visit(elts.get(i)));
 180.117 +                name.append(", ");
 180.118 +            }
 180.119 +            name.append(visit(elts.get(n - 1)));
 180.120 +        }
 180.121 +        name.append(")");
 180.122 +        return name.toString();
 180.123 +    }
 180.124 +}
   181.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   181.2 +++ b/python.source/src/org/netbeans/modules/python/source/scopes/ScopeConstants.java	Sun Sep 13 11:47:42 2015 +0200
   181.3 @@ -0,0 +1,28 @@
   181.4 +package org.netbeans.modules.python.source.scopes;
   181.5 +
   181.6 +/** Based on org.python.compiler.ScopeConstants in Jython */
   181.7 +public interface ScopeConstants {
   181.8 +    public final static int BOUND = 1 << 0;
   181.9 +    public final static int NGLOBAL = 1 << 1; // func scope expl global
  181.10 +    public final static int PARAM = 1 << 2;
  181.11 +    public final static int FROM_PARAM = 1 << 3;
  181.12 +    public final static int CELL = 1 << 4;
  181.13 +    public final static int FREE = 1 << 5;
  181.14 +    public final static int CLASS_GLOBAL = 1 << 6; // class scope expl global
  181.15 +    public final static int READ = 1 << 7;
  181.16 +    public final static int CALLED = 1 << 8;
  181.17 +    public final static int DEF = 1 << 9;
  181.18 +    public final static int IMPORTED = 1 << 10;
  181.19 +    public final static int CLASS = 1 << 11;
  181.20 +    public final static int FUNCTION = 1 << 12;
  181.21 +    public final static int MEMBER = 1 << 13;
  181.22 +    public final static int GENERATOR = 1 << 13; // it's a generator expression
  181.23 +    public final static int PRIVATE = 1 << 14;
  181.24 +    public final static int ALIAS = 1 << 15;
  181.25 +    public final static int PROTECTED = 1 << 16;
  181.26 +    public final static int BOUND_IN_CONSTRUCTOR = 1 << 17;
  181.27 +    public final static int GLOBAL = NGLOBAL | CLASS_GLOBAL; // all global
  181.28 +    public final static int TOPSCOPE = 0;
  181.29 +    public final static int FUNCSCOPE = 1;
  181.30 +    public final static int CLASSSCOPE = 2;
  181.31 +}
   182.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   182.2 +++ b/python.source/src/org/netbeans/modules/python/source/scopes/ScopeInfo.java	Sun Sep 13 11:47:42 2015 +0200
   182.3 @@ -0,0 +1,576 @@
   182.4 +// (C) Copyright 2001 Samuele Pedroni
   182.5 +package org.netbeans.modules.python.source.scopes;
   182.6 +
   182.7 +import java.util.ArrayList;
   182.8 +import java.util.Collections;
   182.9 +import java.util.HashMap;
  182.10 +import java.util.LinkedHashMap;
  182.11 +import java.util.Map;
  182.12 +import java.util.List;
  182.13 +
  182.14 +import org.netbeans.modules.python.source.AstPath;
  182.15 +import org.netbeans.modules.python.source.PythonAstUtils;
  182.16 +import org.python.antlr.ParseException;
  182.17 +import org.python.antlr.PythonTree;
  182.18 +import org.python.antlr.ast.Assign;
  182.19 +import org.python.antlr.ast.Attribute;
  182.20 +import org.python.antlr.ast.ClassDef;
  182.21 +import org.python.antlr.ast.Name;
  182.22 +import org.python.antlr.ast.Return;
  182.23 +import org.python.antlr.ast.Tuple;
  182.24 +import org.python.antlr.base.expr;
  182.25 +import static org.netbeans.modules.python.source.scopes.ScopeConstants.*;
  182.26 +import org.netbeans.modules.python.source.NameStyle;
  182.27 +
  182.28 +/** 
  182.29 + * Based on org.python.compiler.ScopeInfo in Jython
  182.30 + *
  182.31 + * See {@link ScopesCompiler} for details on my modifications
  182.32 + */
  182.33 +@SuppressWarnings("unchecked")
  182.34 +public class ScopeInfo extends Object {
  182.35 +    public PythonTree scope_node;
  182.36 +    public String scope_name;
  182.37 +    public int level;
  182.38 +    public int func_level;
  182.39 +    public boolean hidden;
  182.40 +
  182.41 +    public String dump() {
  182.42 +        StringBuilder sb = new StringBuilder();
  182.43 +
  182.44 +        for (int i = 0; i < level; i++) {
  182.45 +            sb.append("    ");
  182.46 +        }
  182.47 +        sb.append("=============================================\n");
  182.48 +        for (int i = 0; i < level; i++) {
  182.49 +            sb.append("    ");
  182.50 +        }
  182.51 +        sb.append(((kind != CLASSSCOPE) ? scope_name : "class " +
  182.52 +                scope_name) + ": " + scope_node + " : " + PythonAstUtils.getRange(scope_node) + "\n");
  182.53 +        //for(int i=0; i<level; i++) sb.append("    ");
  182.54 +        //sb.append("UP=" + up);
  182.55 +        //sb.append("   NESTED=" + nested);
  182.56 +        //sb.append("\n");
  182.57 +
  182.58 +
  182.59 +        // Sort to make test output stable
  182.60 +        List<String> keys = new ArrayList<>(tbl.keySet());
  182.61 +        Collections.sort(keys);
  182.62 +        for (String name : keys) {
  182.63 +            SymInfo info = tbl.get(name);
  182.64 +            for (int i = 0; i < level; i++) {
  182.65 +                sb.append("    ");
  182.66 +            }
  182.67 +            sb.append(name);
  182.68 +            sb.append(" ");
  182.69 +            sb.append(info.dumpFlags(this));
  182.70 +            sb.append("\n");
  182.71 +        }
  182.72 +
  182.73 +        if (inner_free.size() > 0 || cellvars.size() > 0 || jy_paramcells.size() > 0 ||
  182.74 +                jy_npurecell != 0 /*|| cell != 0 || distance != 0 || up != null*/) {
  182.75 +            for (int i = 0; i < level; i++) {
  182.76 +                sb.append("    ");
  182.77 +            }
  182.78 +            sb.append("---------------------------------------------\n");
  182.79 +        }
  182.80 +
  182.81 +        if (inner_free.size() > 0) {
  182.82 +            List<String> sorted = new ArrayList<>();
  182.83 +            for (String s : inner_free.keySet()) {
  182.84 +                sorted.add(s + "=" + inner_free.get(s));
  182.85 +            }
  182.86 +            Collections.sort(sorted);
  182.87 +
  182.88 +            for (int i = 0; i < level; i++) {
  182.89 +                sb.append("    ");
  182.90 +            }
  182.91 +            sb.append("inner_free: {"); // NOI18N
  182.92 +            boolean first = true;
  182.93 +            for (String s : sorted) {
  182.94 +                if (first) {
  182.95 +                    first = false;
  182.96 +                } else {
  182.97 +                    sb.append(", "); // NOI18N
  182.98 +                }
  182.99 +                sb.append(s);
 182.100 +            }
 182.101 +            sb.append("}\n"); // NOI18N
 182.102 +        }
 182.103 +        if (cellvars.size() > 0) {
 182.104 +            Collections.sort(cellvars);
 182.105 +            for (int i = 0; i < level; i++) {
 182.106 +                sb.append("    ");
 182.107 +            }
 182.108 +            sb.append("cellvars: " + cellvars.toString() + "\n"); // TODO - sort
 182.109 +        }
 182.110 +        if (jy_paramcells.size() > 0) {
 182.111 +            Collections.sort(jy_paramcells);
 182.112 +            for (int i = 0; i < level; i++) {
 182.113 +                sb.append("    ");
 182.114 +            }
 182.115 +            sb.append("jy_paramcells: " + jy_paramcells.toString() + "\n"); // TODO - sort
 182.116 +        }
 182.117 +        if (jy_npurecell != 0) {
 182.118 +            for (int i = 0; i < level; i++) {
 182.119 +                sb.append("    ");
 182.120 +            }
 182.121 +            sb.append("jy_npurecell: " + jy_npurecell + "\n"); // TODO - sort
 182.122 +        }
 182.123 +        //if (cell != 0) {
 182.124 +        //    for(int i=0; i<level; i++) sb.append("    ");
 182.125 +        //    sb.append("cell: " + cell + "\n"); // TODO - sort
 182.126 +        //}
 182.127 +        //if (distance != 0) {
 182.128 +        //    for(int i=0; i<level; i++) sb.append("    ");
 182.129 +        //    sb.append("distance: " + distance + "\n"); // TODO - sort
 182.130 +        //}
 182.131 +        //if (up != null) {
 182.132 +        //    for(int i=0; i<level; i++) sb.append("    ");
 182.133 +        //    sb.append("up: " + up.scope_node);
 182.134 +        //}
 182.135 +
 182.136 +        if (attributes.size() > 0) {
 182.137 +            for (int i = 0; i < level; i++) {
 182.138 +                sb.append("    ");
 182.139 +            }
 182.140 +            sb.append("------ Attributes ---------------------------------------\n"); // NOI18N
 182.141 +            // Sort
 182.142 +            List<String> attributeNames = new ArrayList<>(attributes.keySet());
 182.143 +            Collections.sort(attributeNames);
 182.144 +            for (String attributeName : attributeNames) {
 182.145 +                for (int i = 0; i < level; i++) {
 182.146 +                    sb.append("    ");
 182.147 +                }
 182.148 +                sb.append(attributeName);
 182.149 +                sb.append(" : "); // NOI18N
 182.150 +                sb.append(attributes.get(attributeName));
 182.151 +                sb.append("\n"); // NOI18N
 182.152 +            }
 182.153 +        }
 182.154 +
 182.155 +        return sb.toString();
 182.156 +    }
 182.157 +
 182.158 +    public ScopeInfo(String name, PythonTree node, int level, int kind,
 182.159 +            int func_level, ArgListCompiler ac) {
 182.160 +        scope_name = name;
 182.161 +        scope_node = node;
 182.162 +        this.level = level;
 182.163 +        this.kind = kind;
 182.164 +        this.func_level = func_level;
 182.165 +        this.ac = ac;
 182.166 +    }
 182.167 +    public int kind;
 182.168 +    public boolean unqual_exec;
 182.169 +    public boolean exec;
 182.170 +    public boolean from_import_star;
 182.171 +    public boolean contains_ns_free_vars;
 182.172 +    public boolean generator;
 182.173 +    private boolean hasReturnWithValue;
 182.174 +    public int yield_count;
 182.175 +    public int max_with_count;
 182.176 +    public ArgListCompiler ac;
 182.177 +    public Map<String, SymInfo> tbl = new LinkedHashMap<>();
 182.178 +
 182.179 +    // define a separate dictionary for dynamic bounded variables
 182.180 +    public Map<String, SymInfo> attributes = new HashMap<>();
 182.181 +    public List<String> names = new ArrayList<>();
 182.182 +
 182.183 +    private void addAttributeEntry(String name, PythonTree node, int flags) {
 182.184 +        SymInfo info = attributes.get(name);
 182.185 +        if (info == null) {
 182.186 +            SymInfo entry = new SymInfo(flags);
 182.187 +            if (NameStyle.isPrivateName(name)) {
 182.188 +                entry.flags |= PRIVATE;
 182.189 +            } else if (NameStyle.isProtectedName(name)) {
 182.190 +                entry.flags |= PROTECTED;
 182.191 +            }
 182.192 +            entry.node = node;
 182.193 +            attributes.put(name, entry);
 182.194 +        }
 182.195 +    }
 182.196 +
 182.197 +    private void addToClassScope(String name, PythonTree node, boolean inConstructor) {
 182.198 +        int flags = CLASSSCOPE | BOUND | MEMBER;
 182.199 +        if (inConstructor) {
 182.200 +            flags |= BOUND_IN_CONSTRUCTOR;
 182.201 +        }
 182.202 +        addAttributeEntry(name, node, flags);
 182.203 +    }
 182.204 +
 182.205 +    public ScopeInfo getClassScope() {
 182.206 +        ScopeInfo cur = this;
 182.207 +        while ((cur != null) &&
 182.208 +                (!(cur.scope_node instanceof ClassDef))) {
 182.209 +            cur = cur.nested;
 182.210 +        }
 182.211 +        return cur;
 182.212 +    }
 182.213 +
 182.214 +    private boolean belongsToExprList(List<expr> types, expr cur) {
 182.215 +        return types != null && types.contains(cur);
 182.216 +    }
 182.217 +
 182.218 +    boolean isAttributeAssigment(AstPath path, Attribute attr) {
 182.219 +        PythonTree leaf = path.leaf();
 182.220 +        Assign assign = null;
 182.221 +        expr target = attr; // default to single
 182.222 +        if (leaf instanceof Assign) {
 182.223 +            assign = (Assign)leaf;
 182.224 +        } else if (leaf instanceof Tuple) {
 182.225 +            // check for tuple assignment
 182.226 +            Tuple tuple = (Tuple)leaf;
 182.227 +            PythonTree tupleParent = path.leafParent();
 182.228 +            if (belongsToExprList(tuple.getInternalElts(), attr)) {
 182.229 +                if (tupleParent instanceof Assign) {
 182.230 +                    assign = (Assign)tupleParent;
 182.231 +                    target = tuple; // tuple assignment target
 182.232 +                }
 182.233 +            }
 182.234 +        }
 182.235 +        // check if we got assignment
 182.236 +        if (assign == null) {
 182.237 +            return false;
 182.238 +        }
 182.239 +        if (belongsToExprList(assign.getInternalTargets(), target)) {
 182.240 +            return true;
 182.241 +        }
 182.242 +        return false;
 182.243 +    }
 182.244 +
 182.245 +    public void addAttribute(AstPath path, String name, PythonTree node) {
 182.246 +        // deeply check assignment context for attribute.
 182.247 +        Attribute curAttr = (Attribute)node;
 182.248 +
 182.249 +        if (curAttr.getInternalValue() instanceof Attribute) {
 182.250 +            // recursice attributes( x.y.z.w ) to be handled later
 182.251 +        } else if (curAttr.getInternalValue() instanceof Name) {
 182.252 +
 182.253 +            Name parentName = (Name)curAttr.getInternalValue();
 182.254 +
 182.255 +            ScopeInfo classScope = getClassScope();
 182.256 +            boolean inConstructor = false;
 182.257 +            String parName = parentName.getInternalId();
 182.258 +
 182.259 +            // for simplicity handle only at classScope in current source
 182.260 +            if (classScope != null) {
 182.261 +                // check for self or inherited parent name prefix
 182.262 +                if ((parName.equals("self")) ||
 182.263 +                        (PythonAstUtils.getParentClassFromNode(path, classScope.scope_node, parName) != null)) {
 182.264 +                    if (!(parName.equals("self"))) {
 182.265 +                        // check classname not overridden by local scope variable
 182.266 +                        if (tbl.get(parName) != null) {
 182.267 +                            return;
 182.268 +                        }
 182.269 +                    }
 182.270 +                    if (scope_name.equals("__init__") || scope_name.equals("__new__")) {
 182.271 +                        inConstructor = true; // set in constructor
 182.272 +                    }
 182.273 +                    //
 182.274 +                    // put in class scope
 182.275 +                    if (isAttributeAssigment(path, curAttr)) {
 182.276 +                        classScope.addToClassScope(name, node, inConstructor);
 182.277 +                    } else {
 182.278 +                        // store at current scope if parName is not overriding
 182.279 +                        // classname at current scope
 182.280 +                        int flags = CLASSSCOPE | READ;
 182.281 +                        addAttributeEntry(name, node, flags);
 182.282 +                    }
 182.283 +                }
 182.284 +            }
 182.285 +        }
 182.286 +    }
 182.287 +
 182.288 +    public int addGlobal(String name, PythonTree node) {
 182.289 +        // global kind = func vs. class
 182.290 +        int global = kind == CLASSSCOPE ? CLASS_GLOBAL : NGLOBAL;
 182.291 +        SymInfo info = tbl.get(name);
 182.292 +        if (info == null) {
 182.293 +            SymInfo entry = new SymInfo(global | BOUND);
 182.294 +            if (NameStyle.isPrivateName(name)) {
 182.295 +                entry.flags |= PRIVATE;
 182.296 +            } else if (NameStyle.isProtectedName(name)) {
 182.297 +                entry.flags |= PROTECTED;
 182.298 +            }
 182.299 +            entry.node = node;
 182.300 +            tbl.put(name, entry);
 182.301 +            return -1;
 182.302 +        }
 182.303 +        int prev = info.flags;
 182.304 +        info.flags |= global | BOUND;
 182.305 +        return prev;
 182.306 +    }
 182.307 +    public int local = 0;
 182.308 +
 182.309 +    public void addParam(String name, PythonTree node) {
 182.310 +        SymInfo entry = new SymInfo(PARAM | BOUND, local++);
 182.311 +        entry.node = node;
 182.312 +        tbl.put(name, entry);
 182.313 +        names.add(name);
 182.314 +    }
 182.315 +
 182.316 +    // <netbeans>
 182.317 +    public boolean isUnused(String name) {
 182.318 +        SymInfo info = tbl.get(name);
 182.319 +        if (info != null) {
 182.320 +            return info.isUnused(this);
 182.321 +        }
 182.322 +        return false;
 182.323 +    }
 182.324 +
 182.325 +    public boolean isParameter(String name) {
 182.326 +        SymInfo info = tbl.get(name);
 182.327 +        if (info != null) {
 182.328 +            return info.isParameter();
 182.329 +        }
 182.330 +        return false;
 182.331 +    }
 182.332 +    // </netbeans>
 182.333 +
 182.334 +    public void markFromParam() {
 182.335 +        for (SymInfo info : tbl.values()) {
 182.336 +            info.flags |= FROM_PARAM;
 182.337 +        }
 182.338 +    }
 182.339 +
 182.340 +    public SymInfo addBound(String name, PythonTree node) {
 182.341 +        SymInfo info = tbl.get(name);
 182.342 +        if (info == null) {
 182.343 +            info = new SymInfo(BOUND);
 182.344 +            if (NameStyle.isPrivateName(name)) {
 182.345 +                info.flags |= PRIVATE;
 182.346 +            } else if (NameStyle.isProtectedName(name)) {
 182.347 +                info.flags |= PROTECTED;
 182.348 +            }
 182.349 +            tbl.put(name, info);
 182.350 +            info.node = node;
 182.351 +            return info;
 182.352 +        }
 182.353 +        info.flags |= BOUND;
 182.354 +
 182.355 +        return info;
 182.356 +    }
 182.357 +
 182.358 +    public SymInfo addUsed(String name, PythonTree node) {
 182.359 +        SymInfo info = tbl.get(name);
 182.360 +        if (info == null) {
 182.361 +            // <netbeans>
 182.362 +            info = new SymInfo(0);
 182.363 +            tbl.put(name, info);
 182.364 +            info.node = node;
 182.365 +        }
 182.366 +        info.flags |= READ;
 182.367 +
 182.368 +        return info;
 182.369 +        // </netbeans>
 182.370 +    }
 182.371 +
 182.372 +
 182.373 +    // <netbeans>
 182.374 +    void markCall(String name) {
 182.375 +        SymInfo entry = tbl.get(name);
 182.376 +        if (entry != null) {
 182.377 +            entry.flags |= CALLED;
 182.378 +        }
 182.379 +    }
 182.380 +    // </netbeans>
 182.381 +    private final static String PRESENT = new String("PRESENT");
 182.382 +    public HashMap<String, String> inner_free = new HashMap<>();
 182.383 +    public List<String> cellvars = new ArrayList<>();
 182.384 +    public List<String> jy_paramcells = new ArrayList<>();
 182.385 +    public int jy_npurecell;
 182.386 +    public int cell, distance;
 182.387 +    public ScopeInfo up;
 182.388 +    public ScopeInfo nested;
 182.389 +
 182.390 +    //Resolve the names used in the given scope, and mark any freevars used in the up scope
 182.391 +    public void cook(ScopeInfo up, int distance, SymbolTable ctxt) throws Exception {
 182.392 +        if (up == null) {
 182.393 +            return; // top level => nop
 182.394 +        }
 182.395 +        this.up = up;
 182.396 +        this.distance = distance;
 182.397 +        boolean func = kind == FUNCSCOPE;
 182.398 +        List<String> purecells = new ArrayList<>();
 182.399 +        cell = 0;
 182.400 +        boolean some_inner_free = inner_free.size() > 0;
 182.401 +
 182.402 +        for (String name : inner_free.keySet()) {
 182.403 +
 182.404 +            SymInfo info = tbl.get(name);
 182.405 +            if (info == null) {
 182.406 +                tbl.put(name, new SymInfo(FREE));
 182.407 +                continue;
 182.408 +            }
 182.409 +            int flags = info.flags;
 182.410 +            if (func) {
 182.411 +                // not func global and bound ?
 182.412 +                if ((flags & NGLOBAL) == 0 && (flags & BOUND) != 0) {
 182.413 +                    info.flags |= CELL;
 182.414 +                    if ((info.flags & PARAM) != 0) {
 182.415 +                        jy_paramcells.add(name);
 182.416 +                    }
 182.417 +                    cellvars.add(name);
 182.418 +                    info.env_index = cell++;
 182.419 +                    if ((flags & PARAM) == 0) {
 182.420 +                        purecells.add(name);
 182.421 +                    }
 182.422 +                    continue;
 182.423 +                }
 182.424 +            } else {
 182.425 +                info.flags |= FREE;
 182.426 +            }
 182.427 +        }
 182.428 +        boolean some_free = false;
 182.429 +
 182.430 +        boolean nested = up.kind != TOPSCOPE;
 182.431 +        for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
 182.432 +            String name = entry.getKey();
 182.433 +            SymInfo info = entry.getValue();
 182.434 +            int flags = info.flags;
 182.435 +            if (nested && (flags & FREE) != 0) {
 182.436 +                up.inner_free.put(name, PRESENT);
 182.437 +            }
 182.438 +            if ((flags & (GLOBAL | PARAM | CELL)) == 0) {
 182.439 +                if ((flags & BOUND) != 0) { // ?? only func
 182.440 +                    // System.err.println("local: "+name);
 182.441 +                    names.add(name);
 182.442 +                    info.locals_index = local++;
 182.443 +                    continue;
 182.444 +                }
 182.445 +                info.flags |= FREE;
 182.446 +                some_free = true;
 182.447 +                if (nested) {
 182.448 +                    up.inner_free.put(name, PRESENT);
 182.449 +                }
 182.450 +            }
 182.451 +
 182.452 +            // <netbeans>
 182.453 +            if ((info.flags & FREE) != 0) {
 182.454 +                // Mark definition symbol as read as well
 182.455 +                ScopeInfo curr = up;
 182.456 +                while (curr != null) {
 182.457 +                    SymInfo s = curr.tbl.get(name);
 182.458 +                    if (s != null && ((s.flags & BOUND) != 0)) {
 182.459 +                        s.flags |= READ;
 182.460 +                        s.flags |= (info.flags & (CALLED));
 182.461 +                        break;
 182.462 +                    }
 182.463 +                    curr = curr.up;
 182.464 +                    while (curr != null && curr.kind == CLASSSCOPE) {
 182.465 +                        curr = curr.up;
 182.466 +                    }
 182.467 +                }
 182.468 +            }
 182.469 +
 182.470 +            // </netbeans>
 182.471 +        }
 182.472 +        if ((jy_npurecell = purecells.size()) > 0) {
 182.473 +            int sz = purecells.size();
 182.474 +            for (int i = 0; i < sz; i++) {
 182.475 +                names.add(purecells.get(i));
 182.476 +            }
 182.477 +        }
 182.478 +
 182.479 +        if (some_free && nested) {
 182.480 +            up.contains_ns_free_vars = true;
 182.481 +        }
 182.482 +        // XXX - this doesn't catch all cases - may depend subtly
 182.483 +        // on how visiting NOW works with antlr compared to javacc
 182.484 +        if ((unqual_exec || from_import_star)) {
 182.485 +            if (some_inner_free) {
 182.486 +                dynastuff_trouble(true, ctxt);
 182.487 +            } else if (func_level > 1 && some_free) {
 182.488 +                dynastuff_trouble(false, ctxt);
 182.489 +            }
 182.490 +        }
 182.491 +
 182.492 +    }
 182.493 +
 182.494 +    private void dynastuff_trouble(boolean inner_free,
 182.495 +            SymbolTable ctxt) throws Exception {
 182.496 +        String illegal;
 182.497 +        if (unqual_exec && from_import_star) {
 182.498 +            illegal = "function '" + scope_name +
 182.499 +                    "' uses import * and bare exec, which are illegal";
 182.500 +        } else if (unqual_exec) {
 182.501 +            illegal = "unqualified exec is not allowed in function '" +
 182.502 +                    scope_name + "'";
 182.503 +        } else {
 182.504 +            illegal = "import * is not allowed in function '" + scope_name + "'";
 182.505 +        }
 182.506 +        String why;
 182.507 +        if (inner_free) {
 182.508 +            why = " because it contains a function with free variables";
 182.509 +        } else {
 182.510 +            why = " because it contains free variables";
 182.511 +        }
 182.512 +        ctxt.error(illegal + why, true, scope_node);
 182.513 +    }
 182.514 +    public List<String> freevars = new ArrayList<>();
 182.515 +
 182.516 +    /**
 182.517 +     * setup the closure on this scope using the scope passed into cook as up as
 182.518 +     * the containing scope
 182.519 +     */
 182.520 +    public void setup_closure() {
 182.521 +        setup_closure(up);
 182.522 +    }
 182.523 +
 182.524 +    /**
 182.525 +     * setup the closure on this scope using the passed in scope. This is used
 182.526 +     * by jythonc to setup its closures.
 182.527 +     */
 182.528 +    public void setup_closure(ScopeInfo up) {
 182.529 +        int free = cell; // env = cell...,free...
 182.530 +        Map<String, SymInfo> up_tbl = up.tbl;
 182.531 +        boolean nested = up.kind != TOPSCOPE;
 182.532 +        for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
 182.533 +            String name = entry.getKey();
 182.534 +            SymInfo info = entry.getValue();
 182.535 +            int flags = info.flags;
 182.536 +            if ((flags & FREE) != 0) {
 182.537 +                SymInfo up_info = up_tbl.get(name);
 182.538 +                // ?? differs from CPython -- what is the intended behaviour?
 182.539 +                if (up_info != null) {
 182.540 +                    int up_flags = up_info.flags;
 182.541 +                    if ((up_flags & (CELL | FREE)) != 0) {
 182.542 +                        info.env_index = free++;
 182.543 +                        freevars.add(name);
 182.544 +                        continue;
 182.545 +                    }
 182.546 +                    // ! func global affect nested scopes
 182.547 +                    if (nested && (up_flags & NGLOBAL) != 0) {
 182.548 +                        info.flags = NGLOBAL | BOUND;
 182.549 +                        continue;
 182.550 +                    }
 182.551 +                }
 182.552 +                info.flags &= ~FREE;
 182.553 +            }
 182.554 +        }
 182.555 +
 182.556 +    }
 182.557 +
 182.558 +    @Override
 182.559 +    public String toString() {
 182.560 +        return "ScopeInfo[" + scope_name + " " + kind + "]@" +
 182.561 +                System.identityHashCode(this);
 182.562 +    }
 182.563 +
 182.564 +    public void defineAsGenerator(expr node) {
 182.565 +        generator = true;
 182.566 +        if (hasReturnWithValue) {
 182.567 +            throw new ParseException("'return' with argument " +
 182.568 +                    "inside generator", node);
 182.569 +        }
 182.570 +    }
 182.571 +
 182.572 +    public void noteReturnValue(Return node) {
 182.573 +        if (generator) {
 182.574 +            throw new ParseException("'return' with argument " +
 182.575 +                    "inside generator", node);
 182.576 +        }
 182.577 +        hasReturnWithValue = true;
 182.578 +    }
 182.579 +}
   183.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   183.2 +++ b/python.source/src/org/netbeans/modules/python/source/scopes/ScopesCompiler.java	Sun Sep 13 11:47:42 2015 +0200
   183.3 @@ -0,0 +1,641 @@
   183.4 +// (C) Copyright 2001 Samuele Pedroni
   183.5 +package org.netbeans.modules.python.source.scopes;
   183.6 +
   183.7 +import java.util.ArrayList;
   183.8 +import java.util.List;
   183.9 +import java.util.Map;
  183.10 +import java.util.Set;
  183.11 +import java.util.Stack;
  183.12 +import org.netbeans.modules.python.source.AstPath;
  183.13 +import org.openide.util.Exceptions;
  183.14 +import org.python.antlr.PythonTree;
  183.15 +import org.python.antlr.Visitor;
  183.16 +import org.python.antlr.ast.Assign;
  183.17 +import org.python.antlr.ast.Attribute;
  183.18 +import org.python.antlr.ast.Call;
  183.19 +import org.python.antlr.ast.ClassDef;
  183.20 +import org.python.antlr.ast.Delete;
  183.21 +import org.python.antlr.ast.Exec;
  183.22 +import org.python.antlr.ast.Expression;
  183.23 +import org.python.antlr.ast.FunctionDef;
  183.24 +import org.python.antlr.ast.GeneratorExp;
  183.25 +import org.python.antlr.ast.Global;
  183.26 +import org.python.antlr.ast.Import;
  183.27 +import org.python.antlr.ast.ImportFrom;
  183.28 +import org.python.antlr.ast.Interactive;
  183.29 +import org.python.antlr.ast.Lambda;
  183.30 +import org.python.antlr.ast.ListComp;
  183.31 +import org.python.antlr.ast.Name;
  183.32 +import org.python.antlr.ast.Return;
  183.33 +import org.python.antlr.ast.Str;
  183.34 +import org.python.antlr.ast.With;
  183.35 +import org.python.antlr.ast.Yield;
  183.36 +import org.python.antlr.ast.alias;
  183.37 +import org.python.antlr.ast.arguments;
  183.38 +import org.python.antlr.base.expr;
  183.39 +import org.python.antlr.ast.expr_contextType;
  183.40 +import org.python.antlr.base.stmt;
  183.41 +
  183.42 +/** 
  183.43 + * Based on org.python.compiler.ScopesCompiler in Jython
  183.44 + *
  183.45 + * Modifications I've made:
  183.46 + * - Methods for finding all the free variables
  183.47 + * - Methods for identifying unused bound variables
  183.48 + * - Track whether symbols are referenced as calls or not
  183.49 + *   (so I can determine whether to look in the index for
  183.50 + *    functions or data etc. when trying to resolve imports)
  183.51 + * - Track variable reads/writes
  183.52 + * - Track imports etc.
  183.53 + * - Add nodes to each SymInfo
  183.54 + * - Replace old style Java (Hashtable, Vector, implements ScopeConstants) with
  183.55 + *   modern Java (HashMap, ArrayList, import static)
  183.56 + * 
  183.57 + */
  183.58 +@SuppressWarnings("unchecked")
  183.59 +public class ScopesCompiler extends Visitor implements ScopeConstants {
  183.60 +    private SymbolTable symbolTable;
  183.61 +    private Stack scopes;
  183.62 +    private ScopeInfo cur = null;
  183.63 +    private Map<PythonTree, ScopeInfo> nodeScopes;
  183.64 +    private int level = 0;
  183.65 +    private int func_level = 0;
  183.66 +    private List<Import> imports;
  183.67 +    private List<PythonTree> mainImports;
  183.68 +    private List<ImportFrom> importsFrom;
  183.69 +    private Set<PythonTree> topLevelImports;
  183.70 +    private PythonTree root;
  183.71 +    private PythonTree parent;
  183.72 +    private AstPath path = new AstPath();
  183.73 +    /** List of symbols registered via __all__ = [ "foo", "bar" ] or __all__.extend() or __all__.append() */
  183.74 +    private List<Str> publicSymbols;
  183.75 +    /** Set to true if we encountered manipulation on __all__ that I don't understand */
  183.76 +    private boolean invalidPublicSymbols;
  183.77 +
  183.78 +    public ScopesCompiler(SymbolTable symbolTable, Map<PythonTree, ScopeInfo> nodeScopes, PythonTree root,
  183.79 +            List<Import> imports, List<ImportFrom> importsFrom, List<PythonTree> mainImports, Set<PythonTree> topLevelImports) {
  183.80 +        this.symbolTable = symbolTable;
  183.81 +        this.nodeScopes = nodeScopes;
  183.82 +        scopes = new Stack();
  183.83 +        this.root = root;
  183.84 +
  183.85 +        this.imports = imports;
  183.86 +        this.importsFrom = importsFrom;
  183.87 +        this.mainImports = mainImports;
  183.88 +        this.topLevelImports = topLevelImports;
  183.89 +    }
  183.90 +
  183.91 +    @Override
  183.92 +    public void traverse(PythonTree node) throws Exception {
  183.93 +        // Jython's parser often doesn't set the parent references correctly
  183.94 +        // so try to fix that here
  183.95 +        node.setParent(parent);
  183.96 +
  183.97 +        PythonTree oldParent = parent;
  183.98 +        parent = node;
  183.99 +
 183.100 +        path.descend(node);
 183.101 +        super.traverse(node);
 183.102 +        parent = oldParent;
 183.103 +        path.ascend();
 183.104 +    }
 183.105 +
 183.106 +    public void beginScope(String name, int kind, PythonTree node,
 183.107 +            ArgListCompiler ac) {
 183.108 +        if (cur != null) {
 183.109 +            scopes.push(cur);
 183.110 +        }
 183.111 +        if (kind == FUNCSCOPE) {
 183.112 +            func_level++;
 183.113 +        }
 183.114 +        cur = new ScopeInfo(name, node, level++, kind, func_level, ac);
 183.115 +        nodeScopes.put(node, cur);
 183.116 +    }
 183.117 +
 183.118 +    public void endScope() throws Exception {
 183.119 +        if (cur.kind == FUNCSCOPE) {
 183.120 +            func_level--;
 183.121 +        }
 183.122 +        level--;
 183.123 +        ScopeInfo up = null;
 183.124 +        if (!scopes.empty()) {
 183.125 +            up = (ScopeInfo)scopes.pop();
 183.126 +        }
 183.127 +        //Go into the stack to find a non class containing scope to use making the closure
 183.128 +        //See PEP 227
 183.129 +        int dist = 1;
 183.130 +        ScopeInfo referenceable = up;
 183.131 +        for (int i = scopes.size() - 1; i >= 0 && referenceable.kind == CLASSSCOPE; i--, dist++) {
 183.132 +            referenceable = ((ScopeInfo)scopes.get(i));
 183.133 +        }
 183.134 +        cur.cook(referenceable, dist, symbolTable);
 183.135 +//        cur.dump(); // debug
 183.136 +        cur = up;
 183.137 +    }
 183.138 +
 183.139 +    public void parse() {
 183.140 +        try {
 183.141 +            visit(root);
 183.142 +        } catch (Throwable t) {
 183.143 +            Exceptions.printStackTrace(t);
 183.144 +            //throw org.python.core.ParserFacade.fixParseError(null, t,
 183.145 +            //        code_compiler.getFilename());
 183.146 +        }
 183.147 +    }
 183.148 +
 183.149 +    @Override
 183.150 +    public Object visitInteractive(Interactive node) throws Exception {
 183.151 +        beginScope("<single-top>", TOPSCOPE, node, null);
 183.152 +        PythonTree oldParent = parent;
 183.153 +        parent = node;
 183.154 +        suite(node.getInternalBody());
 183.155 +        parent = oldParent;
 183.156 +        endScope();
 183.157 +        return null;
 183.158 +    }
 183.159 +
 183.160 +    @Override
 183.161 +    public Object visitModule(org.python.antlr.ast.Module node)
 183.162 +            throws Exception {
 183.163 +        List<stmt> body = node.getInternalBody();
 183.164 +        if (body != null && body.size() > 0) {
 183.165 +            boolean foundFirst = false;
 183.166 +            for (stmt stmt : body) {
 183.167 +                if (stmt != null) {
 183.168 +                    if (stmt instanceof Import || stmt instanceof ImportFrom) {
 183.169 +                        if (!foundFirst) {
 183.170 +                            foundFirst = true;
 183.171 +                        }
 183.172 +                        mainImports.add(stmt);
 183.173 +                    } else if (foundFirst) {
 183.174 +                        break;
 183.175 +                    }
 183.176 +                }
 183.177 +            }
 183.178 +        }
 183.179 +
 183.180 +        beginScope("<file-top>", TOPSCOPE, node, null);
 183.181 +
 183.182 +        PythonTree oldParent = parent;
 183.183 +        parent = node;
 183.184 +        suite(node.getInternalBody());
 183.185 +        parent = oldParent;
 183.186 +
 183.187 +        endScope();
 183.188 +        return null;
 183.189 +    }
 183.190 +
 183.191 +    @Override
 183.192 +    public Object visitExpression(Expression node) throws Exception {
 183.193 +        beginScope("<eval-top>", TOPSCOPE, node, null);
 183.194 +        visit(new Return(node, node.getInternalBody()));
 183.195 +        endScope();
 183.196 +        return null;
 183.197 +    }
 183.198 +
 183.199 +    private void def(String name, int extraFlags, PythonTree node) {
 183.200 +        SymInfo info = cur.addBound(name, node);
 183.201 +        // <netbeans>
 183.202 +        info.flags |= (DEF | extraFlags);
 183.203 +        info.node = node;
 183.204 +        // </netbeans>
 183.205 +    }
 183.206 +
 183.207 +    @Override
 183.208 +    public Object visitAssign(Assign node) throws Exception {
 183.209 +        List<expr> targets = node.getInternalTargets();
 183.210 +        if (targets != null && targets.size() == 1 && targets.get(0) instanceof Name) {
 183.211 +            Name lhs = (Name)targets.get(0);
 183.212 +            if ("__all__".equals(lhs.getInternalId())) { // NOI18N
 183.213 +                expr nodeValue = node.getInternalValue();
 183.214 +                if (!invalidPublicSymbols && nodeValue instanceof org.python.antlr.ast.List) {
 183.215 +                    org.python.antlr.ast.List allList = (org.python.antlr.ast.List)nodeValue;
 183.216 +                    if (allList != null) {
 183.217 +                        for (expr expr : allList.getInternalElts()) {
 183.218 +                            if (expr instanceof Str) {
 183.219 +                                Str str = (Str)expr;
 183.220 +                                if (publicSymbols == null) {
 183.221 +                                    publicSymbols = new ArrayList<>();
 183.222 +                                }
 183.223 +                                publicSymbols.add(str);
 183.224 +                            } else {
 183.225 +                                invalidPublicSymbols = true;
 183.226 +                            }
 183.227 +                        }
 183.228 +                    }
 183.229 +                } else {
 183.230 +                    invalidPublicSymbols = true;
 183.231 +                }
 183.232 +            }
 183.233 +        }
 183.234 +
 183.235 +        if (targets.size() > 0) {
 183.236 +            List<Name> names = new ArrayList<>(targets.size());
 183.237 +            boolean valid = true;
 183.238 +            for (expr et : targets) {
 183.239 +                if (et instanceof Name) {
 183.240 +                    Name name = (Name)et;
 183.241 +                    names.add(name);
 183.242 +                } else {
 183.243 +                    valid = false;
 183.244 +                }
 183.245 +            }
 183.246 +            if (valid) {
 183.247 +                expr nodeValue = node.getInternalValue();
 183.248 +                if (nodeValue instanceof Name) {
 183.249 +                    Name value = (Name)nodeValue;
 183.250 +
 183.251 +                    SymInfo rhsSym = cur.tbl.get(value.getInternalId());
 183.252 +                    if (rhsSym != null && rhsSym.isDef()) {
 183.253 +                        for (Name name : names) {
 183.254 +                            visitName(name);
 183.255 +                            SymInfo sym = cur.tbl.get(name.getInternalId());
 183.256 +                            if (sym != null) {
 183.257 +                                sym.flags |= ALIAS;
 183.258 +                                sym.flags |= (rhsSym.flags & (CLASS | FUNCTION));
 183.259 +                                sym.node = rhsSym.node;
 183.260 +                            }
 183.261 +                        }
 183.262 +                    }
 183.263 +                }
 183.264 +            }
 183.265 +        }
 183.266 +
 183.267 +        return super.visitAssign(node);
 183.268 +    }
 183.269 +
 183.270 +    @Override
 183.271 +    public Object visitFunctionDef(FunctionDef node) throws Exception {
 183.272 +        def(node.getInternalName(), FUNCTION, node);
 183.273 +        ArgListCompiler ac = new ArgListCompiler(symbolTable);
 183.274 +        ac.visitArgs(node.getInternalArgs());
 183.275 +
 183.276 +        List<expr> defaults = ac.getDefaults();
 183.277 +        for (int i = 0; i < defaults.size(); i++) {
 183.278 +            visit(defaults.get(i));
 183.279 +        }
 183.280 +
 183.281 +        List<expr> decs = node.getInternalDecorator_list();
 183.282 +        for (int i = decs.size() - 1; i >= 0; i--) {
 183.283 +            visit(decs.get(i));
 183.284 +        }
 183.285 +
 183.286 +        ScopeInfo parentScope = cur;
 183.287 +        beginScope(node.getInternalName(), FUNCSCOPE, node, ac);
 183.288 +        cur.nested = parentScope;
 183.289 +
 183.290 +        int n = ac.names.size();
 183.291 +        for (int i = 0; i < n; i++) {
 183.292 +            cur.addParam(ac.names.get(i), ac.nodes.get(i));
 183.293 +        }
 183.294 +        for (int i = 0; i < ac.init_code.size(); i++) {
 183.295 +            visit(ac.init_code.get(i));
 183.296 +        }
 183.297 +        cur.markFromParam();
 183.298 +
 183.299 +        PythonTree oldParent = parent;
 183.300 +        parent = node;
 183.301 +        suite(node.getInternalBody());
 183.302 +        parent = oldParent;
 183.303 +
 183.304 +        endScope();
 183.305 +        return null;
 183.306 +    }
 183.307 +
 183.308 +    @Override
 183.309 +    public Object visitLambda(Lambda node) throws Exception {
 183.310 +        ArgListCompiler ac = new ArgListCompiler(symbolTable);
 183.311 +        ac.visitArgs(node.getInternalArgs());
 183.312 +
 183.313 +        List<expr> defaults = ac.getDefaults();
 183.314 +        for (expr expr : defaults) {
 183.315 +            visit(expr);
 183.316 +        }
 183.317 +
 183.318 +        beginScope("<lambda>", FUNCSCOPE, node, ac);
 183.319 +        assert ac.names.size() == ac.nodes.size();
 183.320 +        for (int i = 0; i < ac.names.size(); i++) {
 183.321 +            cur.addParam(ac.names.get(i), ac.nodes.get(i));
 183.322 +        }
 183.323 +        for (Object o : ac.init_code) {
 183.324 +            visit((stmt)o);
 183.325 +        }
 183.326 +        cur.markFromParam();
 183.327 +        visit(node.getInternalBody());
 183.328 +        endScope();
 183.329 +        return null;
 183.330 +    }
 183.331 +
 183.332 +    public void suite(List<stmt> stmts) throws Exception {
 183.333 +        if (stmts != null) {
 183.334 +            for (int i = 0; i < stmts.size(); i++) {
 183.335 +                stmt s = stmts.get(i);
 183.336 +                path.descend(s);
 183.337 +                visit(s);
 183.338 +                path.ascend();
 183.339 +            }
 183.340 +        }
 183.341 +    }
 183.342 +
 183.343 +    @Override
 183.344 +    public Object visitImport(Import node) throws Exception {
 183.345 +        if (parent == root) {
 183.346 +            topLevelImports.add(node);
 183.347 +        }
 183.348 +        imports.add(node);
 183.349 +
 183.350 +        List<alias> names = node.getInternalNames();
 183.351 +        if (names != null) {
 183.352 +            for (alias alias : names) {
 183.353 +                String asname = alias.getInternalAsname();
 183.354 +                if (asname != null) {
 183.355 +                    SymInfo entry = cur.addBound(asname, node);
 183.356 +                    entry.flags |= IMPORTED;
 183.357 +                } else {
 183.358 +                    String name = alias.getInternalName();
 183.359 +                    if (name.indexOf('.') > 0) {
 183.360 +                        name = name.substring(0, name.indexOf('.'));
 183.361 +                    }
 183.362 +                    SymInfo entry = cur.addBound(name, node);
 183.363 +                    entry.flags |= IMPORTED;
 183.364 +                }
 183.365 +            }
 183.366 +        }
 183.367 +        return null;
 183.368 +    }
 183.369 +
 183.370 +    @Override
 183.371 +    public Object visitImportFrom(ImportFrom node) throws Exception {
 183.372 +        if (parent == root) {
 183.373 +            topLevelImports.add(node);
 183.374 +        }
 183.375 +        importsFrom.add(node);
 183.376 +
 183.377 +        //Future.checkFromFuture(node); // future stmt support
 183.378 +        List<alias> names = node.getInternalNames();
 183.379 +        if (names == null || names.size() == 0) {
 183.380 +            cur.from_import_star = true;
 183.381 +            return null;
 183.382 +        }
 183.383 +        for (alias alias : names) {
 183.384 +            String asname = alias.getInternalAsname();
 183.385 +            if (asname != null) {
 183.386 +                SymInfo entry = cur.addBound(asname, node);
 183.387 +                entry.flags |= IMPORTED;
 183.388 +            } else {
 183.389 +                SymInfo entry = cur.addBound(alias.getInternalName(), node);
 183.390 +                entry.flags |= IMPORTED;
 183.391 +            }
 183.392 +        }
 183.393 +        return null;
 183.394 +    }
 183.395 +
 183.396 +    @Override
 183.397 +    public Object visitGlobal(Global node) throws Exception {
 183.398 +        List<String> names = node.getInternalNames();
 183.399 +        for (String name : names) {
 183.400 +            int prev = cur.addGlobal(name, node);
 183.401 +            if (prev >= 0) {
 183.402 +                if ((prev & FROM_PARAM) != 0) {
 183.403 +                    symbolTable.error("name '" + name + "' is local and global", true, node);
 183.404 +                }
 183.405 +                if ((prev & GLOBAL) != 0) {
 183.406 +                    continue;
 183.407 +                }
 183.408 +                String what;
 183.409 +                if ((prev & BOUND) != 0) {
 183.410 +                    what = "assignment";
 183.411 +                } else {
 183.412 +                    what = "use";
 183.413 +                }
 183.414 +                symbolTable.error("name '" + name + "' declared global after " + what, false, node);
 183.415 +            }
 183.416 +        }
 183.417 +        return null;
 183.418 +    }
 183.419 +
 183.420 +    @Override
 183.421 +    public Object visitExec(Exec node) throws Exception {
 183.422 +        cur.exec = true;
 183.423 +        if (node.getInternalGlobals() == null && node.getInternalLocals() == null) {
 183.424 +            cur.unqual_exec = true;
 183.425 +        }
 183.426 +        traverse(node);
 183.427 +        return null;
 183.428 +    }
 183.429 +
 183.430 +    @Override
 183.431 +    public Object visitClassDef(ClassDef node) throws Exception {
 183.432 +        String name = node.getInternalName();
 183.433 +        def(name, CLASS, node);
 183.434 +        List<expr> bases = node.getInternalBases();
 183.435 +        if (bases != null) {
 183.436 +            for (expr expr : bases) {
 183.437 +                visit(expr);
 183.438 +            }
 183.439 +        }
 183.440 +        ScopeInfo parentScope = cur;
 183.441 +        beginScope(name, CLASSSCOPE, node, null);
 183.442 +        cur.nested = parentScope;
 183.443 +        PythonTree oldParent = parent;
 183.444 +        parent = node;
 183.445 +        suite(node.getInternalBody());
 183.446 +        parent = oldParent;
 183.447 +        endScope();
 183.448 +        return null;
 183.449 +    }
 183.450 +
 183.451 +    @Override
 183.452 +    public Object visitName(Name node) throws Exception {
 183.453 +        // Jython's parser doesn't always initialize the parent references correctly;
 183.454 +        // try to correct that here.
 183.455 +        node.setParent(parent);
 183.456 +
 183.457 +        String name = node.getInternalId();
 183.458 +        if (node.getInternalCtx() != expr_contextType.Load) {
 183.459 +            if (name.equals("__debug__")) {
 183.460 +                symbolTable.error("can not assign to __debug__", true, node);
 183.461 +            }
 183.462 +            cur.addBound(name, node);
 183.463 +        } else {
 183.464 +            cur.addUsed(name, node);
 183.465 +        }
 183.466 +        return null;
 183.467 +    }
 183.468 +
 183.469 +    // <netbeans>
 183.470 +    @Override
 183.471 +    public Object visitCall(Call node) throws Exception {
 183.472 +        Object ret = super.visitCall(node);
 183.473 +
 183.474 +        expr func = node.getInternalFunc();
 183.475 +        if (func instanceof Name) {
 183.476 +            Name name = (Name)func;
 183.477 +            cur.markCall(name.getInternalId());
 183.478 +        } else if (func instanceof Attribute) {
 183.479 +            Attribute attr = (Attribute)func;
 183.480 +            if (cur.attributes != null) {
 183.481 +                SymInfo funcSymbol = cur.attributes.get(attr.getInternalAttr());
 183.482 +                if (funcSymbol != null) {
 183.483 +                    funcSymbol.flags |= FUNCTION | CALLED; // mark as func/method call
 183.484 +                }
 183.485 +            }
 183.486 +
 183.487 +        }
 183.488 +
 183.489 +        return ret;
 183.490 +    }
 183.491 +
 183.492 +    @Override
 183.493 +    public Object visitDelete(Delete node) throws Exception {
 183.494 +        for (expr et : node.getInternalTargets()) {
 183.495 +            if (et instanceof Name) {
 183.496 +                String name = ((Name)et).getInternalId();
 183.497 +                cur.addUsed(name, node);
 183.498 +            }
 183.499 +        }
 183.500 +
 183.501 +        return super.visitDelete(node);
 183.502 +    }
 183.503 +
 183.504 +    @Override
 183.505 +    public Object visitAttribute(Attribute node) throws Exception {
 183.506 +        if (parent instanceof Call && node.getInternalValue() instanceof Name &&
 183.507 +                ("__all__".equals(((Name)node.getInternalValue()).getInternalId()))) {
 183.508 +            // If you for example call
 183.509 +            //    __all__.extend("foo")
 183.510 +            // or
 183.511 +            //    __all__.append("bar")
 183.512 +            // then I don't want to try to analyze __all__
 183.513 +            String nodeAttr = node.getInternalAttr();
 183.514 +            if ("extend".equals(nodeAttr) || "append".equals(nodeAttr)) { // NOI18N
 183.515 +                Call call = (Call)parent;
 183.516 +                List<expr> callArgs = call.getInternalArgs();
 183.517 +                if (callArgs != null) {
 183.518 +                    for (expr expr : callArgs) {
 183.519 +                        if (expr instanceof Str) {
 183.520 +                            if (publicSymbols == null) {
 183.521 +                                publicSymbols = new ArrayList<>();
 183.522 +                            }
 183.523 +                            publicSymbols.add((Str)expr);
 183.524 +                        } else if (expr instanceof org.python.antlr.ast.List) {
 183.525 +                            org.python.antlr.ast.List list = (org.python.antlr.ast.List)expr;
 183.526 +                            if (list != null) {
 183.527 +                                List<expr> elts = list.getInternalElts();
 183.528 +                                if (elts != null) {
 183.529 +                                    for (expr ex : elts) {
 183.530 +                                        if (ex instanceof Str) {
 183.531 +                                            Str str = (Str)ex;
 183.532 +                                            if (publicSymbols == null) {
 183.533 +                                                publicSymbols = new ArrayList<>();
 183.534 +                                            }
 183.535 +                                            publicSymbols.add(str);
 183.536 +                                        } else {
 183.537 +                                            invalidPublicSymbols = true;
 183.538 +                                        }
 183.539 +                                    }
 183.540 +                                }
 183.541 +                            }
 183.542 +                        } else {
 183.543 +                            invalidPublicSymbols = true;
 183.544 +                            break;
 183.545 +                        }
 183.546 +                    }
 183.547 +                }
 183.548 +            } else {
 183.549 +                invalidPublicSymbols = true;
 183.550 +            }
 183.551 +        } else {
 183.552 +            String nodeAttr = node.getInternalAttr();
 183.553 +            if (nodeAttr != null) {
 183.554 +                cur.addAttribute(path, nodeAttr, node);
 183.555 +            }
 183.556 +        }
 183.557 +        return super.visitAttribute(node);
 183.558 +    }
 183.559 +    // </netbeans>
 183.560 +
 183.561 +    @Override
 183.562 +    public Object visitListComp(ListComp node) throws Exception {
 183.563 +        String tmp = "_[" + node.getLine() + "_" + node.getCharPositionInLine() + "]";
 183.564 +        cur.addBound(tmp, node);
 183.565 +        traverse(node);
 183.566 +        return null;
 183.567 +    }
 183.568 +
 183.569 +    @Override
 183.570 +    public Object visitYield(Yield node) throws Exception {
 183.571 +        cur.defineAsGenerator(node);
 183.572 +        cur.yield_count++;
 183.573 +        traverse(node);
 183.574 +        return null;
 183.575 +    }
 183.576 +
 183.577 +    @Override
 183.578 +    public Object visitReturn(Return node) throws Exception {
 183.579 +        if (node.getInternalValue() != null) {
 183.580 +            cur.noteReturnValue(node);
 183.581 +        }
 183.582 +        traverse(node);
 183.583 +        return null;
 183.584 +    }
 183.585 +
 183.586 +    @Override
 183.587 +    public Object visitGeneratorExp(GeneratorExp node) throws Exception {
 183.588 +        // The first iterator is evaluated in the outer scope
 183.589 +        if (node.getInternalGenerators() != null && node.getInternalGenerators().size() > 0) {
 183.590 +            visit(node.getInternalGenerators().get(0).getInternalIter());
 183.591 +        }
 183.592 +        String bound_exp = "_(x)";
 183.593 +        String tmp = "_(" + node.getLine() + "_" + node.getCharPositionInLine() + ")";
 183.594 +        def(tmp, GENERATOR, node);
 183.595 +        ArgListCompiler ac = new ArgListCompiler(symbolTable);
 183.596 +        List<expr> args = new ArrayList<>();
 183.597 +        Name argsName = new Name(node.getToken(), bound_exp, expr_contextType.Param);
 183.598 +        args.add(argsName);
 183.599 +        ac.visitArgs(new arguments(node, args, null, null, new ArrayList<expr>()));
 183.600 +        beginScope(tmp, FUNCSCOPE, node, ac);
 183.601 +        cur.addParam(bound_exp, argsName);
 183.602 +        cur.markFromParam();
 183.603 +
 183.604 +        cur.defineAsGenerator(node);
 183.605 +        cur.yield_count++;
 183.606 +        // The reset of the iterators are evaluated in the inner scope
 183.607 +        if (node.getInternalElt() != null) {
 183.608 +            visit(node.getInternalElt());
 183.609 +        }
 183.610 +        if (node.getInternalGenerators() != null) {
 183.611 +            for (int i = 0; i < node.getInternalGenerators().size(); i++) {
 183.612 +                if (node.getInternalGenerators().get(i) != null) {
 183.613 +                    if (i == 0) {
 183.614 +                        visit(node.getInternalGenerators().get(i).getInternalTarget());
 183.615 +                        if (node.getInternalGenerators().get(i).getInternalIfs() != null) {
 183.616 +                            for (expr cond : node.getInternalGenerators().get(i).getInternalIfs()) {
 183.617 +                                if (cond != null) {
 183.618 +                                    visit(cond);
 183.619 +                                }
 183.620 +                            }
 183.621 +                        }
 183.622 +                    } else {
 183.623 +                        visit(node.getInternalGenerators().get(i));
 183.624 +                    }
 183.625 +                }
 183.626 +            }
 183.627 +        }
 183.628 +
 183.629 +        endScope();
 183.630 +        return null;
 183.631 +    }
 183.632 +
 183.633 +    @Override
 183.634 +    public Object visitWith(With node) throws Exception {
 183.635 +        cur.max_with_count++;
 183.636 +        traverse(node);
 183.637 +
 183.638 +        return null;
 183.639 +    }
 183.640 +
 183.641 +    public List<Str> getPublicSymbols() {
 183.642 +        return invalidPublicSymbols ? null : publicSymbols;
 183.643 +    }
 183.644 +}
   184.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   184.2 +++ b/python.source/src/org/netbeans/modules/python/source/scopes/SymInfo.java	Sun Sep 13 11:47:42 2015 +0200
   184.3 @@ -0,0 +1,182 @@
   184.4 +package org.netbeans.modules.python.source.scopes;
   184.5 +
   184.6 +import org.python.antlr.PythonTree;
   184.7 +import static org.netbeans.modules.python.source.scopes.ScopeConstants.*;
   184.8 +
   184.9 +public class SymInfo extends Object {
  184.10 +    public SymInfo(int flags) {
  184.11 +        this.flags = flags;
  184.12 +    }
  184.13 +
  184.14 +    public SymInfo(int flags, int locals_index) {
  184.15 +        this.flags = flags;
  184.16 +        this.locals_index = locals_index;
  184.17 +    }
  184.18 +    public int flags;
  184.19 +    public int locals_index;
  184.20 +    public int env_index;
  184.21 +    public PythonTree node;
  184.22 +
  184.23 +    @Override
  184.24 +    public String toString() {
  184.25 +        return "SymInfo[" + flags + " " + locals_index + " " +
  184.26 +                env_index + "]" + dumpFlags(null);
  184.27 +    }
  184.28 +
  184.29 +    public String dumpFlags(ScopeInfo info) {
  184.30 +        StringBuilder sb = new StringBuilder();
  184.31 +        if ((flags & BOUND) != 0) {
  184.32 +            sb.append("[bound]");
  184.33 +        }
  184.34 +        // func scope global (affect nested scopes)
  184.35 +        // vs. class scope global
  184.36 +        if ((flags & NGLOBAL) != 0) {
  184.37 +            sb.append("[func-global]");
  184.38 +        } else if ((flags & CLASS_GLOBAL) != 0) {
  184.39 +            sb.append("[class-global]");
  184.40 +        }
  184.41 +        if ((flags & PARAM) != 0) {
  184.42 +            sb.append("[param]");
  184.43 +        } else if ((flags & FROM_PARAM) != 0) {
  184.44 +            sb.append("[from-param]");
  184.45 +        }
  184.46 +        if ((flags & CELL) != 0) {
  184.47 +            sb.append("[cell]");
  184.48 +        }
  184.49 +        if ((flags & FREE) != 0) {
  184.50 +            sb.append("[free]");
  184.51 +        }
  184.52 +        if (isImported()) {
  184.53 +            sb.append("[imported]");
  184.54 +        }
  184.55 +        if (isPrivate()) {
  184.56 +            sb.append("[private]");
  184.57 +        }
  184.58 +        if (isClass()) {
  184.59 +            sb.append("[class]");
  184.60 +        }
  184.61 +        if (isFunction()) {
  184.62 +            sb.append("[function]");
  184.63 +        }
  184.64 +        if (isData()) {
  184.65 +            sb.append("[data]");
  184.66 +        }
  184.67 +        if (isMember()) {
  184.68 +            sb.append("[member]");
  184.69 +        }
  184.70 +        if (isDef()) {
  184.71 +            sb.append("[def]");
  184.72 +        }
  184.73 +        if (isRead()) {
  184.74 +            sb.append("[read]");
  184.75 +        }
  184.76 +        if (isAlias()) {
  184.77 +            sb.append("[alias]");
  184.78 +        }
  184.79 +        if (isGeneratorExp()) {
  184.80 +            sb.append("[generator]");
  184.81 +        }
  184.82 +        if (isCalled()) {
  184.83 +            sb.append("[called]");
  184.84 +        }
  184.85 +        if (isProtected()) {
  184.86 +            sb.append("[protected]");
  184.87 +        }
  184.88 +        if (isBoundInConstructor()) {
  184.89 +            sb.append("[bound-in-constructor]");
  184.90 +        }
  184.91 +        if (isUnused(info)) {
  184.92 +            sb.append("[unused]");
  184.93 +        }
  184.94 +        if (isUnresolved()) {
  184.95 +            sb.append("[UNRESOLVED]");
  184.96 +        }
  184.97 +        sb.append("[node=");
  184.98 +        if (node != null) {
  184.99 +            sb.append(node.getClass().getSimpleName());
 184.100 +        } else {
 184.101 +            sb.append("null");
 184.102 +        }
 184.103 +        sb.append("]");
 184.104 +
 184.105 +        return sb.toString();
 184.106 +    }
 184.107 +
 184.108 +    public boolean isUnused(ScopeInfo info) {
 184.109 +        return (info == null || info.kind == FUNCSCOPE) && (flags & (READ | BOUND | DEF)) == BOUND;
 184.110 +    }
 184.111 +
 184.112 +    public boolean isParameter() {
 184.113 +        return (flags & (PARAM | FROM_PARAM)) != 0;
 184.114 +    }
 184.115 +
 184.116 +    public boolean isUnresolved() {
 184.117 +        return (flags & (BOUND | FREE)) == 0;
 184.118 +    }
 184.119 +
 184.120 +    public boolean isImported() {
 184.121 +        return (flags & IMPORTED) != 0;
 184.122 +    }
 184.123 +
 184.124 +    public boolean isData() {
 184.125 +        return (flags & (BOUND | DEF | CLASS | FUNCTION)) == (BOUND);
 184.126 +    }
 184.127 +
 184.128 +    public boolean isClass() {
 184.129 +        return (flags & CLASS) != 0;
 184.130 +    }
 184.131 +
 184.132 +    public boolean isDef() {
 184.133 +        return (flags & DEF) != 0;
 184.134 +    }
 184.135 +
 184.136 +    public boolean isFunction() {
 184.137 +        return (flags & FUNCTION) != 0;
 184.138 +    }
 184.139 +
 184.140 +    public boolean isBound() {
 184.141 +        return (flags & BOUND) != 0;
 184.142 +    }
 184.143 +
 184.144 +    public boolean isMember() {
 184.145 +        return (flags & MEMBER) != 0;
 184.146 +    }
 184.147 +
 184.148 +    public boolean isCalled() {
 184.149 +        return (flags & CALLED) != 0;
 184.150 +    }
 184.151 +
 184.152 +    public boolean isRead() {
 184.153 +        return (flags & READ) != 0;
 184.154 +    }
 184.155 +
 184.156 +    public boolean isGeneratorExp() {
 184.157 +        return (flags & GENERATOR) != 0;
 184.158 +    }
 184.159 +
 184.160 +    public boolean isFree() {
 184.161 +        return (flags & FREE) != 0;
 184.162 +    }
 184.163 +
 184.164 +    public boolean isPrivate() {
 184.165 +        return (flags & PRIVATE) != 0;
 184.166 +    }
 184.167 +
 184.168 +    public boolean isProtected() {
 184.169 +        return (flags & PROTECTED) != 0;
 184.170 +    }
 184.171 +
 184.172 +    public boolean isBoundInConstructor() {
 184.173 +        return (flags & BOUND_IN_CONSTRUCTOR) != 0;
 184.174 +    }
 184.175 +
 184.176 +    public boolean isAlias() {
 184.177 +        return (flags & ALIAS) != 0;
 184.178 +    }
 184.179 +
 184.180 +    public boolean isVariable(boolean mustBeBound) {
 184.181 +        int mask = mustBeBound ? BOUND : 0;
 184.182 +        return (flags & (BOUND | CALLED | DEF | IMPORTED | CLASS | FUNCTION | MEMBER | GENERATOR)) == mask;
 184.183 +    }
 184.184 +
 184.185 +}
   185.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   185.2 +++ b/python.source/src/org/netbeans/modules/python/source/scopes/SymbolTable.java	Sun Sep 13 11:47:42 2015 +0200
   185.3 @@ -0,0 +1,1247 @@
   185.4 +/*
   185.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   185.6 + *
   185.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   185.8 + *
   185.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  185.10 + * Other names may be trademarks of their respective owners.
  185.11 + *
  185.12 + * The contents of this file are subject to the terms of either the GNU
  185.13 + * General Public License Version 2 only ("GPL") or the Common
  185.14 + * Development and Distribution License("CDDL") (collectively, the
  185.15 + * "License"). You may not use this file except in compliance with the
  185.16 + * License. You can obtain a copy of the License at
  185.17 + * http://www.netbeans.org/cddl-gplv2.html
  185.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  185.19 + * specific language governing permissions and limitations under the
  185.20 + * License.  When distributing the software, include this License Header
  185.21 + * Notice in each file and include the License file at
  185.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  185.23 + * particular file as subject to the "Classpath" exception as provided
  185.24 + * by Oracle in the GPL Version 2 section of the License file that
  185.25 + * accompanied this code. If applicable, add the following below the
  185.26 + * License Header, with the fields enclosed by brackets [] replaced by
  185.27 + * your own identifying information:
  185.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  185.29 + *
  185.30 + * If you wish your version of this file to be governed by only the CDDL
  185.31 + * or only the GPL Version 2, indicate your decision by adding
  185.32 + * "[Contributor] elects to include this software in this distribution
  185.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  185.34 + * single choice of license, a recipient has the option to distribute
  185.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  185.36 + * to extend the choice of license to its licensees as provided above.
  185.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  185.38 + * Version 2 license, then the option applies only if the new code is
  185.39 + * made subject to such option by the copyright holder.
  185.40 + *
  185.41 + * Contributor(s):
  185.42 + *
  185.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  185.44 + */
  185.45 +package org.netbeans.modules.python.source.scopes;
  185.46 +
  185.47 +import java.util.ArrayList;
  185.48 +import java.util.Collections;
  185.49 +import java.util.HashMap;
  185.50 +import java.util.HashSet;
  185.51 +import java.util.List;
  185.52 +import java.util.Map;
  185.53 +import java.util.Set;
  185.54 +import org.netbeans.modules.csl.api.ElementKind;
  185.55 +import org.netbeans.modules.csl.api.OffsetRange;
  185.56 +import org.netbeans.modules.csl.api.Severity;
  185.57 +import org.netbeans.modules.csl.api.Error;
  185.58 +import org.netbeans.modules.csl.spi.DefaultError;
  185.59 +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
  185.60 +import org.netbeans.modules.python.source.PythonAstUtils;
  185.61 +import org.netbeans.modules.python.source.PythonIndex;
  185.62 +import org.netbeans.modules.python.source.PythonIndexer;
  185.63 +import org.netbeans.modules.python.source.PythonParserResult;
  185.64 +import org.netbeans.modules.python.source.PythonUtils;
  185.65 +import org.netbeans.modules.python.source.elements.AstElement;
  185.66 +import org.netbeans.modules.python.source.elements.Element;
  185.67 +import org.netbeans.modules.python.source.elements.IndexedElement;
  185.68 +import org.netbeans.modules.python.source.ImportEntry;
  185.69 +import org.netbeans.modules.python.source.ImportManager;
  185.70 +import org.openide.filesystems.FileObject;
  185.71 +import org.openide.filesystems.FileUtil;
  185.72 +import org.openide.util.Exceptions;
  185.73 +import org.python.antlr.PythonTree;
  185.74 +import org.python.antlr.Visitor;
  185.75 +import org.python.antlr.ast.Attribute;
  185.76 +import org.python.antlr.ast.ClassDef;
  185.77 +import org.python.antlr.ast.Expression;
  185.78 +import org.python.antlr.ast.FunctionDef;
  185.79 +import org.python.antlr.ast.GeneratorExp;
  185.80 +import org.python.antlr.ast.Import;
  185.81 +import org.python.antlr.ast.ImportFrom;
  185.82 +import org.python.antlr.ast.Interactive;
  185.83 +import org.python.antlr.ast.Lambda;
  185.84 +import org.python.antlr.ast.Name;
  185.85 +import org.python.antlr.ast.Str;
  185.86 +import org.python.antlr.ast.alias;
  185.87 +import org.python.antlr.base.expr;
  185.88 +import static org.netbeans.modules.python.source.scopes.ScopeConstants.*;
  185.89 +
  185.90 +/**
  185.91 + * A symbol table tracks a bunch of scopes and can answer questions about defined
  185.92 + * symbols.
  185.93 + *
  185.94 + * Based on Jython's ScopeManager.
  185.95 + *
  185.96 + * @author Tor Norbye
  185.97 + */
  185.98 +public class SymbolTable {
  185.99 +    private final static int YES = 1;
 185.100 +    private final static int NO = 0;
 185.101 +    private final static int CIRCULAR = -1;
 185.102 +    private Map<PythonTree, ScopeInfo> scopes = new HashMap<>();
 185.103 +    private PythonTree root;
 185.104 +    private FileObject fileObject;
 185.105 +    private List<Import> imports = new ArrayList<>();
 185.106 +    private List<ImportFrom> importsFrom = new ArrayList<>();
 185.107 +    private List<PythonTree> mainImports = new ArrayList<>();
 185.108 +    private Set<PythonTree> topLevelImports = new HashSet<>();
 185.109 +    private List<Error> errors;
 185.110 +    /** List of symbols registered via __all__ = [ "foo", "bar" ] or __all__.extend() or __all__.append() */
 185.111 +    private List<Str> publicSymbols;
 185.112 +    private final static HashMap<String, String> classAttributes = new HashMap<String, String>() {
 185.113 +        {
 185.114 +            put("__class__", "__class__");
 185.115 +            put("__bases__", "__bases__");
 185.116 +            put("__dict__", "__dict__");
 185.117 +            put("__doc__", "__doc__");
 185.118 +            put("__name__", "__bases");
 185.119 +        }
 185.120 +    };
 185.121 +    private HashMap<String, ClassDef> classes = new HashMap<>();
 185.122 +    // TODO - use WeakHashMap?
 185.123 +    static Map<String, Set<IndexedElement>> importedElements = new HashMap<>();
 185.124 +
 185.125 +    private HashMap<String, ClassDef> buildLocalClasses() {
 185.126 +        HashMap<String, ClassDef> localClasses = new HashMap<>();
 185.127 +        for (PythonTree cur : scopes.keySet()) {
 185.128 +            if (cur instanceof ClassDef) {
 185.129 +                ClassDef curClass = (ClassDef)cur;
 185.130 +                localClasses.put(curClass.getInternalName(), curClass);
 185.131 +            }
 185.132 +        }
 185.133 +        return localClasses;
 185.134 +    }
 185.135 +
 185.136 +    public SymbolTable(PythonTree root, FileObject fileObject) {
 185.137 +        this.root = root;
 185.138 +        this.fileObject = fileObject;
 185.139 +
 185.140 +        if (root != null) {
 185.141 +            try {
 185.142 +                ScopesCompiler compiler = new ScopesCompiler(this, scopes, root, imports, importsFrom, mainImports, topLevelImports);
 185.143 +                compiler.parse();
 185.144 +                publicSymbols = compiler.getPublicSymbols();
 185.145 +                classes = buildLocalClasses();
 185.146 +                if (publicSymbols != null) {
 185.147 +                    // Mark all other symbols private!
 185.148 +                    Set<String> names = new HashSet<>(publicSymbols.size() + 1);
 185.149 +                    names.add("__all__"); // __all__ itself is exported!
 185.150 +                    for (Str str : publicSymbols) {
 185.151 +                        String name = PythonAstUtils.getStrContent(str);
 185.152 +                        if (name != null) {
 185.153 +                            names.add(name);
 185.154 +                        }
 185.155 +                    }
 185.156 +
 185.157 +                    ScopeInfo topScope = scopes.get(root);
 185.158 +                    if (topScope != null) {
 185.159 +                        for (Map.Entry<String, SymInfo> entry : topScope.tbl.entrySet()) {
 185.160 +                            String name = entry.getKey();
 185.161 +                            if (!names.contains(name)) {
 185.162 +                                SymInfo sym = entry.getValue();
 185.163 +                                sym.flags |= PRIVATE;
 185.164 +                                if (sym.isDef() && sym.node != null) {
 185.165 +                                    ScopeInfo scope = scopes.get(sym.node);
 185.166 +                                    scope.hidden = true;
 185.167 +                                }
 185.168 +                            }
 185.169 +                        }
 185.170 +                    }
 185.171 +
 185.172 +                    for (Map.Entry<PythonTree, ScopeInfo> entry : scopes.entrySet()) {
 185.173 +                        ScopeInfo scope = entry.getValue();
 185.174 +                        boolean isHidden = false;
 185.175 +                        ScopeInfo curr = scope;
 185.176 +                        while (curr != null) {
 185.177 +                            if (curr.hidden) {
 185.178 +                                isHidden = true;
 185.179 +                                break;
 185.180 +                            }
 185.181 +                            if (curr.nested != null) {
 185.182 +                                curr = curr.nested;
 185.183 +                            } else {
 185.184 +                                curr = curr.up;
 185.185 +                            }
 185.186 +
 185.187 +                        }
 185.188 +                        if (isHidden) {
 185.189 +                            scope.hidden = true;
 185.190 +                        }
 185.191 +                    }
 185.192 +
 185.193 +                    // Mark all symbols private, unless the scope is a direct descendant
 185.194 +                    // of a public symbol
 185.195 +                    for (ScopeInfo scope : scopes.values()) {
 185.196 +                        if (scope.hidden) {
 185.197 +                            for (SymInfo sym : scope.tbl.values()) {
 185.198 +                                sym.flags |= PRIVATE;
 185.199 +                            }
 185.200 +                        }
 185.201 +                    }
 185.202 +                }
 185.203 +            } catch (Exception ex) {
 185.204 +                Exceptions.printStackTrace(ex);
 185.205 +            }
 185.206 +        }
 185.207 +    }
 185.208 +
 185.209 +    public boolean isPrivate(PythonTree node, String name) {
 185.210 +        ScopeInfo scope = scopes.get(node);
 185.211 +        if (scope == null) {
 185.212 +            scope = scopes.get(root);
 185.213 +        }
 185.214 +        if (scope != null) {
 185.215 +            if (scope.up != null) {
 185.216 +                if (scope.hidden) {
 185.217 +                    return true;
 185.218 +                }
 185.219 +                // Look in parent's scope table
 185.220 +                if (scope.nested != null) {
 185.221 +                    scope = scope.nested;
 185.222 +                } else {
 185.223 +                    scope = scope.up;
 185.224 +                }
 185.225 +                if (scope != null) {
 185.226 +                    SymInfo sym = scope.tbl.get(name);
 185.227 +                    if (sym != null) {
 185.228 +                        return sym.isPrivate();
 185.229 +                    }
 185.230 +                }
 185.231 +            } else {
 185.232 +                SymInfo sym = scope.tbl.get(name);
 185.233 +                if (sym != null) {
 185.234 +                    return sym.isPrivate();
 185.235 +                }
 185.236 +            }
 185.237 +        }
 185.238 +
 185.239 +        return false;
 185.240 +    }
 185.241 +
 185.242 +    public SymInfo findDeclaration(PythonTree scope, String name, boolean allowFree) {
 185.243 +        ScopeInfo scopeInfo = getScopeInfo(scope);
 185.244 +        if (scopeInfo != null) {
 185.245 +            SymInfo sym = scopeInfo.tbl.get(name);
 185.246 +            SymInfo orig = sym;
 185.247 +            while (sym != null && sym.isFree()) {
 185.248 +                scopeInfo = scopeInfo.up;
 185.249 +                while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 185.250 +                    scopeInfo = scopeInfo.up;
 185.251 +                }
 185.252 +                sym = scopeInfo.tbl.get(name);
 185.253 +            }
 185.254 +
 185.255 +            if (allowFree && sym == null && orig != null) {
 185.256 +                // Free variable -- might have to resolve it
 185.257 +                return orig;
 185.258 +            }
 185.259 +
 185.260 +            // Look for attributes too
 185.261 +            if (sym == null) {
 185.262 +                sym = scopeInfo.attributes.get(name);
 185.263 +                orig = sym;
 185.264 +                while (sym != null && sym.isFree()) {
 185.265 +                    scopeInfo = scopeInfo.up;
 185.266 +                    while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 185.267 +                        scopeInfo = scopeInfo.up;
 185.268 +                    }
 185.269 +                    sym = scopeInfo.tbl.get(name);
 185.270 +                }
 185.271 +
 185.272 +                if (allowFree && sym == null && orig != null) {
 185.273 +                    // Free variable -- might have to resolve it
 185.274 +                    return orig;
 185.275 +                }
 185.276 +            }
 185.277 +
 185.278 +            return sym;
 185.279 +        }
 185.280 +
 185.281 +        return null;
 185.282 +    }
 185.283 +
 185.284 +    public ScopeInfo getScopeInfo(PythonTree node) {
 185.285 +        return scopes.get(node);
 185.286 +    }
 185.287 +
 185.288 +    public List<Error> getErrors() {
 185.289 +        return errors != null ? errors : Collections.<Error>emptyList();
 185.290 +    }
 185.291 +
 185.292 +    public SymInfo findBySignature(ElementKind kind, String signature) {
 185.293 +        PythonTree scope = root;
 185.294 +        String name = signature;
 185.295 +        int dot = signature.lastIndexOf('.');
 185.296 +        if (dot != -1) {
 185.297 +            String clz = signature.substring(0, dot);
 185.298 +            name = signature.substring(dot + 1);
 185.299 +            SymInfo sym = findDeclaration(root, clz, true);
 185.300 +            if (sym != null && sym.node != null) {
 185.301 +                scope = sym.node;
 185.302 +            }
 185.303 +        }
 185.304 +        SymInfo sym = findDeclaration(scope, name, true);
 185.305 +
 185.306 +        return sym;
 185.307 +    }
 185.308 +
 185.309 +    private List<String> getModulesToStarImport() {
 185.310 +        List<String> modules = new ArrayList<>();
 185.311 +
 185.312 +        for (ImportFrom from : importsFrom) {
 185.313 +            List<alias> names = from.getInternalNames();
 185.314 +            if (names != null) {
 185.315 +                for (alias at : names) {
 185.316 +                    if ("*".equals(at.getInternalName())) { // NOI18N
 185.317 +                        modules.add(from.getInternalModule());
 185.318 +                    }
 185.319 +                }
 185.320 +            }
 185.321 +        }
 185.322 +
 185.323 +        modules.addAll(PythonIndex.BUILTIN_MODULES);
 185.324 +
 185.325 +        return modules;
 185.326 +    }
 185.327 +
 185.328 +    private void addSymbolsFromModule(PythonParserResult info, String module, String prefix, QuerySupport.Kind kind, Set<? super IndexedElement> result) {
 185.329 +        if (PythonIndex.isBuiltinModule(module)) {
 185.330 +            Set<IndexedElement> all = getAllSymbolsFromModule(info, module);
 185.331 +            for (IndexedElement e : all) {
 185.332 +                if (kind == QuerySupport.Kind.PREFIX) {
 185.333 +                    if (e.getName().startsWith(prefix)) {
 185.334 +                        result.add(e);
 185.335 +                    }
 185.336 +                } else if (kind == QuerySupport.Kind.EXACT) {
 185.337 +                    if (prefix.equals(e.getName())) {
 185.338 +                        result.add(e);
 185.339 +                    }
 185.340 +                } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX) {
 185.341 +                    if (e.getName().regionMatches(true, 0, prefix, 0, prefix.length())) {
 185.342 +                        result.add(e);
 185.343 +                    }
 185.344 +                }
 185.345 +            }
 185.346 +        } else {
 185.347 +            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 185.348 +            Set<IndexedElement> elements = index.getImportedElements(prefix, kind, Collections.singleton(module), null);
 185.349 +            for (IndexedElement e : elements) {
 185.350 +                result.add(e);
 185.351 +            }
 185.352 +        }
 185.353 +    }
 185.354 +
 185.355 +    private Set<IndexedElement> getAllSymbolsFromModule(PythonParserResult info, String module) {
 185.356 +        Set<IndexedElement> elements = importedElements.get(module);
 185.357 +        if (elements == null) {
 185.358 +            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 185.359 +            Set<String> systemHolder = new HashSet<>(3);
 185.360 +            elements = index.getImportedElements("", QuerySupport.Kind.PREFIX, Collections.singleton(module), systemHolder);
 185.361 +            // Cache system modules - don't cache local modules
 185.362 +            if (!systemHolder.isEmpty()) {
 185.363 +                importedElements.put(module, elements);
 185.364 +            }
 185.365 +        }
 185.366 +
 185.367 +        return elements;
 185.368 +    }
 185.369 +
 185.370 +    public Set<Element> getDefinedElements(PythonParserResult info, PythonTree scope, String prefix, QuerySupport.Kind kind) {
 185.371 +        Set<Element> elements = new HashSet<>(300);
 185.372 +        ScopeInfo scopeInfo = scopes.get(scope);
 185.373 +        String module = PythonUtils.getModuleName(fileObject);
 185.374 +        String url = fileObject.toURL().toExternalForm();
 185.375 +
 185.376 +        // Get builtin symbols
 185.377 +        for (String mod : getModulesToStarImport()) {
 185.378 +            addSymbolsFromModule(info, mod, prefix, kind, elements);
 185.379 +        }
 185.380 +
 185.381 +        // I can't just search the scope table for all variables in scope because this
 185.382 +        // will only include the local -bound- variables and the -used- free variables.
 185.383 +        // I need to find potential free variables as well. This means I should walk up
 185.384 +        // the scope chain and compute all eligible names. By keep track of the ones I've
 185.385 +        // already added I avoid adding references to variables I have re-bound in closer
 185.386 +        // scopes.
 185.387 +
 185.388 +        Set<String> added = new HashSet<>();
 185.389 +
 185.390 +        while (scopeInfo != null) {
 185.391 +            for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 185.392 +                String name = entry.getKey();
 185.393 +                if (added.contains(name)) {
 185.394 +                    // Something in narrower scope already processed this one
 185.395 +                    continue;
 185.396 +                }
 185.397 +                if (kind == QuerySupport.Kind.EXACT) {
 185.398 +                    if (!(name.equals(prefix))) {
 185.399 +                        continue;
 185.400 +                    }
 185.401 +                } else if (kind == QuerySupport.Kind.PREFIX) {
 185.402 +                    if (!name.startsWith(prefix)) {
 185.403 +                        continue;
 185.404 +                    }
 185.405 +                } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX) {
 185.406 +                    if (!name.regionMatches(true, 0, prefix, 0, prefix.length())) {
 185.407 +                        continue;
 185.408 +                    }
 185.409 +                }
 185.410 +                SymInfo sym = entry.getValue();
 185.411 +
 185.412 +                ScopeInfo curr = scopeInfo;
 185.413 +                while (sym != null && sym.isFree()) {
 185.414 +                    curr = curr.up;
 185.415 +                    while (curr != null && curr.kind == CLASSSCOPE) {
 185.416 +                        curr = curr.up;
 185.417 +                    }
 185.418 +                    if (curr == null) {
 185.419 +                        sym = null;
 185.420 +                        break;
 185.421 +                    }
 185.422 +                    sym = scopeInfo.tbl.get(name);
 185.423 +                }
 185.424 +                if (sym == null) {
 185.425 +                    continue;
 185.426 +                }
 185.427 +                if (sym.isUnresolved()) {
 185.428 +                    // Don't add completion items for stuff we're not sure about
 185.429 +                    continue;
 185.430 +                }
 185.431 +
 185.432 +                PythonTree node = sym.node;
 185.433 +                if (node == null) {
 185.434 +                    continue;
 185.435 +                }
 185.436 +
 185.437 +
 185.438 +                if (sym.isImported()) {
 185.439 +                    Element element = new AstElement(this, node, name, Character.isUpperCase(name.charAt(0)) ? ElementKind.CLASS : ElementKind.MODULE);
 185.440 +                    elements.add(element);
 185.441 +                } else if (sym.isDef()) {
 185.442 +                    String signature;
 185.443 +                    if (sym.isClass() && node instanceof ClassDef) {
 185.444 +                        signature = PythonIndexer.computeClassSig((ClassDef)node, sym);
 185.445 +                    } else if (sym.isFunction() && node instanceof FunctionDef) {
 185.446 +                        assert sym.isFunction() && node instanceof FunctionDef : name + ";" + sym + " in " + module;
 185.447 +                        signature = PythonIndexer.computeFunctionSig(name, (FunctionDef)node, sym);
 185.448 +                    } else {
 185.449 +                        // Probably a generator expression
 185.450 +                        continue;
 185.451 +                    }
 185.452 +                    //Element element = AstElement.create(null, node);
 185.453 +                    IndexedElement element = IndexedElement.create(signature, module, url, null);
 185.454 +                    element.setSmart(true);
 185.455 +                    elements.add(element);
 185.456 +                } else {
 185.457 +                    // TODO - class attributes?
 185.458 +                    Element element = new AstElement(this, node, name, ElementKind.VARIABLE);
 185.459 +                    elements.add(element);
 185.460 +                }
 185.461 +
 185.462 +                added.add(name);
 185.463 +            }
 185.464 +
 185.465 +            scopeInfo = scopeInfo.up;
 185.466 +            while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 185.467 +                scopeInfo = scopeInfo.up;
 185.468 +            }
 185.469 +        }
 185.470 +
 185.471 +        return elements;
 185.472 +    }
 185.473 +
 185.474 +    // Return all node references to the given name
 185.475 +    // This will include imports, calls, definitions, etc.
 185.476 +    public List<PythonTree> getOccurrences(PythonTree scope, String name, boolean abortOnFree) {
 185.477 +        ScopeInfo scopeInfo = scopes.get(scope);
 185.478 +        if (scopeInfo != null) {
 185.479 +            SymInfo sym = scopeInfo.tbl.get(name);
 185.480 +            while (sym != null && sym.isFree()) {
 185.481 +                if (abortOnFree) {
 185.482 +                    return null;
 185.483 +                }
 185.484 +                scopeInfo = scopeInfo.up;
 185.485 +                while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 185.486 +                    scopeInfo = scopeInfo.up;
 185.487 +                }
 185.488 +                sym = scopeInfo.tbl.get(name);
 185.489 +            }
 185.490 +
 185.491 +            if (sym != null) {
 185.492 +                NameNodeFinder finder = new NameNodeFinder(name, scopeInfo.scope_node);
 185.493 +                finder.run();
 185.494 +                return finder.getNodes();
 185.495 +            }
 185.496 +        }
 185.497 +
 185.498 +        return Collections.emptyList();
 185.499 +    }
 185.500 +
 185.501 +    /** Return a list of the variables visible from a given scope */
 185.502 +    public Set<String> getVarNames(PythonTree scope, boolean mustBeBound) {
 185.503 +        ScopeInfo scopeInfo = scopes.get(scope);
 185.504 +        Set<String> names = new HashSet<>();
 185.505 +        while (scopeInfo != null) {
 185.506 +            for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 185.507 +                String name = entry.getKey();
 185.508 +                SymInfo sym = entry.getValue();
 185.509 +                if (sym.isVariable(mustBeBound)) {
 185.510 +                    names.add(name);
 185.511 +                }
 185.512 +            }
 185.513 +            scopeInfo = scopeInfo.up;
 185.514 +            while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 185.515 +                scopeInfo = scopeInfo.up;
 185.516 +            }
 185.517 +        }
 185.518 +
 185.519 +        return names;
 185.520 +    }
 185.521 +
 185.522 +    public List<ImportEntry> getUnusedImports() {
 185.523 +        List<ImportEntry> unused = new ArrayList<>();
 185.524 +        ScopeInfo scopeInfo = scopes.get(root);
 185.525 +        for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 185.526 +            SymInfo sym = entry.getValue();
 185.527 +            if (sym.isImported() && !sym.isRead()) {
 185.528 +                String name = entry.getKey();
 185.529 +                if (name.equals("*")) { // NOI18N
 185.530 +                    // Not detecting usages of wildcard imports yet...
 185.531 +                    continue;
 185.532 +                }
 185.533 +                PythonTree node = sym.node;
 185.534 +                if (node instanceof Import) {
 185.535 +                    Import imp = (Import)node;
 185.536 +                    int ordinal = 0;
 185.537 +                    String module = null;
 185.538 +                    String asName = null;
 185.539 +                    List<alias> names = imp.getInternalNames();
 185.540 +                    if (names != null) {
 185.541 +                        for (alias at : names) {
 185.542 +                            if (name.equals(at.getInternalAsname())) {
 185.543 +                                module = at.getInternalName();
 185.544 +                                asName = at.getInternalAsname();
 185.545 +                                break;
 185.546 +                            } else if (name.equals(at.getInternalName())) {
 185.547 +                                module = at.getInternalName();
 185.548 +                                break;
 185.549 +                            }
 185.550 +                        }
 185.551 +                        if (module == null) {
 185.552 +                            // For imports with dotted names, like wsgiref.handlers,
 185.553 +                            // the symbol table entry is just "wsgiref", yet I have to match
 185.554 +                            // the symbols, so try again more carefully
 185.555 +                            for (alias at : names) {
 185.556 +                                if (at.getInternalAsname() != null && at.getInternalAsname().startsWith(name) &&
 185.557 +                                        at.getInternalAsname().charAt(name.length()) == '.') {
 185.558 +                                    module = at.getInternalName();
 185.559 +                                    asName = at.getInternalAsname();
 185.560 +                                    break;
 185.561 +                                } else if (at.getInternalName().startsWith(name) &&
 185.562 +                                        at.getInternalName().charAt(name.length()) == '.') {
 185.563 +                                    module = at.getInternalName();
 185.564 +                                    break;
 185.565 +                                }
 185.566 +                            }
 185.567 +                        }
 185.568 +                    }
 185.569 +                    unused.add(new ImportEntry(module, asName, true, imp, imp.getCharStartIndex() + (ordinal++)));
 185.570 +                } else if (node instanceof ImportFrom) {
 185.571 +                    ImportFrom imp = (ImportFrom)node;
 185.572 +                    if (ImportManager.isFutureImport(imp)) {
 185.573 +                        continue;
 185.574 +                    }
 185.575 +                    String module = imp.getInternalModule();
 185.576 +                    String origName = null;
 185.577 +                    String asName = null;
 185.578 +                    int ordinal = 0;
 185.579 +                    List<alias> names = imp.getInternalNames();
 185.580 +                    if (names != null) {
 185.581 +                        for (alias at : names) {
 185.582 +                            if (name.equals(at.getInternalAsname())) {
 185.583 +                                origName = at.getInternalName();
 185.584 +                                asName = at.getInternalAsname();
 185.585 +                                break;
 185.586 +                            } else if (name.equals(at.getInternalName())) {
 185.587 +                                origName = at.getInternalName();
 185.588 +                                break;
 185.589 +                            }
 185.590 +                        }
 185.591 +                        if (origName == null) {
 185.592 +                            // For imports with dotted names, like wsgiref.handlers,
 185.593 +                            // the symbol table entry is just "wsgiref", yet I have to match
 185.594 +                            // the symbols, so try again more carefully
 185.595 +                            for (alias at : names) {
 185.596 +                                if (at.getInternalAsname() != null && at.getInternalAsname().startsWith(name) &&
 185.597 +                                        at.getInternalAsname().charAt(name.length()) == '.') {
 185.598 +                                    origName = at.getInternalName();
 185.599 +                                    asName = at.getInternalAsname();
 185.600 +                                    break;
 185.601 +                                } else if (at.getInternalName().startsWith(name) &&
 185.602 +                                        at.getInternalName().charAt(name.length()) == '.') {
 185.603 +                                    origName = at.getInternalName();
 185.604 +                                    break;
 185.605 +                                }
 185.606 +                            }
 185.607 +                        }
 185.608 +                    }
 185.609 +                    unused.add(new ImportEntry(module, origName, asName, true, imp, imp.getCharStartIndex() + (ordinal++)));
 185.610 +                }
 185.611 +            }
 185.612 +        }
 185.613 +
 185.614 +        return unused;
 185.615 +    }
 185.616 +
 185.617 +    private class NameNodeFinder extends Visitor {
 185.618 +        private List<PythonTree> nodes = new ArrayList<>();
 185.619 +        private PythonTree startScope;
 185.620 +        private String name;
 185.621 +
 185.622 +        public NameNodeFinder(String name, PythonTree startScope) {
 185.623 +            this.name = name;
 185.624 +            this.startScope = startScope;
 185.625 +        }
 185.626 +
 185.627 +        public void run() {
 185.628 +            try {
 185.629 +                visit(startScope);
 185.630 +            } catch (Exception ex) {
 185.631 +                Exceptions.printStackTrace(ex);
 185.632 +            }
 185.633 +        }
 185.634 +
 185.635 +        @Override
 185.636 +        public Object visitImport(Import imp) throws Exception {
 185.637 +            List<alias> names = imp.getInternalNames();
 185.638 +            if (names != null && names.size() > 0) {
 185.639 +                boolean found = false;
 185.640 +                for (alias at : names) {
 185.641 +                    String asName = at.getInternalAsname();
 185.642 +                    if (asName != null) {
 185.643 +                        if (name.equals(asName)) {
 185.644 +                            found = true;
 185.645 +                            break;
 185.646 +                        }
 185.647 +                    } else if (name.equals(at.getInternalName())) {
 185.648 +                        found = true;
 185.649 +                        break;
 185.650 +                    }
 185.651 +                }
 185.652 +                if (found) {
 185.653 +                    nodes.add(imp);
 185.654 +                }
 185.655 +            }
 185.656 +            return super.visitImport(imp);
 185.657 +        }
 185.658 +
 185.659 +        @Override
 185.660 +        public Object visitImportFrom(ImportFrom imp) throws Exception {
 185.661 +            List<alias> names = imp.getInternalNames();
 185.662 +            if (names != null && names.size() > 0) {
 185.663 +                boolean found = false;
 185.664 +                for (alias at : names) {
 185.665 +                    String asName = at.getInternalAsname();
 185.666 +                    if (asName != null) {
 185.667 +                        if (name.equals(asName)) {
 185.668 +                            found = true;
 185.669 +                            break;
 185.670 +                        }
 185.671 +                    } else if (name.equals(at.getInternalName())) {
 185.672 +                        found = true;
 185.673 +                        break;
 185.674 +                    }
 185.675 +                }
 185.676 +                if (found) {
 185.677 +                    nodes.add(imp);
 185.678 +                }
 185.679 +            }
 185.680 +
 185.681 +            return super.visitImportFrom(imp);
 185.682 +        }
 185.683 +
 185.684 +        @Override
 185.685 +        public Object visitName(Name node) throws Exception {
 185.686 +            if (node.getInternalId().equals(name)) {
 185.687 +                nodes.add(node);
 185.688 +            }
 185.689 +            return super.visitName(node);
 185.690 +        }
 185.691 +
 185.692 +        @Override
 185.693 +        public Object visitFunctionDef(FunctionDef node) throws Exception {
 185.694 +            if (name.equals(node.getInternalName())) {
 185.695 +                nodes.add(node);
 185.696 +            }
 185.697 +
 185.698 +            if (isIncludedScope(node)) {
 185.699 +                return super.visitFunctionDef(node);
 185.700 +            } else {
 185.701 +                return null;
 185.702 +            }
 185.703 +        }
 185.704 +
 185.705 +        @Override
 185.706 +        public Object visitClassDef(ClassDef node) throws Exception {
 185.707 +            if (name.equals(node.getInternalName())) {
 185.708 +                nodes.add(node);
 185.709 +            }
 185.710 +
 185.711 +            if (isIncludedScope(node)) {
 185.712 +                return super.visitClassDef(node);
 185.713 +            } else {
 185.714 +                return null;
 185.715 +            }
 185.716 +        }
 185.717 +
 185.718 +        @Override
 185.719 +        public Object visitExpression(Expression node) throws Exception {
 185.720 +            if (isIncludedScope(node)) {
 185.721 +                return super.visitExpression(node);
 185.722 +            } else {
 185.723 +                return null;
 185.724 +            }
 185.725 +        }
 185.726 +
 185.727 +        @Override
 185.728 +        public Object visitInteractive(Interactive node) throws Exception {
 185.729 +            if (isIncludedScope(node)) {
 185.730 +                return super.visitInteractive(node);
 185.731 +            } else {
 185.732 +                return null;
 185.733 +            }
 185.734 +        }
 185.735 +
 185.736 +        @Override
 185.737 +        public Object visitLambda(Lambda node) throws Exception {
 185.738 +            if (isIncludedScope(node)) {
 185.739 +                return super.visitLambda(node);
 185.740 +            } else {
 185.741 +                return null;
 185.742 +            }
 185.743 +        }
 185.744 +
 185.745 +        @Override
 185.746 +        public Object visitGeneratorExp(GeneratorExp node) throws Exception {
 185.747 +            if (isIncludedScope(node)) {
 185.748 +                return super.visitGeneratorExp(node);
 185.749 +            } else {
 185.750 +                return null;
 185.751 +            }
 185.752 +        }
 185.753 +
 185.754 +        private boolean isIncludedScope(PythonTree node) {
 185.755 +            if (node == startScope) {
 185.756 +                return true;
 185.757 +            }
 185.758 +
 185.759 +            ScopeInfo info = scopes.get(node);
 185.760 +            if (info == null) {
 185.761 +                return false;
 185.762 +            }
 185.763 +
 185.764 +            SymInfo sym = info.tbl.get(name);
 185.765 +            // Skip scopes that redefine the variable
 185.766 +            if (sym != null && sym.isBound()) {
 185.767 +                return false;
 185.768 +            }
 185.769 +
 185.770 +            return true;
 185.771 +        }
 185.772 +
 185.773 +        public List<PythonTree> getNodes() {
 185.774 +            return nodes;
 185.775 +        }
 185.776 +    }
 185.777 +
 185.778 +    public Map<String, SymInfo> getUnresolvedNames(PythonParserResult info) {
 185.779 +        Map<String, SymInfo> unresolved = new HashMap<>();
 185.780 +        Set<String> builtin = getBuiltin(info);
 185.781 +
 185.782 +        for (ScopeInfo scopeInfo : scopes.values()) {
 185.783 +            Map<String, SymInfo> tbl = scopeInfo.tbl;
 185.784 +            for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
 185.785 +                SymInfo symInfo = entry.getValue();
 185.786 +                boolean isUnresolved = symInfo.isUnresolved();
 185.787 +                if (!isUnresolved && symInfo.isFree()) {
 185.788 +                    // Peek up scope stack
 185.789 +                    String name = entry.getKey();
 185.790 +                    SymInfo sym = symInfo;
 185.791 +                    ScopeInfo scope = scopeInfo;
 185.792 +                    while (sym != null && sym.isFree()) {
 185.793 +                        scope = scope.up;
 185.794 +                        while (scope != null && scope.kind == CLASSSCOPE) {
 185.795 +                            scope = scope.up;
 185.796 +                        }
 185.797 +                        sym = scope.tbl.get(name);
 185.798 +                    }
 185.799 +                    if (sym == null) {
 185.800 +                        isUnresolved = true;
 185.801 +                    } else {
 185.802 +                        isUnresolved = sym.isUnresolved();
 185.803 +                    }
 185.804 +                }
 185.805 +                if (isUnresolved) {
 185.806 +                    String key = entry.getKey();
 185.807 +                    if (!builtin.contains(key)) {
 185.808 +                        unresolved.put(key, symInfo);
 185.809 +                    }
 185.810 +                }
 185.811 +            }
 185.812 +        }
 185.813 +
 185.814 +        return unresolved;
 185.815 +    }
 185.816 +
 185.817 +    public List<Attribute> getNotInInitAttributes(PythonParserResult info) {
 185.818 +        List<Attribute> notInInitAttribs = new ArrayList<>();
 185.819 +        for (ScopeInfo scopeInfo : scopes.values()) {
 185.820 +            if (scopeInfo.scope_node instanceof ClassDef) {
 185.821 +                if (scopeInfo.attributes != null) {
 185.822 +                    for (Map.Entry<String, SymInfo> entry : scopeInfo.attributes.entrySet()) {
 185.823 +                        SymInfo symInfo = entry.getValue();
 185.824 +                        if (!symInfo.isBoundInConstructor()) {
 185.825 +                            notInInitAttribs.add((Attribute)symInfo.node);
 185.826 +                        }
 185.827 +                    }
 185.828 +                }
 185.829 +            }
 185.830 +        }
 185.831 +        return notInInitAttribs;
 185.832 +    }
 185.833 +
 185.834 +    private ScopeInfo getClassScope(String className) {
 185.835 +        for (ScopeInfo scopeInfo : scopes.values()) {
 185.836 +            if (scopeInfo.scope_node instanceof ClassDef) {
 185.837 +                ClassDef curClass = (ClassDef)scopeInfo.scope_node;
 185.838 +                if (curClass.getInternalName().equals(className)) {
 185.839 +                    return scopeInfo;
 185.840 +                }
 185.841 +            }
 185.842 +        }
 185.843 +        return null;
 185.844 +    }
 185.845 +
 185.846 +    private int belongsToParents(ClassDef cls, String name, HashMap<String, String> cycling) {
 185.847 +        List<expr> bases = cls.getInternalBases();
 185.848 +        if (bases == null || bases.size() == 0) {
 185.849 +            return NO; // no parents
 185.850 +        }
 185.851 +        for (expr base : bases) {
 185.852 +            String className = null;
 185.853 +            if (base instanceof Name) {
 185.854 +                className = ((Name)base).getInternalId();
 185.855 +            } else {
 185.856 +                // should be Attribute here( module.className form )
 185.857 +                // which imply imported from external scope
 185.858 +                // So we give up on scope returning optimistaically True
 185.859 +                return YES;
 185.860 +            }
 185.861 +            assert (className != null);
 185.862 +            if (cycling.get(className) != null) {
 185.863 +                cycling.clear();
 185.864 +                // put parent child conficting back in cycling
 185.865 +                cycling.put(className, cls.getInternalName());
 185.866 +                return CIRCULAR;
 185.867 +            }
 185.868 +            cycling.put(className, className);
 185.869 +            ScopeInfo localClassScope = getClassScope(className);
 185.870 +            if (localClassScope == null) {
 185.871 +                // return true (success) when at least one parent is outside module scope
 185.872 +                // just to notify caller to be optimistic and assume that
 185.873 +                // name is resolved by imported classes inheritance
 185.874 +                // scanning imported classed from here is discouraged for
 185.875 +                // performances reasons
 185.876 +                return YES;
 185.877 +            } else {
 185.878 +                if ((name != null) &&
 185.879 +                        (localClassScope.attributes.get(name) != null)) {
 185.880 +                    return YES;
 185.881 +                }
 185.882 +                // try recurse parentage to resolve attribute
 185.883 +                ClassDef parentClass = (ClassDef)localClassScope.scope_node;
 185.884 +                int recResult = belongsToParents(parentClass, name, cycling);
 185.885 +                if (recResult != NO) // stop on FOUND(YES) or CIRCULAR error
 185.886 +                {
 185.887 +                    return recResult;
 185.888 +                }
 185.889 +            }
 185.890 +        }
 185.891 +        return NO;
 185.892 +    }
 185.893 +
 185.894 +    private boolean isImported(String moduleName) {
 185.895 +        for (Import imported : imports) {
 185.896 +            List<alias> names = imported.getInternalNames();
 185.897 +            if (names != null) {
 185.898 +                for (alias cur : names) {
 185.899 +                    String name = cur.getInternalName();
 185.900 +                    String asName = cur.getInternalAsname();
 185.901 +                    if (((name != null) && (name.equals(moduleName))) ||
 185.902 +                            ((asName != null) && (asName.equals(moduleName)))) {
 185.903 +                        return true;
 185.904 +                    }
 185.905 +                }
 185.906 +            }
 185.907 +        }
 185.908 +        return false;
 185.909 +    }
 185.910 +
 185.911 +    private boolean isImportedFrom(String className) {
 185.912 +        for (ImportFrom importedFrom : importsFrom) {
 185.913 +            List<alias> names = importedFrom.getInternalNames();
 185.914 +            if (names != null) {
 185.915 +                for (alias cur : names) {
 185.916 +                    String name = cur.getInternalName();
 185.917 +                    String asName = cur.getInternalAsname();
 185.918 +                    if (((name != null) && (name.equals(className))) ||
 185.919 +                            ((asName != null) && (asName.equals(className)))) {
 185.920 +                        return true;
 185.921 +                    }
 185.922 +                }
 185.923 +            }
 185.924 +        }
 185.925 +        return false;
 185.926 +    }
 185.927 +
 185.928 +    public List<PythonTree> getUnresolvedParents(PythonParserResult info) {
 185.929 +        // deal with unresolved parents in inherit trees
 185.930 +        List<PythonTree> unresolvedParents = new ArrayList<>();
 185.931 +        PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 185.932 +
 185.933 +        for (String cur : classes.keySet()) {
 185.934 +            ClassDef cls = classes.get(cur);
 185.935 +            List<expr> bases = cls.getInternalBases();
 185.936 +            if (bases == null || bases.size() > 0) {
 185.937 +                // has parents
 185.938 +                for (expr base : bases) {
 185.939 +                    if (base instanceof Name) {
 185.940 +                        String className = ((Name)base).getInternalId();
 185.941 +                        Set<String> builtin = getBuiltin(info);
 185.942 +                        if ((!classes.containsKey(className)) &&
 185.943 +                                (!builtin.contains(className))) {
 185.944 +                            // check in from imports
 185.945 +                            if (!isImportedFrom(className)) {
 185.946 +                                unresolvedParents.add(base);
 185.947 +                            }
 185.948 +                        }
 185.949 +                    } else {
 185.950 +                        // should be Attribute here( module.className form )
 185.951 +                        // which imply imported from external scope
 185.952 +                        Attribute attr = (Attribute)base;
 185.953 +                        String clsName = attr.getInternalAttr();
 185.954 +                        if (attr.getInternalValue() instanceof Name) {
 185.955 +                            String moduleName = ((Name)(attr.getInternalValue())).getInternalId();
 185.956 +                            // check that import is resolved first
 185.957 +                            if (!isImported(moduleName)) {
 185.958 +                                unresolvedParents.add(base);
 185.959 +                            } else {
 185.960 +                                Set<IndexedElement> found = index.getImportedElements(clsName, QuerySupport.Kind.EXACT, Collections.<String>singleton(moduleName), null);
 185.961 +                                if (found.size() == 0) {
 185.962 +                                    unresolvedParents.add(base);
 185.963 +                                }
 185.964 +                            }
 185.965 +                        } else {
 185.966 +                            unresolvedParents.add(base);
 185.967 +                        }
 185.968 +                    }
 185.969 +                }
 185.970 +            }
 185.971 +        }
 185.972 +        return unresolvedParents;
 185.973 +    }
 185.974 +
 185.975 +    public HashMap<ClassDef, String> getClassesCyclingRedundancies(PythonParserResult info) {
 185.976 +        HashMap<ClassDef, String> cyclingRedundancies = new HashMap<>();
 185.977 +        for (String cur : classes.keySet()) {
 185.978 +            HashMap<String, String> returned = new HashMap<>();
 185.979 +            ClassDef curClass = classes.get(cur);
 185.980 +            if (!cyclingRedundancies.containsKey(curClass)) {
 185.981 +                if (belongsToParents(curClass, null, returned) == CIRCULAR) {
 185.982 +                    // store hashMap returned
 185.983 +                    Map.Entry<String, String> cycling = returned.entrySet().iterator().next();
 185.984 +                    cyclingRedundancies.put(curClass, cycling.getKey());
 185.985 +                }
 185.986 +            }
 185.987 +        }
 185.988 +        return cyclingRedundancies;
 185.989 +    }
 185.990 +
 185.991 +    public List<PythonTree> getUnresolvedAttributes(PythonParserResult info) {
 185.992 +        List<PythonTree> unresolvedNodes = new ArrayList<>();
 185.993 +        for (ScopeInfo scopeInfo : scopes.values()) {
 185.994 +            Set<String> unresolved = new HashSet<>();
 185.995 +            Map<String, SymInfo> tbl = scopeInfo.tbl;
 185.996 +            // unresolved attributes in local classes
 185.997 +            Map<String, SymInfo> attribs = scopeInfo.attributes;
 185.998 +            for (Map.Entry<String, SymInfo> curAttr : attribs.entrySet()) {
 185.999 +                SymInfo symInfo = curAttr.getValue();
185.1000 +                if (symInfo.isRead()) {
185.1001 +                    // check for builtin attribs first
185.1002 +                    if (classAttributes.get(curAttr.getKey()) == null) {
185.1003 +                        // not a builtin attribute
185.1004 +                        ScopeInfo parentScope = scopeInfo.getClassScope();
185.1005 +                        if (parentScope != null) {
185.1006 +                            // limit scope to Classes for self and inherited
185.1007 +                            Map<String, SymInfo> parentattribs = parentScope.attributes;
185.1008 +                            SymInfo classAttr = parentattribs.get(curAttr.getKey());
185.1009 +                            tbl = parentScope.tbl;
185.1010 +                            if (classAttr == null) {
185.1011 +                                // may be  also a reference to a method
185.1012 +                                classAttr = tbl.get(curAttr.getKey());
185.1013 +                            }
185.1014 +                            if (classAttr == null) {
185.1015 +                                // do not bother with method since they are
185.1016 +                                // managed by completion
185.1017 +                                ClassDef curClass = (ClassDef)parentScope.scope_node;
185.1018 +                                if (belongsToParents(curClass, curAttr.getKey(), new HashMap()) == NO) {
185.1019 +                                    if (!symInfo.isCalled()) {
185.1020 +                                        // no corresponding attributes
185.1021 +                                        //PythonTree tree = symInfo.node ;
185.1022 +                                        Attribute attr = (Attribute)symInfo.node;
185.1023 +                                        // Name name = new Name(tree.getToken(),attr.getInternalAttr(),attr.ctx) ;
185.1024 +                                        unresolvedNodes.add(attr);
185.1025 +                                    }
185.1026 +                                }
185.1027 +                            }
185.1028 +                        }
185.1029 +                    }
185.1030 +                }
185.1031 +            }
185.1032 +            if (unresolved.size() > 0) {
185.1033 +                NameFinder finder = new NameFinder(unresolved);
185.1034 +                List<Name> nodes = finder.run(scopeInfo.scope_node);
185.1035 +                unresolvedNodes.addAll(nodes);
185.1036 +            }
185.1037 +
185.1038 +        }
185.1039 +
185.1040 +        if (unresolvedNodes.size() > 1) {
185.1041 +            Collections.sort(unresolvedNodes, PythonUtils.ATTRIBUTE_NAME_NODE_COMPARATOR);
185.1042 +            //Collections.sort(unusedNodes, PythonUtils.NODE_POS_COMPARATOR);
185.1043 +        }
185.1044 +
185.1045 +        return unresolvedNodes;
185.1046 +    }
185.1047 +
185.1048 +    public List<PythonTree> getUnresolved(PythonParserResult info) {
185.1049 +        List<PythonTree> unresolvedNodes = new ArrayList<>();
185.1050 +        Set<String> builtin = getBuiltin(info);
185.1051 +
185.1052 +        for (ScopeInfo scopeInfo : scopes.values()) {
185.1053 +            Set<String> unresolved = new HashSet<>();
185.1054 +            Map<String, SymInfo> tbl = scopeInfo.tbl;
185.1055 +            for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
185.1056 +                SymInfo symInfo = entry.getValue();
185.1057 +                boolean isUnresolved = symInfo.isUnresolved();
185.1058 +                if (!isUnresolved && symInfo.isFree()) {
185.1059 +                    // Peek up scope stack
185.1060 +                    String name = entry.getKey();
185.1061 +                    SymInfo sym = symInfo;
185.1062 +                    ScopeInfo scope = scopeInfo;
185.1063 +                    while (sym != null && sym.isFree()) {
185.1064 +                        scope = scope.up;
185.1065 +                        while (scope != null && scope.kind == CLASSSCOPE) {
185.1066 +                            scope = scope.up;
185.1067 +                        }
185.1068 +                        sym = scope.tbl.get(name);
185.1069 +                    }
185.1070 +                    if (sym == null) {
185.1071 +                        isUnresolved = true;
185.1072 +                    } else {
185.1073 +                        isUnresolved = sym.isUnresolved();
185.1074 +                    }
185.1075 +                }
185.1076 +                if (isUnresolved) {
185.1077 +                    String key = entry.getKey();
185.1078 +                    if (!builtin.contains(key)) {
185.1079 +                        unresolved.add(key);
185.1080 +                    }
185.1081 +                }
185.1082 +            }
185.1083 +
185.1084 +
185.1085 +            if (unresolved.size() > 0) {
185.1086 +                // Check imports and see if it's resolved by existing imports
185.1087 +                PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
185.1088 +                // TODO - cache system libraries!
185.1089 +                // TODO - make method which doesn't create elements for these guys!
185.1090 +//                Set<IndexedElement> elements = index.getImportedElements("", NameKind.PREFIX, PythonIndex.ALL_SCOPE, imports, importsFrom);
185.1091 +//                for (IndexedElement e : elements) {
185.1092 +//                    unresolved.remove(e.getName());
185.1093 +//                }
185.1094 +                Set<String> wildcarded = index.getImportedFromWildcards(importsFrom);
185.1095 +                unresolved.removeAll(wildcarded);
185.1096 +
185.1097 +                if (unresolved.size() > 0) {
185.1098 +                    NameFinder finder = new NameFinder(unresolved);
185.1099 +                    List<Name> nodes = finder.run(scopeInfo.scope_node);
185.1100 +                    unresolvedNodes.addAll(nodes);
185.1101 +                }
185.1102 +            }
185.1103 +        }
185.1104 +
185.1105 +        if (unresolvedNodes.size() > 1) {
185.1106 +            Collections.sort(unresolvedNodes, PythonUtils.ATTRIBUTE_NAME_NODE_COMPARATOR);
185.1107 +            //Collections.sort(unusedNodes, PythonUtils.NODE_POS_COMPARATOR);
185.1108 +        }
185.1109 +
185.1110 +        return unresolvedNodes;
185.1111 +    }
185.1112 +
185.1113 +    public List<PythonTree> getUnused(boolean skipSelf, boolean skipParams) { // not used for unused imports, see separate method
185.1114 +        List<PythonTree> unusedNodes = new ArrayList<>();
185.1115 +
185.1116 +        for (ScopeInfo scopeInfo : scopes.values()) {
185.1117 +            if (scopeInfo.kind != FUNCSCOPE) {
185.1118 +                continue;
185.1119 +            }
185.1120 +            Set<String> unused = new HashSet<>();
185.1121 +            Map<String, SymInfo> tbl = scopeInfo.tbl;
185.1122 +            for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
185.1123 +                SymInfo symInfo = entry.getValue();
185.1124 +                if (symInfo.isUnused(scopeInfo) && (!skipParams || !symInfo.isParameter())) {
185.1125 +                    String key = entry.getKey();
185.1126 +                    if (skipSelf && "self".equals(key)) { // NOI18N
185.1127 +                        continue;
185.1128 +                    }
185.1129 +                    unused.add(key);
185.1130 +                }
185.1131 +            }
185.1132 +
185.1133 +            if (unused.size() > 0) {
185.1134 +                NameFinder finder = new NameFinder(unused);
185.1135 +                List<Name> nodes = finder.run(scopeInfo.scope_node);
185.1136 +                unusedNodes.addAll(nodes);
185.1137 +            }
185.1138 +        }
185.1139 +
185.1140 +        if (unusedNodes.size() > 1) {
185.1141 +            Collections.sort(unusedNodes, PythonUtils.NAME_NODE_COMPARATOR);
185.1142 +            //Collections.sort(unusedNodes, PythonUtils.NODE_POS_COMPARATOR);
185.1143 +        }
185.1144 +
185.1145 +        return unusedNodes;
185.1146 +    }
185.1147 +
185.1148 +    private static class NameFinder extends Visitor {
185.1149 +        private Set<String> names;
185.1150 +        private List<Name> nodes = new ArrayList<>();
185.1151 +        private PythonTree acceptDef;
185.1152 +
185.1153 +        private NameFinder(Set<String> names) {
185.1154 +            this.names = names;
185.1155 +        }
185.1156 +
185.1157 +        @Override
185.1158 +        public Object visitClassDef(ClassDef node) throws Exception {
185.1159 +            // Don't look in nested scopes
185.1160 +            if (node != acceptDef) {
185.1161 +                return null;
185.1162 +            }
185.1163 +            return super.visitClassDef(node);
185.1164 +        }
185.1165 +
185.1166 +        @Override
185.1167 +        public Object visitFunctionDef(FunctionDef node) throws Exception {
185.1168 +            // Don't look in nested scopes
185.1169 +            if (node != acceptDef) {
185.1170 +                return null;
185.1171 +            }
185.1172 +            return super.visitFunctionDef(node);
185.1173 +        }
185.1174 +
185.1175 +        @Override
185.1176 +        public Object visitName(Name node) throws Exception {
185.1177 +            String name = node.getInternalId();
185.1178 +            if (names.contains(name)) {
185.1179 +                nodes.add(node);
185.1180 +            }
185.1181 +
185.1182 +            return super.visitName(node);
185.1183 +        }
185.1184 +
185.1185 +        public List<Name> run(PythonTree node) {
185.1186 +            this.acceptDef = node;
185.1187 +            try {
185.1188 +                visit(node);
185.1189 +            } catch (Exception ex) {
185.1190 +                Exceptions.printStackTrace(ex);
185.1191 +            }
185.1192 +
185.1193 +            return nodes;
185.1194 +        }
185.1195 +    }
185.1196 +    private static Set<String> builtinSymbols;
185.1197 +
185.1198 +    private Set<String> getBuiltin(PythonParserResult info) {
185.1199 +        if (builtinSymbols == null) {
185.1200 +            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
185.1201 +            builtinSymbols = index.getBuiltinSymbols();
185.1202 +        }
185.1203 +
185.1204 +        return builtinSymbols;
185.1205 +    }
185.1206 +
185.1207 +    public void error(String msg, boolean err, PythonTree node) throws Exception {
185.1208 +        assert node != null;
185.1209 +        // TODO - record and register with the hints manager?
185.1210 +        OffsetRange range = PythonAstUtils.getRange(node);
185.1211 +
185.1212 +        if (errors == null) {
185.1213 +            errors = new ArrayList<>();
185.1214 +        }
185.1215 +        Error error = new DefaultError(null, msg, null, fileObject, range.getStart(), range.getEnd(), err ? Severity.ERROR : Severity.WARNING);
185.1216 +        errors.add(error);
185.1217 +    }
185.1218 +
185.1219 +    public String getFilename() {
185.1220 +        return FileUtil.getFileDisplayName(fileObject);
185.1221 +    }
185.1222 +
185.1223 +    public Map<PythonTree, ScopeInfo> getScopes() {
185.1224 +        return scopes;
185.1225 +    }
185.1226 +
185.1227 +    public List<Import> getImports() {
185.1228 +        return imports;
185.1229 +    }
185.1230 +
185.1231 +    public List<ImportFrom> getImportsFrom() {
185.1232 +        return importsFrom;
185.1233 +    }
185.1234 +
185.1235 +    public boolean isTopLevel(PythonTree node) {
185.1236 +        return topLevelImports.contains(node);
185.1237 +    }
185.1238 +
185.1239 +    public List<PythonTree> getMainImports() {
185.1240 +        return mainImports;
185.1241 +    }
185.1242 +
185.1243 +    public Set<PythonTree> getTopLevelImports() {
185.1244 +        return topLevelImports;
185.1245 +    }
185.1246 +
185.1247 +    public List<Str> getPublicSymbols() {
185.1248 +        return publicSymbols;
185.1249 +    }
185.1250 +}
   186.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   186.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/Bundle.properties	Sun Sep 13 11:47:42 2015 +0200
   186.3 @@ -0,0 +1,284 @@
   186.4 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   186.5 +#
   186.6 +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   186.7 +#
   186.8 +# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   186.9 +# Other names may be trademarks of their respective owners.
  186.10 +#
  186.11 +# The contents of this file are subject to the terms of either the GNU
  186.12 +# General Public License Version 2 only ("GPL") or the Common
  186.13 +# Development and Distribution License("CDDL") (collectively, the
  186.14 +# "License"). You may not use this file except in compliance with the
  186.15 +# License. You can obtain a copy of the License at
  186.16 +# http://www.netbeans.org/cddl-gplv2.html
  186.17 +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  186.18 +# specific language governing permissions and limitations under the
  186.19 +# License.  When distributing the software, include this License Header
  186.20 +# Notice in each file and include the License file at
  186.21 +# nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  186.22 +# particular file as subject to the "Classpath" exception as provided
  186.23 +# by Oracle in the GPL Version 2 section of the License file that
  186.24 +# accompanied this code. If applicable, add the following below the
  186.25 +# License Header, with the fields enclosed by brackets [] replaced by
  186.26 +# your own identifying information:
  186.27 +# "Portions Copyrighted [year] [name of copyright owner]"
  186.28 +#
  186.29 +# Contributor(s):
  186.30 +#
  186.31 +# The Original Software is NetBeans. The Initial Developer of the Original
  186.32 +# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  186.33 +# Microsystems, Inc. All Rights Reserved.
  186.34 +#
  186.35 +# If you wish your version of this file to be governed by only the CDDL
  186.36 +# or only the GPL Version 2, indicate your decision by adding
  186.37 +# "[Contributor] elects to include this software in this distribution
  186.38 +# under the [CDDL or GPL Version 2] license." If you do not indicate a
  186.39 +# single choice of license, a recipient has the option to distribute
  186.40 +# your version of this file under either the CDDL, the GPL Version 2 or
  186.41 +# to extend the choice of license to its licensees as provided above.
  186.42 +# However, if you add GPL Version 2 code and therefore, elected the GPL
  186.43 +# Version 2 license, then the option applies only if the new code is
  186.44 +# made subject to such option by the copyright holder.
  186.45 +
  186.46 +# Formating options
  186.47 +
  186.48 +LBL_TabsAndIndents=Tabs and Indents
  186.49 +LBL_CodeGeneration=Code Generation
  186.50 +LBL_Alignment=Alignment
  186.51 +LBL_Wrapping=Wrapping
  186.52 +LBL_BlankLines=Blank Lines
  186.53 +LBL_Spaces=Spaces
  186.54 +LBL_Imports=Imports
  186.55 +
  186.56 +LBL_bp_SAME_LINE=Same Line
  186.57 +LBL_bp_NEW_LINE=New Line
  186.58 +LBL_bp_NEW_LINE_HALF_INDENTED=New Line Half Indented
  186.59 +LBL_bp_NEW_LINE_INDENTED= New Line Indented
  186.60 +    
  186.61 +LBL_bg_GENERATE=Generate
  186.62 +LBL_bg_LEAVE_ALONE=Leave Alone
  186.63 +LBL_bg_ELIMINATE=Eliminate
  186.64 +       
  186.65 +LBL_wrp_WRAP_ALWAYS=Always
  186.66 +LBL_wrp_WRAP_IF_LONG=If Long
  186.67 +LBL_wrp_WRAP_NEVER=Never
  186.68 +
  186.69 +LBL_imp_COMMENT_OUT=Comment Out
  186.70 +LBL_imp_LEAVE_ALONE=Leave Alone
  186.71 +LBL_imp_DELETE=Delete
  186.72 +
  186.73 +LBL_ExpandTabToSpaces=&Expand Tab to Spaces
  186.74 +LBL_TabSize=&Tab Size:
  186.75 +LBL_IndentSize=&Indentation Size:
  186.76 +LBL_ContinuationIndentSize=&Continuation Indentation Size:
  186.77 +LBL_LabelIndent=&Label Indentation\:
  186.78 +LBL_AbsoluteLabelIndent=&Absolute Label Indentation
  186.79 +LBL_IndentTopLevelClassMemberts=Indent Top Level Class &Members
  186.80 +LBL_AddLeadingStarInComment=Add Leading Star In Comment
  186.81 +LBL_RightMargin=&Right Margin:
  186.82 +
  186.83 +LBL_Naming=Naming\:
  186.84 +LBL_PreferLongerNames=Prefer Longer Names
  186.85 +LBL_Prefix=Prefix
  186.86 +LBL_Suffix=Suffix
  186.87 +LBL_Field=Field\:
  186.88 +LBL_StaticField=Static Field\:
  186.89 +LBL_Parameter=Parameter\:
  186.90 +LBL_LocalVariable=Local Variable\:
  186.91 +LBL_Misc=Misc\:
  186.92 +LBL_QualifyFieldAccess=Qualify Field Access
  186.93 +LBL_UseIsForBooleanGetters=Use Is For Boolean Getters
  186.94 +LBL_AddOverrideAnnotation=Add Override Annotation
  186.95 +LBL_FinalMofier=Final Modifier\:
  186.96 +LBL_ParametersFinal=Make Generated Parameters Final
  186.97 +LBL_LocalVariablesFinal=Make Generated Local variables Final
  186.98 +LBL_ImportOredering=Import Ordering\:
  186.99 +LBL_ImportUp=Move Up
 186.100 +LBL_ImportDown=Move Down
 186.101 +LBL_blBeforePackage=Before &Package\:
 186.102 +LBL_blAfterPackage=After P&ackage\:
 186.103 +LBL_blBeforeImports=Before &Imports\:
 186.104 +LBL_blAfterImports=After I&mports\:
 186.105 +LBL_blBeforeClass=Before &Class\:
 186.106 +LBL_blAfterClass=After C&lass\:
 186.107 +LBL_blAfterClassHeader=After Class &Header\:
 186.108 +LBL_blBeforeFields=Before &Field\:
 186.109 +LBL_blAfterFields=After Fi&eld\:
 186.110 +LBL_blBeforeMethods=Before &Method\:
 186.111 +LBL_blAfterMethods=After Me&thod\:
 186.112 +
 186.113 +LBL_BeforeKeywords=Before Keywords
 186.114 +LBL_spaceBeforeWhile="while"
 186.115 +LBL_spaceBeforeElse="else"
 186.116 +LBL_spaceBeforeCatch="catch"
 186.117 +LBL_spaceBeforeFinally="finally"
 186.118 +
 186.119 +LBL_BeforeParentheses=Before Parentheses
 186.120 +LBL_spaceBeforeMethodDeclParen=Method Declaration
 186.121 +LBL_spaceBeforeMethodCallParen=Method Call
 186.122 +LBL_spaceBeforeIfParen="if"
 186.123 +LBL_spaceBeforeForParen="for"
 186.124 +LBL_spaceBeforeWhileParen="while"
 186.125 +LBL_spaceBeforeCatchParen="catch"
 186.126 +LBL_spaceBeforeSwitchParen="switch"
 186.127 +LBL_spaceBeforeSynchronizedParen="synchronized"
 186.128 +LBL_spaceBeforeAnnotationParen=Annotation Parameters
 186.129 +
 186.130 +LBL_AroundOperators=Around Operators
 186.131 +LBL_spaceAroundUnaryOps=Unary Operators
 186.132 +LBL_spaceAroundBinaryOps=Binary Operators
 186.133 +LBL_spaceAroundTernaryOps=Ternary Operators
 186.134 +LBL_spaceAroundAssignOps=Assignment Operators
 186.135 +
 186.136 +LBL_BeforeLeftBraces=Before Left Braces
 186.137 +LBL_spaceBeforeClassDeclLeftBrace=Class Declaration
 186.138 +LBL_spaceBeforeMethodDeclLeftBrace=Method Declaration
 186.139 +LBL_spaceBeforeIfLeftBrace="if"
 186.140 +LBL_spaceBeforeElseLeftBrace="else"
 186.141 +LBL_spaceBeforeWhileLeftBrace="while"
 186.142 +LBL_spaceBeforeForLeftBrace="for"
 186.143 +LBL_spaceBeforeDoLeftBrace="do"
 186.144 +LBL_spaceBeforeSwitchLeftBrace="switch"
 186.145 +LBL_spaceBeforeTryLeftBrace="try"
 186.146 +LBL_spaceBeforeCatchLeftBrace="catch"
 186.147 +LBL_spaceBeforeFinallyLeftBrace="finally"
 186.148 +LBL_spaceBeforeSynchronizedLeftBrace="synchronized"
 186.149 +LBL_spaceBeforeStaticInitLeftBrace=Static Initializer
 186.150 +LBL_spaceBeforeArrayInitLeftBrace=Array Initializer
 186.151 +
 186.152 +LBL_WithinParentheses=Within Parentheses
 186.153 +LBL_spaceWithinParens=Parentheses
 186.154 +LBL_spaceWithinMethodDeclParens=Method Declaration
 186.155 +LBL_spaceWithinMethodCallParens=Method Call
 186.156 +LBL_spaceWithinIfParens="if"
 186.157 +LBL_spaceWithinForParens="for"
 186.158 +LBL_spaceWithinWhileParens="while"
 186.159 +LBL_spaceWithinSwitchParens="switch"
 186.160 +LBL_spaceWithinCatchParens="catch"
 186.161 +LBL_spaceWithinSynchronizedParens="synchronized"
 186.162 +LBL_spaceWithinTypeCastParens=Type Cast
 186.163 +LBL_spaceWithinAnnotationParens=Annotation
 186.164 +LBL_spaceWithinBraces=Braces
 186.165 +LBL_spaceWithinArrayInitBrackets=Array Initializer Brackets
 186.166 +
 186.167 +LBL_Other=Other
 186.168 +LBL_spaceBeforeComma=Before Comma
 186.169 +LBL_spaceAfterComma=After Comma
 186.170 +LBL_spaceBeforeSemi=Before Semicolon
 186.171 +LBL_spaceAfterSemi=After Semicolon
 186.172 +LBL_spaceBeforeColon=Before Colon
 186.173 +LBL_spaceAfterColon=After Colon
 186.174 +LBL_spaceAfterTypeCast=After Type Cast
 186.175 +LBL_wrp_extendsImplementsKeyword=&Extends/Implements Keyword\: 
 186.176 +LBL_wrp_extendsImplementsList=E&xtends/Implements List\:
 186.177 +LBL_wrp_methodParameters=Method &Parameters\:
 186.178 +LBL_wrp_throwsKeyword=&Throws Keyword\:
 186.179 +LBL_wrp_throwsList=Th&rows List\:
 186.180 +LBL_wrp_methodCallArgs=Method Call &Arguments\:
 186.181 +LBL_wrp_annotationArgs=Annotation Arg&uments\:
 186.182 +LBL_wrp_chainedMethodCalls=C&hained Method Calls\:
 186.183 +LBL_wrp_arrayInit=Array Initiali&zer\:
 186.184 +LBL_wrp_for=&For\:
 186.185 +LBL_wrp_forStatement=F&or Statement\:
 186.186 +LBL_wrp_ifStatement=&If Statement\:
 186.187 +LBL_wrp_whileStatement=&While Statement\:
 186.188 +LBL_wrp_doWhileStatement=&Do ... While Statement
 186.189 +LBL_wrp_assert=&Assert\:
 186.190 +LBL_wrp_enumConstants=Enum &Constants\:
 186.191 +LBL_wrp_annotations=A&nnotations\:
 186.192 +LBL_wrp_binaryOps=&Binary Operators\:
 186.193 +LBL_wrp_ternaryOps=Ternar&y Operators\:
 186.194 +LBL_wrp_assignOps=Assi&gnment Operators\:
 186.195 +
 186.196 +LBL_br_bracesPlacement=Braces Placement
 186.197 +LBL_br_bracesGeneration=Braces Generation
 186.198 +LBL_al_newLines=New Lines
 186.199 +LBL_al_multilineAlignment=Multiline Alignment
 186.200 +LBL_nl_Else="&else"
 186.201 +LBL_nl_While="w&hile"
 186.202 +LBL_nl_Catch="c&atch"
 186.203 +LBL_nl_Finally="finall&y"
 186.204 +LBL_nl_Modifiers=after modifie&rs
 186.205 +LBL_am_MethodParams=Method &Parameters
 186.206 +LBL_am_CallArgs=Method Call Arg&uments
 186.207 +LBL_am_AnnotationArgs=&Annotation Arguments
 186.208 +LBL_an_Implements=I&mplements List
 186.209 +LBL_am_Throws=&Throws List
 186.210 +LBL_am_Paren=Parenthesize&d
 186.211 +LBL_am_BinaryOp=&Binary Operators
 186.212 +LBL_am_TernaryOp=Ter&nary Operators
 186.213 +LBL_am_Assign=Assi&gnment
 186.214 +LBL_am_For=&For
 186.215 +LBL_am_ArrayInit=Array Initiali&zer
 186.216 +
 186.217 +LBL_IndentCasesFromSwitch=Indent Case Statements In &Switch
 186.218 +
 186.219 +# Following entries (marked) as samples are used as examples in the formating
 186.220 +# options. It is highly discourage to localize them unless absolutely necessary.
 186.221 +
 186.222 +SAMPLE_Default=public class ClassA extends Object implements InterfaceA, InterfaceB, InterfaceC
 186.223 +SAMPLE_TabsIndents=public class ClassA extends Object implements InterfaceA, InterfaceB, InterfaceC {
 186.224 +SAMPLE_AlignBraces=@Anno(paramA="a Value", paramB="bValue")\n
 186.225 +SAMPLE_Wrapping=@Anno(paramA="a Value", paramB="bValue")
 186.226 +SAMPLE_BlankLines=package org.netbeans.samples;
 186.227 +
 186.228 +SAMPLE_Imports=\
 186.229 +# Copyright 2008\n\
 186.230 +"""My Module"""\n\
 186.231 +\n\
 186.232 +import sys\n\
 186.233 +import wsgiref.handlers\n\
 186.234 +from google.appengine.ext.webapp.util import run_wsgi_app\n\
 186.235 +from google.appengine.ext import webapp\n\
 186.236 +from google.appengine.ext import db\n\
 186.237 +import os\n\
 186.238 +\n\
 186.239 +\n\
 186.240 +from google.appengine.api import users\n\
 186.241 +import google.appengine.api.test\n\
 186.242 +from google.appengine.api import users\n\
 186.243 +\n\
 186.244 +from google.appengine.api import users\n\
 186.245 +from google.appengine.api import users\n\
 186.246 +import string\n\
 186.247 +from google.appengine.ext.webapp import template as FooBar\n\
 186.248 +from google.appengine.ext.webapp.util import login_required\n\
 186.249 +import random\n\
 186.250 +import datetime\n
 186.251 +
 186.252 +#\n\
 186.253 +#new_str = swapcase("foo")
 186.254 +
 186.255 +
 186.256 +# Newlines on the following line since space prefixes are ignored by the .properties loader
 186.257 +SAMPLE_Spaces=\
 186.258 +def func( arg1 ,arg2 ,\
 186.259 +\n  arg3 = 3,  arg  =  4):\
 186.260 +\n\
 186.261 +\n  if pos!=-1 and optval[ pos-1 ].isspace():\
 186.262 +\n      x=5+2\
 186.263 +\n\
 186.264 +\nmodeDict = { 'r':'rb','w':'wb', \\\
 186.265 +\n   'a' : 'r+b' }\
 186.266 +\nx = 2; y=3 ; z    =      5\n
 186.267 +
 186.268 +
 186.269 +nlFinallyCheckBox1.text="finall&y"
 186.270 +
 186.271 +
 186.272 +AN_Preview=Preview
 186.273 +AD_Preview=Preview
 186.274 +FmtImports.formatImportsCb.text=Organize Imports during formatting
 186.275 +FmtImports.removeDuplicateCb.text=Remove Duplicate Imports
 186.276 +FmtImports.systemLibsCb.text=Separate out system libraries
 186.277 +FmtImports.onePerLineCb.text=Prefer one import per line
 186.278 +FmtImports.cleanupLabel.text=Unused imports:
 186.279 +FmtImports.preferSymbols.text=Prefer symbol imports
 186.280 +FmtImports.sortImportsCb.text=Sort Alphabetically
 186.281 +FmtSpaces.addAroundOp.text=Add spaces around operators
 186.282 +FmtSpaces.removeInParam.text=But remove in parameter assignments
 186.283 +FmtSpaces.removeInParen.text=Remove spaces inside ( ), { }, and [ ]
 186.284 +FmtSpaces.addAfterComma.text=Add spaces after commas
 186.285 +FmtSpaces.removeBeforeSep.text=Remove spaces before separators ( : , ; )
 186.286 +FmtSpaces.collapseSpacesCb.text=Collapse multiple spaces
 186.287 +FmtImports.sepFromImpCb.text=Separate "from" and "import" statements
   187.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   187.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtAlignment.form	Sun Sep 13 11:47:42 2015 +0200
   187.3 @@ -0,0 +1,350 @@
   187.4 +<?xml version="1.0" encoding="UTF-8" ?>
   187.5 +
   187.6 +<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   187.7 +  <Properties>
   187.8 +    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   187.9 +      <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_Alignment" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  187.10 +    </Property>
  187.11 +    <Property name="opaque" type="boolean" value="false"/>
  187.12 +  </Properties>
  187.13 +  <AuxValues>
  187.14 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
  187.15 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  187.16 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  187.17 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
  187.18 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  187.19 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
  187.20 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
  187.21 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  187.22 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  187.23 +  </AuxValues>
  187.24 +
  187.25 +  <Layout>
  187.26 +    <DimensionLayout dim="0">
  187.27 +      <Group type="103" groupAlignment="0" attributes="0">
  187.28 +          <Group type="102" attributes="0">
  187.29 +              <Group type="103" groupAlignment="0" attributes="0">
  187.30 +                  <Group type="102" alignment="0" attributes="0">
  187.31 +                      <EmptySpace min="-2" max="-2" attributes="0"/>
  187.32 +                      <Component id="amParenthesizedCheckBox1" min="-2" max="-2" attributes="0"/>
  187.33 +                  </Group>
  187.34 +                  <Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
  187.35 +                      <Group type="102" alignment="0" attributes="1">
  187.36 +                          <Component id="newLinesLabel" min="-2" max="-2" attributes="0"/>
  187.37 +                          <EmptySpace max="-2" attributes="0"/>
  187.38 +                          <Component id="jSeparator1" max="32767" attributes="0"/>
  187.39 +                      </Group>
  187.40 +                      <Group type="102" alignment="0" attributes="1">
  187.41 +                          <Component id="multilineAlignmentLabel" min="-2" max="-2" attributes="0"/>
  187.42 +                          <EmptySpace max="-2" attributes="0"/>
  187.43 +                          <Component id="jSeparator2" max="32767" attributes="1"/>
  187.44 +                      </Group>
  187.45 +                      <Group type="102" alignment="0" attributes="0">
  187.46 +                          <EmptySpace max="-2" attributes="0"/>
  187.47 +                          <Group type="103" groupAlignment="0" attributes="0">
  187.48 +                              <Component id="amThrowsCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/>
  187.49 +                              <Component id="amBinaryOpCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/>
  187.50 +                              <Component id="amAssignCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/>
  187.51 +                              <Component id="amAnnotationArgsCheckBox" alignment="0" min="-2" max="-2" attributes="1"/>
  187.52 +                              <Component id="nlElseCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
  187.53 +                              <Component id="nlWhileCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
  187.54 +                              <Component id="nlCatchCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
  187.55 +                              <Component id="amMethodParamsCheckBox" alignment="0" min="-2" max="-2" attributes="1"/>
  187.56 +                          </Group>
  187.57 +                          <EmptySpace min="-2" max="-2" attributes="0"/>
  187.58 +                          <Group type="103" groupAlignment="0" attributes="0">
  187.59 +                              <Component id="amCallArgsCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
  187.60 +                              <Component id="nlModifiersCheckBox" min="-2" max="-2" attributes="0"/>
  187.61 +                              <Component id="nlFinallyCheckBox" min="-2" max="-2" attributes="0"/>
  187.62 +                              <Component id="amImplementsCheckBox1" min="-2" max="-2" attributes="0"/>
  187.63 +                              <Component id="amArrayInitCheckBox1" min="-2" max="-2" attributes="0"/>
  187.64 +                              <Component id="amTernaryOpCheckBox1" min="-2" max="-2" attributes="0"/>
  187.65 +                              <Component id="amForCheckBox1" min="-2" max="-2" attributes="0"/>
  187.66 +                          </Group>
  187.67 +                      </Group>
  187.68 +                  </Group>
  187.69 +              </Group>
  187.70 +              <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
  187.71 +          </Group>
  187.72 +      </Group>
  187.73 +    </DimensionLayout>
  187.74 +    <DimensionLayout dim="1">
  187.75 +      <Group type="103" groupAlignment="0" attributes="0">
  187.76 +          <Group type="102" alignment="0" attributes="0">
  187.77 +              <Group type="103" groupAlignment="0" attributes="0">
  187.78 +                  <Group type="102" attributes="0">
  187.79 +                      <EmptySpace max="-2" attributes="0"/>
  187.80 +                      <Component id="newLinesLabel" min="-2" max="-2" attributes="1"/>
  187.81 +                  </Group>
  187.82 +                  <Group type="102" attributes="0">
  187.83 +                      <EmptySpace min="-2" pref="17" max="-2" attributes="0"/>
  187.84 +                      <Component id="jSeparator1" min="-2" pref="10" max="-2" attributes="0"/>
  187.85 +                  </Group>
  187.86 +              </Group>
  187.87 +              <EmptySpace max="-2" attributes="0"/>
  187.88 +              <Group type="103" groupAlignment="3" attributes="0">
  187.89 +                  <Component id="nlElseCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
  187.90 +                  <Component id="nlFinallyCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
  187.91 +              </Group>
  187.92 +              <EmptySpace max="-2" attributes="0"/>
  187.93 +              <Group type="103" groupAlignment="3" attributes="0">
  187.94 +                  <Component id="nlWhileCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
  187.95 +                  <Component id="nlModifiersCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
  187.96 +              </Group>
  187.97 +              <Group type="103" groupAlignment="0" attributes="0">
  187.98 +                  <Group type="102" attributes="0">
  187.99 +                      <EmptySpace max="-2" attributes="0"/>
 187.100 +                      <Component id="nlCatchCheckBox" min="-2" max="-2" attributes="0"/>
 187.101 +                      <EmptySpace type="separate" max="-2" attributes="0"/>
 187.102 +                      <Component id="multilineAlignmentLabel" min="-2" max="-2" attributes="0"/>
 187.103 +                  </Group>
 187.104 +                  <Group type="102" attributes="0">
 187.105 +                      <EmptySpace min="-2" pref="44" max="-2" attributes="0"/>
 187.106 +                      <Component id="jSeparator2" min="-2" pref="10" max="-2" attributes="0"/>
 187.107 +                  </Group>
 187.108 +              </Group>
 187.109 +              <EmptySpace min="-2" max="-2" attributes="0"/>
 187.110 +              <Group type="103" groupAlignment="3" attributes="0">
 187.111 +                  <Component id="amMethodParamsCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
 187.112 +                  <Component id="amCallArgsCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
 187.113 +              </Group>
 187.114 +              <EmptySpace min="-2" max="-2" attributes="0"/>
 187.115 +              <Group type="103" groupAlignment="3" attributes="0">
 187.116 +                  <Component id="amAnnotationArgsCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
 187.117 +                  <Component id="amImplementsCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
 187.118 +              </Group>
 187.119 +              <EmptySpace max="-2" attributes="0"/>
 187.120 +              <Group type="103" groupAlignment="3" attributes="0">
 187.121 +                  <Component id="amThrowsCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
 187.122 +                  <Component id="amArrayInitCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
 187.123 +              </Group>
 187.124 +              <EmptySpace max="-2" attributes="0"/>
 187.125 +              <Group type="103" groupAlignment="3" attributes="0">
 187.126 +                  <Component id="amBinaryOpCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
 187.127 +                  <Component id="amTernaryOpCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
 187.128 +              </Group>
 187.129 +              <EmptySpace max="-2" attributes="0"/>
 187.130 +              <Group type="103" groupAlignment="3" attributes="0">
 187.131 +                  <Component id="amAssignCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
 187.132 +                  <Component id="amForCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
 187.133 +              </Group>
 187.134 +              <EmptySpace min="-2" max="-2" attributes="0"/>
 187.135 +              <Component id="amParenthesizedCheckBox1" min="-2" max="-2" attributes="0"/>
 187.136 +              <EmptySpace max="32767" attributes="0"/>
 187.137 +          </Group>
 187.138 +      </Group>
 187.139 +    </DimensionLayout>
 187.140 +  </Layout>
 187.141 +  <SubComponents>
 187.142 +    <Component class="javax.swing.JLabel" name="newLinesLabel">
 187.143 +      <Properties>
 187.144 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.145 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_al_newLines" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.146 +        </Property>
 187.147 +      </Properties>
 187.148 +    </Component>
 187.149 +    <Component class="javax.swing.JCheckBox" name="nlElseCheckBox">
 187.150 +      <Properties>
 187.151 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.152 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_nl_Else" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.153 +        </Property>
 187.154 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.155 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.156 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.157 +          </Border>
 187.158 +        </Property>
 187.159 +      </Properties>
 187.160 +    </Component>
 187.161 +    <Component class="javax.swing.JCheckBox" name="nlWhileCheckBox">
 187.162 +      <Properties>
 187.163 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.164 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_nl_While" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.165 +        </Property>
 187.166 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.167 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.168 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.169 +          </Border>
 187.170 +        </Property>
 187.171 +      </Properties>
 187.172 +    </Component>
 187.173 +    <Component class="javax.swing.JCheckBox" name="nlCatchCheckBox">
 187.174 +      <Properties>
 187.175 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.176 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_nl_Catch" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.177 +        </Property>
 187.178 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.179 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.180 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.181 +          </Border>
 187.182 +        </Property>
 187.183 +      </Properties>
 187.184 +    </Component>
 187.185 +    <Component class="javax.swing.JCheckBox" name="nlFinallyCheckBox">
 187.186 +      <Properties>
 187.187 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.188 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_nl_Finally" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.189 +        </Property>
 187.190 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.191 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.192 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.193 +          </Border>
 187.194 +        </Property>
 187.195 +      </Properties>
 187.196 +    </Component>
 187.197 +    <Component class="javax.swing.JCheckBox" name="nlModifiersCheckBox">
 187.198 +      <Properties>
 187.199 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.200 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_nl_Modifiers" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.201 +        </Property>
 187.202 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.203 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.204 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.205 +          </Border>
 187.206 +        </Property>
 187.207 +      </Properties>
 187.208 +    </Component>
 187.209 +    <Component class="javax.swing.JLabel" name="multilineAlignmentLabel">
 187.210 +      <Properties>
 187.211 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.212 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_al_multilineAlignment" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.213 +        </Property>
 187.214 +      </Properties>
 187.215 +    </Component>
 187.216 +    <Component class="javax.swing.JCheckBox" name="amMethodParamsCheckBox">
 187.217 +      <Properties>
 187.218 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.219 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_MethodParams" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.220 +        </Property>
 187.221 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.222 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.223 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.224 +          </Border>
 187.225 +        </Property>
 187.226 +      </Properties>
 187.227 +    </Component>
 187.228 +    <Component class="javax.swing.JCheckBox" name="amCallArgsCheckBox">
 187.229 +      <Properties>
 187.230 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.231 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_CallArgs" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.232 +        </Property>
 187.233 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.234 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.235 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.236 +          </Border>
 187.237 +        </Property>
 187.238 +      </Properties>
 187.239 +    </Component>
 187.240 +    <Component class="javax.swing.JCheckBox" name="amAnnotationArgsCheckBox">
 187.241 +      <Properties>
 187.242 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.243 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_AnnotationArgs" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.244 +        </Property>
 187.245 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.246 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.247 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.248 +          </Border>
 187.249 +        </Property>
 187.250 +      </Properties>
 187.251 +    </Component>
 187.252 +    <Component class="javax.swing.JCheckBox" name="amImplementsCheckBox1">
 187.253 +      <Properties>
 187.254 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.255 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_an_Implements" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.256 +        </Property>
 187.257 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.258 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.259 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.260 +          </Border>
 187.261 +        </Property>
 187.262 +      </Properties>
 187.263 +    </Component>
 187.264 +    <Component class="javax.swing.JCheckBox" name="amThrowsCheckBox1">
 187.265 +      <Properties>
 187.266 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.267 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_Throws" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.268 +        </Property>
 187.269 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.270 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.271 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.272 +          </Border>
 187.273 +        </Property>
 187.274 +      </Properties>
 187.275 +    </Component>
 187.276 +    <Component class="javax.swing.JCheckBox" name="amArrayInitCheckBox1">
 187.277 +      <Properties>
 187.278 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.279 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_ArrayInit" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.280 +        </Property>
 187.281 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.282 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.283 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.284 +          </Border>
 187.285 +        </Property>
 187.286 +      </Properties>
 187.287 +    </Component>
 187.288 +    <Component class="javax.swing.JCheckBox" name="amBinaryOpCheckBox1">
 187.289 +      <Properties>
 187.290 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.291 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_BinaryOp" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.292 +        </Property>
 187.293 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.294 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.295 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.296 +          </Border>
 187.297 +        </Property>
 187.298 +      </Properties>
 187.299 +    </Component>
 187.300 +    <Component class="javax.swing.JCheckBox" name="amTernaryOpCheckBox1">
 187.301 +      <Properties>
 187.302 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.303 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_TernaryOp" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.304 +        </Property>
 187.305 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.306 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.307 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.308 +          </Border>
 187.309 +        </Property>
 187.310 +      </Properties>
 187.311 +    </Component>
 187.312 +    <Component class="javax.swing.JCheckBox" name="amAssignCheckBox1">
 187.313 +      <Properties>
 187.314 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.315 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_Assign" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.316 +        </Property>
 187.317 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.318 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.319 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.320 +          </Border>
 187.321 +        </Property>
 187.322 +      </Properties>
 187.323 +    </Component>
 187.324 +    <Component class="javax.swing.JCheckBox" name="amForCheckBox1">
 187.325 +      <Properties>
 187.326 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.327 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_For" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.328 +        </Property>
 187.329 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.330 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.331 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.332 +          </Border>
 187.333 +        </Property>
 187.334 +      </Properties>
 187.335 +    </Component>
 187.336 +    <Component class="javax.swing.JCheckBox" name="amParenthesizedCheckBox1">
 187.337 +      <Properties>
 187.338 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 187.339 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_am_Paren" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 187.340 +        </Property>
 187.341 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 187.342 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 187.343 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 187.344 +          </Border>
 187.345 +        </Property>
 187.346 +      </Properties>
 187.347 +    </Component>
 187.348 +    <Component class="javax.swing.JSeparator" name="jSeparator1">
 187.349 +    </Component>
 187.350 +    <Component class="javax.swing.JSeparator" name="jSeparator2">
 187.351 +    </Component>
 187.352 +  </SubComponents>
 187.353 +</Form>
   188.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   188.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtAlignment.java	Sun Sep 13 11:47:42 2015 +0200
   188.3 @@ -0,0 +1,309 @@
   188.4 +/*
   188.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   188.6 + *
   188.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   188.8 + *
   188.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  188.10 + * Other names may be trademarks of their respective owners.
  188.11 + *
  188.12 + * The contents of this file are subject to the terms of either the GNU
  188.13 + * General Public License Version 2 only ("GPL") or the Common
  188.14 + * Development and Distribution License("CDDL") (collectively, the
  188.15 + * "License"). You may not use this file except in compliance with the
  188.16 + * License. You can obtain a copy of the License at
  188.17 + * http://www.netbeans.org/cddl-gplv2.html
  188.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  188.19 + * specific language governing permissions and limitations under the
  188.20 + * License.  When distributing the software, include this License Header
  188.21 + * Notice in each file and include the License file at
  188.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  188.23 + * particular file as subject to the "Classpath" exception as provided
  188.24 + * by Oracle in the GPL Version 2 section of the License file that
  188.25 + * accompanied this code. If applicable, add the following below the
  188.26 + * License Header, with the fields enclosed by brackets [] replaced by
  188.27 + * your own identifying information:
  188.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  188.29 + *
  188.30 + * Contributor(s):
  188.31 + *
  188.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  188.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  188.34 + * Microsystems, Inc. All Rights Reserved.
  188.35 + *
  188.36 + * If you wish your version of this file to be governed by only the CDDL
  188.37 + * or only the GPL Version 2, indicate your decision by adding
  188.38 + * "[Contributor] elects to include this software in this distribution
  188.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  188.40 + * single choice of license, a recipient has the option to distribute
  188.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  188.42 + * to extend the choice of license to its licensees as provided above.
  188.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  188.44 + * Version 2 license, then the option applies only if the new code is
  188.45 + * made subject to such option by the copyright holder.
  188.46 + */
  188.47 +
  188.48 +package org.netbeans.modules.python.source.ui;
  188.49 +
  188.50 +//import org.netbeans.modules.python.editor.options.CodeStyle.WrapStyle;
  188.51 +//import static org.netbeans.modules.python.editor.options.FmtOptions.*;
  188.52 +//import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
  188.53 +//import org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport;
  188.54 +//import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
  188.55 +
  188.56 +
  188.57 +/**
  188.58 + *
  188.59 + * @author  phrebejk
  188.60 + */
  188.61 +public class FmtAlignment extends javax.swing.JPanel {
  188.62 +    
  188.63 +    /** Creates new form FmtAlignment */
  188.64 +    public FmtAlignment() {
  188.65 +        initComponents();
  188.66 +/*
  188.67 +        nlElseCheckBox.putClientProperty(OPTION_ID, placeElseOnNewLine);
  188.68 +        nlWhileCheckBox.putClientProperty(OPTION_ID, placeWhileOnNewLine);
  188.69 +        nlCatchCheckBox.putClientProperty(OPTION_ID, placeCatchOnNewLine);
  188.70 +        nlFinallyCheckBox.putClientProperty(OPTION_ID, placeFinallyOnNewLine);
  188.71 +        nlModifiersCheckBox.putClientProperty(OPTION_ID, placeNewLineAfterModifiers);
  188.72 +        amMethodParamsCheckBox.putClientProperty(OPTION_ID, alignMultilineMethodParams);
  188.73 +        amCallArgsCheckBox.putClientProperty(OPTION_ID, alignMultilineCallArgs);
  188.74 +        amAnnotationArgsCheckBox.putClientProperty(OPTION_ID, alignMultilineAnnotationArgs);
  188.75 +        amArrayInitCheckBox1.putClientProperty(OPTION_ID, alignMultilineArrayInit);
  188.76 +        amAssignCheckBox1.putClientProperty(OPTION_ID, alignMultilineAssignment);
  188.77 +        amBinaryOpCheckBox1.putClientProperty(OPTION_ID, alignMultilineBinaryOp);
  188.78 +        amForCheckBox1.putClientProperty(OPTION_ID, alignMultilineFor);
  188.79 +        amImplementsCheckBox1.putClientProperty(OPTION_ID, alignMultilineImplements);
  188.80 +        amParenthesizedCheckBox1.putClientProperty(OPTION_ID, alignMultilineParenthesized);
  188.81 +        amTernaryOpCheckBox1.putClientProperty(OPTION_ID, alignMultilineTernaryOp);
  188.82 +        amThrowsCheckBox1.putClientProperty(OPTION_ID, alignMultilineThrows);
  188.83 +    }
  188.84 +    
  188.85 +    public static PreferencesCustomizer.Factory getController() {
  188.86 +        return new CategorySupport.Factory("alignment", FmtAlignment.class, //NOI18N
  188.87 +                org.openide.util.NbBundle.getMessage(FmtAlignment.class, "SAMPLE_AlignBraces"), // NOI18N
  188.88 +                new String[] { FmtOptions.wrapAnnotations, WrapStyle.WRAP_ALWAYS.name() },
  188.89 +                new String[] { FmtOptions.wrapArrayInit, WrapStyle.WRAP_ALWAYS.name() },
  188.90 +                new String[] { FmtOptions.wrapAssert, WrapStyle.WRAP_ALWAYS.name() },
  188.91 +                new String[] { FmtOptions.wrapAssignOps, WrapStyle.WRAP_ALWAYS.name() },
  188.92 +                new String[] { FmtOptions.wrapBinaryOps, WrapStyle.WRAP_ALWAYS.name() },
  188.93 +                new String[] { FmtOptions.wrapChainedMethodCalls, WrapStyle.WRAP_ALWAYS.name() },
  188.94 +                new String[] { FmtOptions.wrapDoWhileStatement, WrapStyle.WRAP_ALWAYS.name() },
  188.95 +                new String[] { FmtOptions.wrapEnumConstants, WrapStyle.WRAP_ALWAYS.name() },
  188.96 +                new String[] { FmtOptions.wrapExtendsImplementsKeyword, WrapStyle.WRAP_ALWAYS.name() },
  188.97 +                new String[] { FmtOptions.wrapExtendsImplementsList, WrapStyle.WRAP_ALWAYS.name() },
  188.98 +                new String[] { FmtOptions.wrapFor, WrapStyle.WRAP_ALWAYS.name() },
  188.99 +                new String[] { FmtOptions.wrapForStatement, WrapStyle.WRAP_ALWAYS.name() },
 188.100 +                new String[] { FmtOptions.wrapIfStatement, WrapStyle.WRAP_ALWAYS.name() },
 188.101 +                new String[] { FmtOptions.wrapMethodCallArgs, WrapStyle.WRAP_ALWAYS.name() },
 188.102 +                new String[] { FmtOptions.wrapAnnotationArgs, WrapStyle.WRAP_ALWAYS.name() },
 188.103 +                new String[] { FmtOptions.wrapMethodParams, WrapStyle.WRAP_ALWAYS.name() },
 188.104 +                new String[] { FmtOptions.wrapTernaryOps, WrapStyle.WRAP_ALWAYS.name() },
 188.105 +                new String[] { FmtOptions.wrapThrowsKeyword, WrapStyle.WRAP_ALWAYS.name() },
 188.106 +                new String[] { FmtOptions.wrapThrowsList, WrapStyle.WRAP_ALWAYS.name() },
 188.107 +                new String[] { FmtOptions.wrapWhileStatement, WrapStyle.WRAP_ALWAYS.name() }  );
 188.108 + */
 188.109 +    }
 188.110 +    
 188.111 +    /** This method is called from within the constructor to
 188.112 +     * initialize the form.
 188.113 +     * WARNING: Do NOT modify this code. The content of this method is
 188.114 +     * always regenerated by the Form Editor.
 188.115 +     */
 188.116 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
 188.117 +    private void initComponents() {
 188.118 +
 188.119 +        newLinesLabel = new javax.swing.JLabel();
 188.120 +        nlElseCheckBox = new javax.swing.JCheckBox();
 188.121 +        nlWhileCheckBox = new javax.swing.JCheckBox();
 188.122 +        nlCatchCheckBox = new javax.swing.JCheckBox();
 188.123 +        nlFinallyCheckBox = new javax.swing.JCheckBox();
 188.124 +        nlModifiersCheckBox = new javax.swing.JCheckBox();
 188.125 +        multilineAlignmentLabel = new javax.swing.JLabel();
 188.126 +        amMethodParamsCheckBox = new javax.swing.JCheckBox();
 188.127 +        amCallArgsCheckBox = new javax.swing.JCheckBox();
 188.128 +        amAnnotationArgsCheckBox = new javax.swing.JCheckBox();
 188.129 +        amImplementsCheckBox1 = new javax.swing.JCheckBox();
 188.130 +        amThrowsCheckBox1 = new javax.swing.JCheckBox();
 188.131 +        amArrayInitCheckBox1 = new javax.swing.JCheckBox();
 188.132 +        amBinaryOpCheckBox1 = new javax.swing.JCheckBox();
 188.133 +        amTernaryOpCheckBox1 = new javax.swing.JCheckBox();
 188.134 +        amAssignCheckBox1 = new javax.swing.JCheckBox();
 188.135 +        amForCheckBox1 = new javax.swing.JCheckBox();
 188.136 +        amParenthesizedCheckBox1 = new javax.swing.JCheckBox();
 188.137 +        jSeparator1 = new javax.swing.JSeparator();
 188.138 +        jSeparator2 = new javax.swing.JSeparator();
 188.139 +
 188.140 +        setName(org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_Alignment")); // NOI18N
 188.141 +        setOpaque(false);
 188.142 +
 188.143 +        org.openide.awt.Mnemonics.setLocalizedText(newLinesLabel, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_al_newLines")); // NOI18N
 188.144 +
 188.145 +        org.openide.awt.Mnemonics.setLocalizedText(nlElseCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Else")); // NOI18N
 188.146 +        nlElseCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.147 +
 188.148 +        org.openide.awt.Mnemonics.setLocalizedText(nlWhileCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_While")); // NOI18N
 188.149 +        nlWhileCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.150 +
 188.151 +        org.openide.awt.Mnemonics.setLocalizedText(nlCatchCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Catch")); // NOI18N
 188.152 +        nlCatchCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.153 +
 188.154 +        org.openide.awt.Mnemonics.setLocalizedText(nlFinallyCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Finally")); // NOI18N
 188.155 +        nlFinallyCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.156 +
 188.157 +        org.openide.awt.Mnemonics.setLocalizedText(nlModifiersCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Modifiers")); // NOI18N
 188.158 +        nlModifiersCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.159 +
 188.160 +        org.openide.awt.Mnemonics.setLocalizedText(multilineAlignmentLabel, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_al_multilineAlignment")); // NOI18N
 188.161 +
 188.162 +        org.openide.awt.Mnemonics.setLocalizedText(amMethodParamsCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_MethodParams")); // NOI18N
 188.163 +        amMethodParamsCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.164 +
 188.165 +        org.openide.awt.Mnemonics.setLocalizedText(amCallArgsCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_CallArgs")); // NOI18N
 188.166 +        amCallArgsCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.167 +
 188.168 +        org.openide.awt.Mnemonics.setLocalizedText(amAnnotationArgsCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_AnnotationArgs")); // NOI18N
 188.169 +        amAnnotationArgsCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.170 +
 188.171 +        org.openide.awt.Mnemonics.setLocalizedText(amImplementsCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_an_Implements")); // NOI18N
 188.172 +        amImplementsCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.173 +
 188.174 +        org.openide.awt.Mnemonics.setLocalizedText(amThrowsCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_Throws")); // NOI18N
 188.175 +        amThrowsCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.176 +
 188.177 +        org.openide.awt.Mnemonics.setLocalizedText(amArrayInitCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_ArrayInit")); // NOI18N
 188.178 +        amArrayInitCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.179 +
 188.180 +        org.openide.awt.Mnemonics.setLocalizedText(amBinaryOpCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_BinaryOp")); // NOI18N
 188.181 +        amBinaryOpCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.182 +
 188.183 +        org.openide.awt.Mnemonics.setLocalizedText(amTernaryOpCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_TernaryOp")); // NOI18N
 188.184 +        amTernaryOpCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.185 +
 188.186 +        org.openide.awt.Mnemonics.setLocalizedText(amAssignCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_Assign")); // NOI18N
 188.187 +        amAssignCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.188 +
 188.189 +        org.openide.awt.Mnemonics.setLocalizedText(amForCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_For")); // NOI18N
 188.190 +        amForCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.191 +
 188.192 +        org.openide.awt.Mnemonics.setLocalizedText(amParenthesizedCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_Paren")); // NOI18N
 188.193 +        amParenthesizedCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 188.194 +
 188.195 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
 188.196 +        this.setLayout(layout);
 188.197 +        layout.setHorizontalGroup(
 188.198 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 188.199 +            .addGroup(layout.createSequentialGroup()
 188.200 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 188.201 +                    .addGroup(layout.createSequentialGroup()
 188.202 +                        .addContainerGap()
 188.203 +                        .addComponent(amParenthesizedCheckBox1))
 188.204 +                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
 188.205 +                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
 188.206 +                            .addComponent(newLinesLabel)
 188.207 +                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 188.208 +                            .addComponent(jSeparator1))
 188.209 +                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
 188.210 +                            .addComponent(multilineAlignmentLabel)
 188.211 +                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 188.212 +                            .addComponent(jSeparator2))
 188.213 +                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
 188.214 +                            .addContainerGap()
 188.215 +                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 188.216 +                                .addComponent(amThrowsCheckBox1)
 188.217 +                                .addComponent(amBinaryOpCheckBox1)
 188.218 +                                .addComponent(amAssignCheckBox1)
 188.219 +                                .addComponent(amAnnotationArgsCheckBox)
 188.220 +                                .addComponent(nlElseCheckBox)
 188.221 +                                .addComponent(nlWhileCheckBox)
 188.222 +                                .addComponent(nlCatchCheckBox)
 188.223 +                                .addComponent(amMethodParamsCheckBox))
 188.224 +                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 188.225 +                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 188.226 +                                .addComponent(amCallArgsCheckBox)
 188.227 +                                .addComponent(nlModifiersCheckBox)
 188.228 +                                .addComponent(nlFinallyCheckBox)
 188.229 +                                .addComponent(amImplementsCheckBox1)
 188.230 +                                .addComponent(amArrayInitCheckBox1)
 188.231 +                                .addComponent(amTernaryOpCheckBox1)
 188.232 +                                .addComponent(amForCheckBox1)))))
 188.233 +                .addGap(0, 0, 0))
 188.234 +        );
 188.235 +        layout.setVerticalGroup(
 188.236 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 188.237 +            .addGroup(layout.createSequentialGroup()
 188.238 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 188.239 +                    .addGroup(layout.createSequentialGroup()
 188.240 +                        .addContainerGap()
 188.241 +                        .addComponent(newLinesLabel))
 188.242 +                    .addGroup(layout.createSequentialGroup()
 188.243 +                        .addGap(17, 17, 17)
 188.244 +                        .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)))
 188.245 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 188.246 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 188.247 +                    .addComponent(nlElseCheckBox)
 188.248 +                    .addComponent(nlFinallyCheckBox))
 188.249 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 188.250 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 188.251 +                    .addComponent(nlWhileCheckBox)
 188.252 +                    .addComponent(nlModifiersCheckBox))
 188.253 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 188.254 +                    .addGroup(layout.createSequentialGroup()
 188.255 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 188.256 +                        .addComponent(nlCatchCheckBox)
 188.257 +                        .addGap(18, 18, 18)
 188.258 +                        .addComponent(multilineAlignmentLabel))
 188.259 +                    .addGroup(layout.createSequentialGroup()
 188.260 +                        .addGap(44, 44, 44)
 188.261 +                        .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)))
 188.262 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 188.263 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 188.264 +                    .addComponent(amMethodParamsCheckBox)
 188.265 +                    .addComponent(amCallArgsCheckBox))
 188.266 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 188.267 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 188.268 +                    .addComponent(amAnnotationArgsCheckBox)
 188.269 +                    .addComponent(amImplementsCheckBox1))
 188.270 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 188.271 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 188.272 +                    .addComponent(amThrowsCheckBox1)
 188.273 +                    .addComponent(amArrayInitCheckBox1))
 188.274 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 188.275 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 188.276 +                    .addComponent(amBinaryOpCheckBox1)
 188.277 +                    .addComponent(amTernaryOpCheckBox1))
 188.278 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 188.279 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 188.280 +                    .addComponent(amAssignCheckBox1)
 188.281 +                    .addComponent(amForCheckBox1))
 188.282 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 188.283 +                .addComponent(amParenthesizedCheckBox1)
 188.284 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 188.285 +        );
 188.286 +    }// </editor-fold>//GEN-END:initComponents
 188.287 +    
 188.288 +    
 188.289 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 188.290 +    private javax.swing.JCheckBox amAnnotationArgsCheckBox;
 188.291 +    private javax.swing.JCheckBox amArrayInitCheckBox1;
 188.292 +    private javax.swing.JCheckBox amAssignCheckBox1;
 188.293 +    private javax.swing.JCheckBox amBinaryOpCheckBox1;
 188.294 +    private javax.swing.JCheckBox amCallArgsCheckBox;
 188.295 +    private javax.swing.JCheckBox amForCheckBox1;
 188.296 +    private javax.swing.JCheckBox amImplementsCheckBox1;
 188.297 +    private javax.swing.JCheckBox amMethodParamsCheckBox;
 188.298 +    private javax.swing.JCheckBox amParenthesizedCheckBox1;
 188.299 +    private javax.swing.JCheckBox amTernaryOpCheckBox1;
 188.300 +    private javax.swing.JCheckBox amThrowsCheckBox1;
 188.301 +    private javax.swing.JSeparator jSeparator1;
 188.302 +    private javax.swing.JSeparator jSeparator2;
 188.303 +    private javax.swing.JLabel multilineAlignmentLabel;
 188.304 +    private javax.swing.JLabel newLinesLabel;
 188.305 +    private javax.swing.JCheckBox nlCatchCheckBox;
 188.306 +    private javax.swing.JCheckBox nlElseCheckBox;
 188.307 +    private javax.swing.JCheckBox nlFinallyCheckBox;
 188.308 +    private javax.swing.JCheckBox nlModifiersCheckBox;
 188.309 +    private javax.swing.JCheckBox nlWhileCheckBox;
 188.310 +    // End of variables declaration//GEN-END:variables
 188.311 +    
 188.312 +}
   189.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   189.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtBlankLines.form	Sun Sep 13 11:47:42 2015 +0200
   189.3 @@ -0,0 +1,284 @@
   189.4 +<?xml version="1.0" encoding="UTF-8" ?>
   189.5 +
   189.6 +<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   189.7 +  <Properties>
   189.8 +    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   189.9 +      <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_BlankLines" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  189.10 +    </Property>
  189.11 +    <Property name="opaque" type="boolean" value="false"/>
  189.12 +  </Properties>
  189.13 +  <AuxValues>
  189.14 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
  189.15 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  189.16 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  189.17 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
  189.18 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  189.19 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
  189.20 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
  189.21 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  189.22 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  189.23 +  </AuxValues>
  189.24 +
  189.25 +  <Layout>
  189.26 +    <DimensionLayout dim="0">
  189.27 +      <Group type="103" groupAlignment="0" attributes="0">
  189.28 +          <Group type="102" attributes="0">
  189.29 +              <Group type="103" groupAlignment="0" attributes="0">
  189.30 +                  <Component id="bPackageLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  189.31 +                  <Component id="aPackageLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  189.32 +                  <Component id="bImportsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  189.33 +                  <Component id="aImports" alignment="0" min="-2" max="-2" attributes="0"/>
  189.34 +                  <Component id="bClassLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  189.35 +                  <Component id="aClassLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  189.36 +                  <Component id="aClassHeaderLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  189.37 +                  <Component id="bFieldsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  189.38 +                  <Component id="aFieldsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  189.39 +                  <Component id="bMethodsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  189.40 +                  <Component id="aMethodsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  189.41 +              </Group>
  189.42 +              <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
  189.43 +              <Group type="103" groupAlignment="0" attributes="0">
  189.44 +                  <Component id="aMethodsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  189.45 +                  <Component id="bMethodsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  189.46 +                  <Component id="aFieldsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  189.47 +                  <Component id="bFieldsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  189.48 +                  <Component id="aClassHeaderField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  189.49 +                  <Component id="aClassField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  189.50 +                  <Component id="bClassField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  189.51 +                  <Component id="aImportsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  189.52 +                  <Component id="bImportsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  189.53 +                  <Component id="aPackageField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  189.54 +                  <Component id="bPackageField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  189.55 +              </Group>
  189.56 +          </Group>
  189.57 +      </Group>
  189.58 +    </DimensionLayout>
  189.59 +    <DimensionLayout dim="1">
  189.60 +      <Group type="103" groupAlignment="0" attributes="0">
  189.61 +          <Group type="102" attributes="0">
  189.62 +              <Group type="103" groupAlignment="3" attributes="0">
  189.63 +                  <Component id="bPackageField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  189.64 +                  <Component id="bPackageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  189.65 +              </Group>
  189.66 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  189.67 +              <Group type="103" groupAlignment="3" attributes="0">
  189.68 +                  <Component id="aPackageField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  189.69 +                  <Component id="aPackageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  189.70 +              </Group>
  189.71 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  189.72 +              <Group type="103" groupAlignment="3" attributes="0">
  189.73 +                  <Component id="bImportsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  189.74 +                  <Component id="bImportsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  189.75 +              </Group>
  189.76 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  189.77 +              <Group type="103" groupAlignment="3" attributes="0">
  189.78 +                  <Component id="aImportsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  189.79 +                  <Component id="aImports" alignment="3" min="-2" max="-2" attributes="0"/>
  189.80 +              </Group>
  189.81 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  189.82 +              <Group type="103" groupAlignment="3" attributes="0">
  189.83 +                  <Component id="bClassField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  189.84 +                  <Component id="bClassLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  189.85 +              </Group>
  189.86 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  189.87 +              <Group type="103" groupAlignment="3" attributes="0">
  189.88 +                  <Component id="aClassField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  189.89 +                  <Component id="aClassLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  189.90 +              </Group>
  189.91 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  189.92 +              <Group type="103" groupAlignment="3" attributes="0">
  189.93 +                  <Component id="aClassHeaderField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  189.94 +                  <Component id="aClassHeaderLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  189.95 +              </Group>
  189.96 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  189.97 +              <Group type="103" groupAlignment="3" attributes="0">
  189.98 +                  <Component id="bFieldsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  189.99 +                  <Component id="bFieldsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
 189.100 +              </Group>
 189.101 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
 189.102 +              <Group type="103" groupAlignment="3" attributes="0">
 189.103 +                  <Component id="aFieldsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
 189.104 +                  <Component id="aFieldsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
 189.105 +              </Group>
 189.106 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
 189.107 +              <Group type="103" groupAlignment="3" attributes="0">
 189.108 +                  <Component id="bMethodsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
 189.109 +                  <Component id="bMethodsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
 189.110 +              </Group>
 189.111 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
 189.112 +              <Group type="103" groupAlignment="3" attributes="0">
 189.113 +                  <Component id="aMethodsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
 189.114 +                  <Component id="aMethodsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
 189.115 +              </Group>
 189.116 +          </Group>
 189.117 +      </Group>
 189.118 +    </DimensionLayout>
 189.119 +  </Layout>
 189.120 +  <SubComponents>
 189.121 +    <Component class="javax.swing.JLabel" name="bPackageLabel">
 189.122 +      <Properties>
 189.123 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 189.124 +          <ComponentRef name="bPackageField"/>
 189.125 +        </Property>
 189.126 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 189.127 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blBeforePackage" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 189.128 +        </Property>
 189.129 +      </Properties>
 189.130 +    </Component>
 189.131 +    <Component class="javax.swing.JTextField" name="bPackageField">
 189.132 +      <Properties>
 189.133 +        <Property name="columns" type="int" value="5"/>
 189.134 +      </Properties>
 189.135 +    </Component>
 189.136 +    <Component class="javax.swing.JLabel" name="aPackageLabel">
 189.137 +      <Properties>
 189.138 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 189.139 +          <ComponentRef name="aPackageField"/>
 189.140 +        </Property>
 189.141 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 189.142 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blAfterPackage" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 189.143 +        </Property>
 189.144 +      </Properties>
 189.145 +    </Component>
 189.146 +    <Component class="javax.swing.JTextField" name="aPackageField">
 189.147 +      <Properties>
 189.148 +        <Property name="columns" type="int" value="5"/>
 189.149 +      </Properties>
 189.150 +    </Component>
 189.151 +    <Component class="javax.swing.JLabel" name="bImportsLabel">
 189.152 +      <Properties>
 189.153 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 189.154 +          <ComponentRef name="bImportsField"/>
 189.155 +        </Property>
 189.156 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 189.157 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blBeforeImports" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 189.158 +        </Property>
 189.159 +      </Properties>
 189.160 +    </Component>
 189.161 +    <Component class="javax.swing.JTextField" name="bImportsField">
 189.162 +      <Properties>
 189.163 +        <Property name="columns" type="int" value="5"/>
 189.164 +      </Properties>
 189.165 +    </Component>
 189.166 +    <Component class="javax.swing.JLabel" name="aImports">
 189.167 +      <Properties>
 189.168 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 189.169 +          <ComponentRef name="aImportsField"/>
 189.170 +        </Property>
 189.171 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 189.172 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blAfterImports" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 189.173 +        </Property>
 189.174 +      </Properties>
 189.175 +    </Component>
 189.176 +    <Component class="javax.swing.JTextField" name="aImportsField">
 189.177 +      <Properties>
 189.178 +        <Property name="columns" type="int" value="5"/>
 189.179 +      </Properties>
 189.180 +    </Component>
 189.181 +    <Component class="javax.swing.JLabel" name="bClassLabel">
 189.182 +      <Properties>
 189.183 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 189.184 +          <ComponentRef name="bClassField"/>
 189.185 +        </Property>
 189.186 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 189.187 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blBeforeClass" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 189.188 +        </Property>
 189.189 +      </Properties>
 189.190 +    </Component>
 189.191 +    <Component class="javax.swing.JTextField" name="bClassField">
 189.192 +      <Properties>
 189.193 +        <Property name="columns" type="int" value="5"/>
 189.194 +      </Properties>
 189.195 +    </Component>
 189.196 +    <Component class="javax.swing.JLabel" name="aClassLabel">
 189.197 +      <Properties>
 189.198 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 189.199 +          <ComponentRef name="aClassField"/>
 189.200 +        </Property>
 189.201 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 189.202 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blAfterClass" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 189.203 +        </Property>
 189.204 +      </Properties>
 189.205 +    </Component>
 189.206 +    <Component class="javax.swing.JTextField" name="aClassField">
 189.207 +      <Properties>
 189.208 +        <Property name="columns" type="int" value="5"/>
 189.209 +      </Properties>
 189.210 +    </Component>
 189.211 +    <Component class="javax.swing.JLabel" name="aClassHeaderLabel">
 189.212 +      <Properties>
 189.213 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 189.214 +          <ComponentRef name="aClassHeaderField"/>
 189.215 +        </Property>
 189.216 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 189.217 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blAfterClassHeader" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 189.218 +        </Property>
 189.219 +      </Properties>
 189.220 +    </Component>
 189.221 +    <Component class="javax.swing.JTextField" name="aClassHeaderField">
 189.222 +      <Properties>
 189.223 +        <Property name="columns" type="int" value="5"/>
 189.224 +      </Properties>
 189.225 +    </Component>
 189.226 +    <Component class="javax.swing.JLabel" name="bFieldsLabel">
 189.227 +      <Properties>
 189.228 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 189.229 +          <ComponentRef name="bFieldsField"/>
 189.230 +        </Property>
 189.231 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 189.232 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blBeforeFields" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 189.233 +        </Property>
 189.234 +      </Properties>
 189.235 +    </Component>
 189.236 +    <Component class="javax.swing.JTextField" name="bFieldsField">
 189.237 +      <Properties>
 189.238 +        <Property name="columns" type="int" value="5"/>
 189.239 +      </Properties>
 189.240 +    </Component>
 189.241 +    <Component class="javax.swing.JLabel" name="aFieldsLabel">
 189.242 +      <Properties>
 189.243 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 189.244 +          <ComponentRef name="aFieldsField"/>
 189.245 +        </Property>
 189.246 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 189.247 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blAfterFields" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 189.248 +        </Property>
 189.249 +      </Properties>
 189.250 +    </Component>
 189.251 +    <Component class="javax.swing.JTextField" name="aFieldsField">
 189.252 +      <Properties>
 189.253 +        <Property name="columns" type="int" value="5"/>
 189.254 +      </Properties>
 189.255 +    </Component>
 189.256 +    <Component class="javax.swing.JLabel" name="bMethodsLabel">
 189.257 +      <Properties>
 189.258 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 189.259 +          <ComponentRef name="bMethodsField"/>
 189.260 +        </Property>
 189.261 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 189.262 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blBeforeMethods" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 189.263 +        </Property>
 189.264 +      </Properties>
 189.265 +    </Component>
 189.266 +    <Component class="javax.swing.JTextField" name="bMethodsField">
 189.267 +      <Properties>
 189.268 +        <Property name="columns" type="int" value="5"/>
 189.269 +      </Properties>
 189.270 +    </Component>
 189.271 +    <Component class="javax.swing.JLabel" name="aMethodsLabel">
 189.272 +      <Properties>
 189.273 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 189.274 +          <ComponentRef name="aMethodsField"/>
 189.275 +        </Property>
 189.276 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 189.277 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_blAfterMethods" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 189.278 +        </Property>
 189.279 +      </Properties>
 189.280 +    </Component>
 189.281 +    <Component class="javax.swing.JTextField" name="aMethodsField">
 189.282 +      <Properties>
 189.283 +        <Property name="columns" type="int" value="5"/>
 189.284 +      </Properties>
 189.285 +    </Component>
 189.286 +  </SubComponents>
 189.287 +</Form>
   190.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   190.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtBlankLines.java	Sun Sep 13 11:47:42 2015 +0200
   190.3 @@ -0,0 +1,295 @@
   190.4 +/*
   190.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   190.6 + *
   190.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   190.8 + *
   190.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  190.10 + * Other names may be trademarks of their respective owners.
  190.11 + *
  190.12 + * The contents of this file are subject to the terms of either the GNU
  190.13 + * General Public License Version 2 only ("GPL") or the Common
  190.14 + * Development and Distribution License("CDDL") (collectively, the
  190.15 + * "License"). You may not use this file except in compliance with the
  190.16 + * License. You can obtain a copy of the License at
  190.17 + * http://www.netbeans.org/cddl-gplv2.html
  190.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  190.19 + * specific language governing permissions and limitations under the
  190.20 + * License.  When distributing the software, include this License Header
  190.21 + * Notice in each file and include the License file at
  190.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  190.23 + * particular file as subject to the "Classpath" exception as provided
  190.24 + * by Oracle in the GPL Version 2 section of the License file that
  190.25 + * accompanied this code. If applicable, add the following below the
  190.26 + * License Header, with the fields enclosed by brackets [] replaced by
  190.27 + * your own identifying information:
  190.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  190.29 + *
  190.30 + * Contributor(s):
  190.31 + *
  190.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  190.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  190.34 + * Microsystems, Inc. All Rights Reserved.
  190.35 + *
  190.36 + * If you wish your version of this file to be governed by only the CDDL
  190.37 + * or only the GPL Version 2, indicate your decision by adding
  190.38 + * "[Contributor] elects to include this software in this distribution
  190.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  190.40 + * single choice of license, a recipient has the option to distribute
  190.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  190.42 + * to extend the choice of license to its licensees as provided above.
  190.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  190.44 + * Version 2 license, then the option applies only if the new code is
  190.45 + * made subject to such option by the copyright holder.
  190.46 + */
  190.47 +
  190.48 +package org.netbeans.modules.python.source.ui;
  190.49 +
  190.50 +//import static org.netbeans.modules.python.editor.options.FmtOptions.*;
  190.51 +//import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
  190.52 +//import org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport;
  190.53 +//import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
  190.54 +
  190.55 +/**
  190.56 + *
  190.57 + * @author  phrebejk
  190.58 + */
  190.59 +public class FmtBlankLines extends javax.swing.JPanel {
  190.60 +    
  190.61 +    /** Creates new form FmtBlankLines */
  190.62 +    public FmtBlankLines() {
  190.63 +        initComponents();
  190.64 +/*
  190.65 +        bPackageField.putClientProperty(OPTION_ID, blankLinesBeforePackage );
  190.66 +        aPackageField.putClientProperty(OPTION_ID, blankLinesAfterPackage);
  190.67 +        bImportsField.putClientProperty(OPTION_ID, blankLinesBeforeImports);
  190.68 +        aImportsField.putClientProperty(OPTION_ID, blankLinesAfterImports);
  190.69 +        bClassField.putClientProperty(OPTION_ID, blankLinesBeforeClass);
  190.70 +        aClassField.putClientProperty(OPTION_ID, blankLinesAfterClass);
  190.71 +        aClassHeaderField.putClientProperty(OPTION_ID, blankLinesAfterClassHeader);
  190.72 +        bFieldsField.putClientProperty(OPTION_ID, blankLinesBeforeFields);
  190.73 +        aFieldsField.putClientProperty(OPTION_ID, blankLinesAfterFields);
  190.74 +        bMethodsField.putClientProperty(OPTION_ID, blankLinesBeforeMethods );
  190.75 +        aMethodsField.putClientProperty(OPTION_ID, blankLinesAfterMethods);
  190.76 +        
  190.77 +        bPackageField.addKeyListener(new NumericKeyListener());
  190.78 +        aPackageField.addKeyListener(new NumericKeyListener());
  190.79 +        bImportsField.addKeyListener(new NumericKeyListener());
  190.80 +        aImportsField.addKeyListener(new NumericKeyListener());
  190.81 +        bClassField.addKeyListener(new NumericKeyListener());
  190.82 +        aClassField.addKeyListener(new NumericKeyListener());
  190.83 +        aClassHeaderField.addKeyListener(new NumericKeyListener());
  190.84 +        bFieldsField.addKeyListener(new NumericKeyListener());
  190.85 +        aFieldsField.addKeyListener(new NumericKeyListener());
  190.86 +        bMethodsField.addKeyListener(new NumericKeyListener());
  190.87 +        aMethodsField.addKeyListener(new NumericKeyListener());
  190.88 +        
  190.89 +    }
  190.90 +    
  190.91 +    public static PreferencesCustomizer.Factory getController() {
  190.92 +        return new CategorySupport.Factory("blank-lines", FmtBlankLines.class, //NOI18N
  190.93 +                 org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "SAMPLE_BlankLines")); // NOI18N
  190.94 + */
  190.95 +    }
  190.96 +    
  190.97 +    /** This method is called from within the constructor to
  190.98 +     * initialize the form.
  190.99 +     * WARNING: Do NOT modify this code. The content of this method is
 190.100 +     * always regenerated by the Form Editor.
 190.101 +     */
 190.102 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
 190.103 +    private void initComponents() {
 190.104 +
 190.105 +        bPackageLabel = new javax.swing.JLabel();
 190.106 +        bPackageField = new javax.swing.JTextField();
 190.107 +        aPackageLabel = new javax.swing.JLabel();
 190.108 +        aPackageField = new javax.swing.JTextField();
 190.109 +        bImportsLabel = new javax.swing.JLabel();
 190.110 +        bImportsField = new javax.swing.JTextField();
 190.111 +        aImports = new javax.swing.JLabel();
 190.112 +        aImportsField = new javax.swing.JTextField();
 190.113 +        bClassLabel = new javax.swing.JLabel();
 190.114 +        bClassField = new javax.swing.JTextField();
 190.115 +        aClassLabel = new javax.swing.JLabel();
 190.116 +        aClassField = new javax.swing.JTextField();
 190.117 +        aClassHeaderLabel = new javax.swing.JLabel();
 190.118 +        aClassHeaderField = new javax.swing.JTextField();
 190.119 +        bFieldsLabel = new javax.swing.JLabel();
 190.120 +        bFieldsField = new javax.swing.JTextField();
 190.121 +        aFieldsLabel = new javax.swing.JLabel();
 190.122 +        aFieldsField = new javax.swing.JTextField();
 190.123 +        bMethodsLabel = new javax.swing.JLabel();
 190.124 +        bMethodsField = new javax.swing.JTextField();
 190.125 +        aMethodsLabel = new javax.swing.JLabel();
 190.126 +        aMethodsField = new javax.swing.JTextField();
 190.127 +
 190.128 +        setName(org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_BlankLines")); // NOI18N
 190.129 +        setOpaque(false);
 190.130 +
 190.131 +        bPackageLabel.setLabelFor(bPackageField);
 190.132 +        org.openide.awt.Mnemonics.setLocalizedText(bPackageLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforePackage")); // NOI18N
 190.133 +
 190.134 +        bPackageField.setColumns(5);
 190.135 +
 190.136 +        aPackageLabel.setLabelFor(aPackageField);
 190.137 +        org.openide.awt.Mnemonics.setLocalizedText(aPackageLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterPackage")); // NOI18N
 190.138 +
 190.139 +        aPackageField.setColumns(5);
 190.140 +
 190.141 +        bImportsLabel.setLabelFor(bImportsField);
 190.142 +        org.openide.awt.Mnemonics.setLocalizedText(bImportsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeImports")); // NOI18N
 190.143 +
 190.144 +        bImportsField.setColumns(5);
 190.145 +
 190.146 +        aImports.setLabelFor(aImportsField);
 190.147 +        org.openide.awt.Mnemonics.setLocalizedText(aImports, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterImports")); // NOI18N
 190.148 +
 190.149 +        aImportsField.setColumns(5);
 190.150 +
 190.151 +        bClassLabel.setLabelFor(bClassField);
 190.152 +        org.openide.awt.Mnemonics.setLocalizedText(bClassLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeClass")); // NOI18N
 190.153 +
 190.154 +        bClassField.setColumns(5);
 190.155 +
 190.156 +        aClassLabel.setLabelFor(aClassField);
 190.157 +        org.openide.awt.Mnemonics.setLocalizedText(aClassLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterClass")); // NOI18N
 190.158 +
 190.159 +        aClassField.setColumns(5);
 190.160 +
 190.161 +        aClassHeaderLabel.setLabelFor(aClassHeaderField);
 190.162 +        org.openide.awt.Mnemonics.setLocalizedText(aClassHeaderLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterClassHeader")); // NOI18N
 190.163 +
 190.164 +        aClassHeaderField.setColumns(5);
 190.165 +
 190.166 +        bFieldsLabel.setLabelFor(bFieldsField);
 190.167 +        org.openide.awt.Mnemonics.setLocalizedText(bFieldsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeFields")); // NOI18N
 190.168 +
 190.169 +        bFieldsField.setColumns(5);
 190.170 +
 190.171 +        aFieldsLabel.setLabelFor(aFieldsField);
 190.172 +        org.openide.awt.Mnemonics.setLocalizedText(aFieldsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterFields")); // NOI18N
 190.173 +
 190.174 +        aFieldsField.setColumns(5);
 190.175 +
 190.176 +        bMethodsLabel.setLabelFor(bMethodsField);
 190.177 +        org.openide.awt.Mnemonics.setLocalizedText(bMethodsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeMethods")); // NOI18N
 190.178 +
 190.179 +        bMethodsField.setColumns(5);
 190.180 +
 190.181 +        aMethodsLabel.setLabelFor(aMethodsField);
 190.182 +        org.openide.awt.Mnemonics.setLocalizedText(aMethodsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterMethods")); // NOI18N
 190.183 +
 190.184 +        aMethodsField.setColumns(5);
 190.185 +
 190.186 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
 190.187 +        this.setLayout(layout);
 190.188 +        layout.setHorizontalGroup(
 190.189 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 190.190 +            .addGroup(layout.createSequentialGroup()
 190.191 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 190.192 +                    .addComponent(bPackageLabel)
 190.193 +                    .addComponent(aPackageLabel)
 190.194 +                    .addComponent(bImportsLabel)
 190.195 +                    .addComponent(aImports)
 190.196 +                    .addComponent(bClassLabel)
 190.197 +                    .addComponent(aClassLabel)
 190.198 +                    .addComponent(aClassHeaderLabel)
 190.199 +                    .addComponent(bFieldsLabel)
 190.200 +                    .addComponent(aFieldsLabel)
 190.201 +                    .addComponent(bMethodsLabel)
 190.202 +                    .addComponent(aMethodsLabel))
 190.203 +                .addGap(6, 6, 6)
 190.204 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 190.205 +                    .addComponent(aMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.206 +                    .addComponent(bMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.207 +                    .addComponent(aFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.208 +                    .addComponent(bFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.209 +                    .addComponent(aClassHeaderField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.210 +                    .addComponent(aClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.211 +                    .addComponent(bClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.212 +                    .addComponent(aImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.213 +                    .addComponent(bImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.214 +                    .addComponent(aPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.215 +                    .addComponent(bPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
 190.216 +        );
 190.217 +
 190.218 +        layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {aClassField, aClassHeaderField, aFieldsField, aImportsField, aMethodsField, aPackageField, bClassField, bFieldsField, bImportsField, bMethodsField, bPackageField});
 190.219 +
 190.220 +        layout.setVerticalGroup(
 190.221 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 190.222 +            .addGroup(layout.createSequentialGroup()
 190.223 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 190.224 +                    .addComponent(bPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.225 +                    .addComponent(bPackageLabel))
 190.226 +                .addGap(4, 4, 4)
 190.227 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 190.228 +                    .addComponent(aPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.229 +                    .addComponent(aPackageLabel))
 190.230 +                .addGap(4, 4, 4)
 190.231 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 190.232 +                    .addComponent(bImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.233 +                    .addComponent(bImportsLabel))
 190.234 +                .addGap(4, 4, 4)
 190.235 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 190.236 +                    .addComponent(aImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.237 +                    .addComponent(aImports))
 190.238 +                .addGap(4, 4, 4)
 190.239 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 190.240 +                    .addComponent(bClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.241 +                    .addComponent(bClassLabel))
 190.242 +                .addGap(4, 4, 4)
 190.243 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 190.244 +                    .addComponent(aClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.245 +                    .addComponent(aClassLabel))
 190.246 +                .addGap(4, 4, 4)
 190.247 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 190.248 +                    .addComponent(aClassHeaderField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.249 +                    .addComponent(aClassHeaderLabel))
 190.250 +                .addGap(4, 4, 4)
 190.251 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 190.252 +                    .addComponent(bFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.253 +                    .addComponent(bFieldsLabel))
 190.254 +                .addGap(4, 4, 4)
 190.255 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 190.256 +                    .addComponent(aFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.257 +                    .addComponent(aFieldsLabel))
 190.258 +                .addGap(4, 4, 4)
 190.259 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 190.260 +                    .addComponent(bMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.261 +                    .addComponent(bMethodsLabel))
 190.262 +                .addGap(4, 4, 4)
 190.263 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 190.264 +                    .addComponent(aMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 190.265 +                    .addComponent(aMethodsLabel)))
 190.266 +        );
 190.267 +
 190.268 +        layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {aClassField, aClassHeaderField, aFieldsField, aImportsField, aMethodsField, aPackageField, bClassField, bFieldsField, bImportsField, bMethodsField, bPackageField});
 190.269 +
 190.270 +    }// </editor-fold>//GEN-END:initComponents
 190.271 +    
 190.272 +    
 190.273 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 190.274 +    private javax.swing.JTextField aClassField;
 190.275 +    private javax.swing.JTextField aClassHeaderField;
 190.276 +    private javax.swing.JLabel aClassHeaderLabel;
 190.277 +    private javax.swing.JLabel aClassLabel;
 190.278 +    private javax.swing.JTextField aFieldsField;
 190.279 +    private javax.swing.JLabel aFieldsLabel;
 190.280 +    private javax.swing.JLabel aImports;
 190.281 +    private javax.swing.JTextField aImportsField;
 190.282 +    private javax.swing.JTextField aMethodsField;
 190.283 +    private javax.swing.JLabel aMethodsLabel;
 190.284 +    private javax.swing.JTextField aPackageField;
 190.285 +    private javax.swing.JLabel aPackageLabel;
 190.286 +    private javax.swing.JTextField bClassField;
 190.287 +    private javax.swing.JLabel bClassLabel;
 190.288 +    private javax.swing.JTextField bFieldsField;
 190.289 +    private javax.swing.JLabel bFieldsLabel;
 190.290 +    private javax.swing.JTextField bImportsField;
 190.291 +    private javax.swing.JLabel bImportsLabel;
 190.292 +    private javax.swing.JTextField bMethodsField;
 190.293 +    private javax.swing.JLabel bMethodsLabel;
 190.294 +    private javax.swing.JTextField bPackageField;
 190.295 +    private javax.swing.JLabel bPackageLabel;
 190.296 +    // End of variables declaration//GEN-END:variables
 190.297 +    
 190.298 +}
   191.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   191.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtImports.form	Sun Sep 13 11:47:42 2015 +0200
   191.3 @@ -0,0 +1,129 @@
   191.4 +<?xml version="1.0" encoding="UTF-8" ?>
   191.5 +
   191.6 +<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   191.7 +  <Properties>
   191.8 +    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   191.9 +      <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_Imports" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  191.10 +    </Property>
  191.11 +  </Properties>
  191.12 +  <AuxValues>
  191.13 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
  191.14 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  191.15 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  191.16 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
  191.17 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  191.18 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
  191.19 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
  191.20 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  191.21 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  191.22 +  </AuxValues>
  191.23 +
  191.24 +  <Layout>
  191.25 +    <DimensionLayout dim="0">
  191.26 +      <Group type="103" groupAlignment="0" attributes="0">
  191.27 +          <Group type="102" attributes="0">
  191.28 +              <Group type="103" groupAlignment="0" attributes="0">
  191.29 +                  <Component id="formatImportsCb" alignment="0" min="-2" max="-2" attributes="0"/>
  191.30 +                  <Component id="onePerLineCb" alignment="0" min="-2" max="-2" attributes="0"/>
  191.31 +                  <Component id="systemLibsCb" alignment="0" min="-2" max="-2" attributes="0"/>
  191.32 +                  <Component id="sortImportsCb" alignment="0" min="-2" max="-2" attributes="0"/>
  191.33 +                  <Component id="sepFromImpCb" alignment="0" min="-2" max="-2" attributes="0"/>
  191.34 +                  <Component id="removeDuplicateCb" alignment="0" min="-2" max="-2" attributes="0"/>
  191.35 +                  <Component id="preferSymbols" alignment="0" min="-2" max="-2" attributes="0"/>
  191.36 +                  <Group type="102" alignment="0" attributes="0">
  191.37 +                      <Component id="cleanupLabel" min="-2" max="-2" attributes="0"/>
  191.38 +                      <EmptySpace max="-2" attributes="0"/>
  191.39 +                      <Component id="cleanupCombo" min="-2" max="-2" attributes="0"/>
  191.40 +                  </Group>
  191.41 +              </Group>
  191.42 +              <EmptySpace max="32767" attributes="0"/>
  191.43 +          </Group>
  191.44 +      </Group>
  191.45 +    </DimensionLayout>
  191.46 +    <DimensionLayout dim="1">
  191.47 +      <Group type="103" groupAlignment="0" attributes="0">
  191.48 +          <Group type="102" alignment="0" attributes="0">
  191.49 +              <Component id="formatImportsCb" min="-2" max="-2" attributes="0"/>
  191.50 +              <EmptySpace type="separate" max="-2" attributes="0"/>
  191.51 +              <Component id="onePerLineCb" min="-2" max="-2" attributes="0"/>
  191.52 +              <EmptySpace max="-2" attributes="0"/>
  191.53 +              <Component id="systemLibsCb" min="-2" max="-2" attributes="0"/>
  191.54 +              <EmptySpace max="-2" attributes="0"/>
  191.55 +              <Component id="sortImportsCb" min="-2" max="-2" attributes="0"/>
  191.56 +              <EmptySpace max="-2" attributes="0"/>
  191.57 +              <Component id="sepFromImpCb" min="-2" max="-2" attributes="0"/>
  191.58 +              <EmptySpace max="-2" attributes="0"/>
  191.59 +              <Component id="removeDuplicateCb" min="-2" max="-2" attributes="0"/>
  191.60 +              <EmptySpace max="-2" attributes="0"/>
  191.61 +              <Component id="preferSymbols" min="-2" max="-2" attributes="0"/>
  191.62 +              <EmptySpace type="separate" max="-2" attributes="0"/>
  191.63 +              <Group type="103" groupAlignment="3" attributes="0">
  191.64 +                  <Component id="cleanupLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  191.65 +                  <Component id="cleanupCombo" alignment="3" min="-2" max="-2" attributes="0"/>
  191.66 +              </Group>
  191.67 +              <EmptySpace max="32767" attributes="0"/>
  191.68 +          </Group>
  191.69 +      </Group>
  191.70 +    </DimensionLayout>
  191.71 +  </Layout>
  191.72 +  <SubComponents>
  191.73 +    <Component class="javax.swing.JCheckBox" name="formatImportsCb">
  191.74 +      <Properties>
  191.75 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  191.76 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.formatImportsCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  191.77 +        </Property>
  191.78 +      </Properties>
  191.79 +    </Component>
  191.80 +    <Component class="javax.swing.JCheckBox" name="onePerLineCb">
  191.81 +      <Properties>
  191.82 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  191.83 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.onePerLineCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  191.84 +        </Property>
  191.85 +      </Properties>
  191.86 +    </Component>
  191.87 +    <Component class="javax.swing.JCheckBox" name="systemLibsCb">
  191.88 +      <Properties>
  191.89 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  191.90 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.systemLibsCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  191.91 +        </Property>
  191.92 +      </Properties>
  191.93 +    </Component>
  191.94 +    <Component class="javax.swing.JCheckBox" name="removeDuplicateCb">
  191.95 +      <Properties>
  191.96 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  191.97 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.removeDuplicateCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  191.98 +        </Property>
  191.99 +      </Properties>
 191.100 +    </Component>
 191.101 +    <Component class="javax.swing.JLabel" name="cleanupLabel">
 191.102 +      <Properties>
 191.103 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.104 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.cleanupLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 191.105 +        </Property>
 191.106 +      </Properties>
 191.107 +    </Component>
 191.108 +    <Component class="javax.swing.JComboBox" name="cleanupCombo">
 191.109 +    </Component>
 191.110 +    <Component class="javax.swing.JCheckBox" name="preferSymbols">
 191.111 +      <Properties>
 191.112 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.113 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.preferSymbols.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 191.114 +        </Property>
 191.115 +      </Properties>
 191.116 +    </Component>
 191.117 +    <Component class="javax.swing.JCheckBox" name="sortImportsCb">
 191.118 +      <Properties>
 191.119 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.120 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.sortImportsCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 191.121 +        </Property>
 191.122 +      </Properties>
 191.123 +    </Component>
 191.124 +    <Component class="javax.swing.JCheckBox" name="sepFromImpCb">
 191.125 +      <Properties>
 191.126 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.127 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtImports.sepFromImpCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 191.128 +        </Property>
 191.129 +      </Properties>
 191.130 +    </Component>
 191.131 +  </SubComponents>
 191.132 +</Form>
   192.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   192.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtImports.java	Sun Sep 13 11:47:42 2015 +0200
   192.3 @@ -0,0 +1,169 @@
   192.4 +/*
   192.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   192.6 + *
   192.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   192.8 + *
   192.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  192.10 + * Other names may be trademarks of their respective owners.
  192.11 + *
  192.12 + * The contents of this file are subject to the terms of either the GNU
  192.13 + * General Public License Version 2 only ("GPL") or the Common
  192.14 + * Development and Distribution License("CDDL") (collectively, the
  192.15 + * "License"). You may not use this file except in compliance with the
  192.16 + * License. You can obtain a copy of the License at
  192.17 + * http://www.netbeans.org/cddl-gplv2.html
  192.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  192.19 + * specific language governing permissions and limitations under the
  192.20 + * License.  When distributing the software, include this License Header
  192.21 + * Notice in each file and include the License file at
  192.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  192.23 + * particular file as subject to the "Classpath" exception as provided
  192.24 + * by Oracle in the GPL Version 2 section of the License file that
  192.25 + * accompanied this code. If applicable, add the following below the
  192.26 + * License Header, with the fields enclosed by brackets [] replaced by
  192.27 + * your own identifying information:
  192.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  192.29 + *
  192.30 + * Contributor(s):
  192.31 + *
  192.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  192.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  192.34 + * Microsystems, Inc. All Rights Reserved.
  192.35 + *
  192.36 + * If you wish your version of this file to be governed by only the CDDL
  192.37 + * or only the GPL Version 2, indicate your decision by adding
  192.38 + * "[Contributor] elects to include this software in this distribution
  192.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  192.40 + * single choice of license, a recipient has the option to distribute
  192.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  192.42 + * to extend the choice of license to its licensees as provided above.
  192.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  192.44 + * Version 2 license, then the option applies only if the new code is
  192.45 + * made subject to such option by the copyright holder.
  192.46 + */
  192.47 +
  192.48 +package org.netbeans.modules.python.source.ui;
  192.49 +
  192.50 +import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
  192.51 +import static org.netbeans.modules.python.source.ui.FmtOptions.*;
  192.52 +import static org.netbeans.modules.python.source.ui.FmtOptions.CategorySupport.OPTION_ID;
  192.53 +
  192.54 +/**
  192.55 + * Options related to imports
  192.56 + * 
  192.57 + * @author  Tor Norbye
  192.58 + */
  192.59 +public class FmtImports extends javax.swing.JPanel {
  192.60 +    
  192.61 +    /** Creates new form FmtImports */
  192.62 +    public FmtImports() {
  192.63 +        initComponents();
  192.64 +
  192.65 +        formatImportsCb.putClientProperty(OPTION_ID, formatImports);
  192.66 +        onePerLineCb.putClientProperty(OPTION_ID, oneImportPerLine);
  192.67 +        removeDuplicateCb.putClientProperty(OPTION_ID, removeDuplicates);
  192.68 +        systemLibsCb.putClientProperty(OPTION_ID, systemLibsFirst);
  192.69 +        cleanupCombo.putClientProperty(OPTION_ID, cleanupUnusedImports);
  192.70 +        preferSymbols.putClientProperty(OPTION_ID, preferSymbolImports);
  192.71 +        sortImportsCb.putClientProperty(OPTION_ID, sortImports);
  192.72 +        sepFromImpCb.putClientProperty(OPTION_ID, separateFromImps);
  192.73 +    }
  192.74 +    
  192.75 +    public static PreferencesCustomizer.Factory getController() {
  192.76 +        return new CategorySupport.Factory("imports", FmtImports.class,
  192.77 +                org.openide.util.NbBundle.getMessage(FmtImports.class, "SAMPLE_Imports"));
  192.78 +    }
  192.79 +    
  192.80 +    /** This method is called from within the constructor to
  192.81 +     * initialize the form.
  192.82 +     * WARNING: Do NOT modify this code. The content of this method is
  192.83 +     * always regenerated by the Form Editor.
  192.84 +     */
  192.85 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  192.86 +    private void initComponents() {
  192.87 +
  192.88 +        formatImportsCb = new javax.swing.JCheckBox();
  192.89 +        onePerLineCb = new javax.swing.JCheckBox();
  192.90 +        systemLibsCb = new javax.swing.JCheckBox();
  192.91 +        removeDuplicateCb = new javax.swing.JCheckBox();
  192.92 +        cleanupLabel = new javax.swing.JLabel();
  192.93 +        cleanupCombo = new javax.swing.JComboBox();
  192.94 +        preferSymbols = new javax.swing.JCheckBox();
  192.95 +        sortImportsCb = new javax.swing.JCheckBox();
  192.96 +        sepFromImpCb = new javax.swing.JCheckBox();
  192.97 +
  192.98 +        setName(org.openide.util.NbBundle.getMessage(FmtImports.class, "LBL_Imports")); // NOI18N
  192.99 +
 192.100 +        org.openide.awt.Mnemonics.setLocalizedText(formatImportsCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.formatImportsCb.text")); // NOI18N
 192.101 +
 192.102 +        org.openide.awt.Mnemonics.setLocalizedText(onePerLineCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.onePerLineCb.text")); // NOI18N
 192.103 +
 192.104 +        org.openide.awt.Mnemonics.setLocalizedText(systemLibsCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.systemLibsCb.text")); // NOI18N
 192.105 +
 192.106 +        org.openide.awt.Mnemonics.setLocalizedText(removeDuplicateCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.removeDuplicateCb.text")); // NOI18N
 192.107 +
 192.108 +        org.openide.awt.Mnemonics.setLocalizedText(cleanupLabel, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.cleanupLabel.text")); // NOI18N
 192.109 +
 192.110 +        org.openide.awt.Mnemonics.setLocalizedText(preferSymbols, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.preferSymbols.text")); // NOI18N
 192.111 +
 192.112 +        org.openide.awt.Mnemonics.setLocalizedText(sortImportsCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.sortImportsCb.text")); // NOI18N
 192.113 +
 192.114 +        org.openide.awt.Mnemonics.setLocalizedText(sepFromImpCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.sepFromImpCb.text")); // NOI18N
 192.115 +
 192.116 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
 192.117 +        this.setLayout(layout);
 192.118 +        layout.setHorizontalGroup(
 192.119 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 192.120 +            .addGroup(layout.createSequentialGroup()
 192.121 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 192.122 +                    .addComponent(formatImportsCb)
 192.123 +                    .addComponent(onePerLineCb)
 192.124 +                    .addComponent(systemLibsCb)
 192.125 +                    .addComponent(sortImportsCb)
 192.126 +                    .addComponent(sepFromImpCb)
 192.127 +                    .addComponent(removeDuplicateCb)
 192.128 +                    .addComponent(preferSymbols)
 192.129 +                    .addGroup(layout.createSequentialGroup()
 192.130 +                        .addComponent(cleanupLabel)
 192.131 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.132 +                        .addComponent(cleanupCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
 192.133 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 192.134 +        );
 192.135 +        layout.setVerticalGroup(
 192.136 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 192.137 +            .addGroup(layout.createSequentialGroup()
 192.138 +                .addComponent(formatImportsCb)
 192.139 +                .addGap(18, 18, 18)
 192.140 +                .addComponent(onePerLineCb)
 192.141 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.142 +                .addComponent(systemLibsCb)
 192.143 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.144 +                .addComponent(sortImportsCb)
 192.145 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.146 +                .addComponent(sepFromImpCb)
 192.147 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.148 +                .addComponent(removeDuplicateCb)
 192.149 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.150 +                .addComponent(preferSymbols)
 192.151 +                .addGap(18, 18, 18)
 192.152 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 192.153 +                    .addComponent(cleanupLabel)
 192.154 +                    .addComponent(cleanupCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 192.155 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 192.156 +        );
 192.157 +    }// </editor-fold>//GEN-END:initComponents
 192.158 +    
 192.159 +    
 192.160 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 192.161 +    private javax.swing.JComboBox cleanupCombo;
 192.162 +    private javax.swing.JLabel cleanupLabel;
 192.163 +    private javax.swing.JCheckBox formatImportsCb;
 192.164 +    private javax.swing.JCheckBox onePerLineCb;
 192.165 +    private javax.swing.JCheckBox preferSymbols;
 192.166 +    private javax.swing.JCheckBox removeDuplicateCb;
 192.167 +    private javax.swing.JCheckBox sepFromImpCb;
 192.168 +    private javax.swing.JCheckBox sortImportsCb;
 192.169 +    private javax.swing.JCheckBox systemLibsCb;
 192.170 +    // End of variables declaration//GEN-END:variables
 192.171 +    
 192.172 +}
   193.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   193.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtOptions.java	Sun Sep 13 11:47:42 2015 +0200
   193.3 @@ -0,0 +1,1036 @@
   193.4 +/*
   193.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   193.6 + *
   193.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   193.8 + *
   193.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  193.10 + * Other names may be trademarks of their respective owners.
  193.11 + *
  193.12 + * The contents of this file are subject to the terms of either the GNU
  193.13 + * General Public License Version 2 only ("GPL") or the Common
  193.14 + * Development and Distribution License("CDDL") (collectively, the
  193.15 + * "License"). You may not use this file except in compliance with the
  193.16 + * License. You can obtain a copy of the License at
  193.17 + * http://www.netbeans.org/cddl-gplv2.html
  193.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  193.19 + * specific language governing permissions and limitations under the
  193.20 + * License.  When distributing the software, include this License Header
  193.21 + * Notice in each file and include the License file at
  193.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  193.23 + * particular file as subject to the "Classpath" exception as provided
  193.24 + * by Oracle in the GPL Version 2 section of the License file that
  193.25 + * accompanied this code. If applicable, add the following below the
  193.26 + * License Header, with the fields enclosed by brackets [] replaced by
  193.27 + * your own identifying information:
  193.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  193.29 + *
  193.30 + * Contributor(s):
  193.31 + *
  193.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  193.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
  193.34 + * Microsystems, Inc. All Rights Reserved.
  193.35 + *
  193.36 + * If you wish your version of this file to be governed by only the CDDL
  193.37 + * or only the GPL Version 2, indicate your decision by adding
  193.38 + * "[Contributor] elects to include this software in this distribution
  193.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  193.40 + * single choice of license, a recipient has the option to distribute
  193.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  193.42 + * to extend the choice of license to its licensees as provided above.
  193.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  193.44 + * Version 2 license, then the option applies only if the new code is
  193.45 + * made subject to such option by the copyright holder.
  193.46 + */
  193.47 +package org.netbeans.modules.python.source.ui;
  193.48 +
  193.49 +import org.netbeans.modules.python.source.CodeStyle;
  193.50 +import java.awt.Component;
  193.51 +import java.awt.Container;
  193.52 +import java.awt.Rectangle;
  193.53 +import java.awt.event.ActionEvent;
  193.54 +import java.awt.event.ActionListener;
  193.55 +import java.io.BufferedWriter;
  193.56 +import java.io.File;
  193.57 +import java.io.FileWriter;
  193.58 +import java.io.IOException;
  193.59 +import java.util.Arrays;
  193.60 +import java.util.HashMap;
  193.61 +import java.util.HashSet;
  193.62 +import java.util.LinkedList;
  193.63 +import java.util.List;
  193.64 +import java.util.Map;
  193.65 +import java.util.Set;
  193.66 +import java.util.prefs.AbstractPreferences;
  193.67 +import java.util.prefs.BackingStoreException;
  193.68 +import java.util.prefs.Preferences;
  193.69 +import javax.swing.ComboBoxModel;
  193.70 +import javax.swing.DefaultComboBoxModel;
  193.71 +import javax.swing.JCheckBox;
  193.72 +import javax.swing.JComboBox;
  193.73 +import javax.swing.JComponent;
  193.74 +import javax.swing.JEditorPane;
  193.75 +import javax.swing.JPanel;
  193.76 +import javax.swing.JTextField;
  193.77 +import javax.swing.event.DocumentEvent;
  193.78 +import javax.swing.event.DocumentListener;
  193.79 +import javax.swing.text.BadLocationException;
  193.80 +import javax.swing.text.Document;
  193.81 +import org.netbeans.api.editor.settings.SimpleValueNames;
  193.82 +import static org.netbeans.modules.python.source.CodeStyle.*;
  193.83 +import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
  193.84 +import org.netbeans.modules.options.editor.spi.PreviewProvider;
  193.85 +import org.netbeans.modules.python.api.PythonMIMEResolver;
  193.86 +import org.netbeans.modules.python.source.PythonFormatter;
  193.87 +import org.netbeans.modules.python.source.PythonParserResult;
  193.88 +import org.openide.cookies.SaveCookie;
  193.89 +import org.openide.filesystems.FileObject;
  193.90 +import org.openide.filesystems.FileUtil;
  193.91 +import org.openide.loaders.DataObject;
  193.92 +import org.openide.loaders.DataObjectNotFoundException;
  193.93 +import org.openide.text.CloneableEditorSupport;
  193.94 +import org.openide.util.Exceptions;
  193.95 +import org.openide.util.HelpCtx;
  193.96 +import org.openide.util.NbBundle;
  193.97 +
  193.98 +/**
  193.99 + *
 193.100 + * @author phrebejk
 193.101 + */
 193.102 +public class FmtOptions {
 193.103 +    public static final String expandTabToSpaces = SimpleValueNames.EXPAND_TABS;
 193.104 +    public static final String tabSize = SimpleValueNames.TAB_SIZE;
 193.105 +    public static final String spacesPerTab = SimpleValueNames.SPACES_PER_TAB;
 193.106 +    public static final String indentSize = SimpleValueNames.INDENT_SHIFT_WIDTH;
 193.107 +    public static final String continuationIndentSize = "continuationIndentSize"; //NOI18N
 193.108 +    public static final String labelIndent = "labelIndent"; //NOI18N
 193.109 +    public static final String absoluteLabelIndent = "absoluteLabelIndent"; //NOI18N
 193.110 +    public static final String indentTopLevelClassMembers = "indentTopLevelClassMembers"; //NOI18N
 193.111 +    public static final String indentCasesFromSwitch = "indentCasesFromSwitch"; //NOI18N
 193.112 +    public static final String rightMargin = SimpleValueNames.TEXT_LIMIT_WIDTH;
 193.113 +
 193.114 +    /*
 193.115 +    public static final String addLeadingStarInComment = "addLeadingStarInComment"; //NOI18N
 193.116 +
 193.117 +    public static final String preferLongerNames = "preferLongerNames"; //NOI18N
 193.118 +    public static final String fieldNamePrefix = "fieldNamePrefix"; //NOI18N
 193.119 +    public static final String fieldNameSuffix = "fieldNameSuffix"; //NOI18N
 193.120 +    public static final String staticFieldNamePrefix = "staticFieldNamePrefix"; //NOI18N
 193.121 +    public static final String staticFieldNameSuffix = "staticFieldNameSuffix"; //NOI18N
 193.122 +    public static final String parameterNamePrefix = "parameterNamePrefix"; //NOI18N
 193.123 +    public static final String parameterNameSuffix = "parameterNameSuffix"; //NOI18N
 193.124 +    public static final String localVarNamePrefix = "localVarNamePrefix"; //NOI18N
 193.125 +    public static final String localVarNameSuffix = "localVarNameSuffix"; //NOI18N
 193.126 +    public static final String qualifyFieldAccess = "qualifyFieldAccess"; //NOI18N
 193.127 +    public static final String useIsForBooleanGetters = "useIsForBooleanGetters"; //NOI18N
 193.128 +    public static final String addOverrideAnnotation = "addOverrideAnnotation"; //NOI18N
 193.129 +    public static final String makeLocalVarsFinal = "makeLocalVarsFinal"; //NOI18N
 193.130 +    public static final String makeParametersFinal = "makeParametersFinal"; //NOI18N
 193.131 +    public static final String classMembersOrder = "classMembersOrder"; //NOI18N
 193.132 +    
 193.133 +    public static final String alignMultilineMethodParams = "alignMultilineMethodParams"; //NOI18N
 193.134 +    public static final String alignMultilineCallArgs = "alignMultilineCallArgs"; //NOI18N
 193.135 +    public static final String alignMultilineAnnotationArgs = "alignMultilineAnnotationArgs"; //NOI18N
 193.136 +    public static final String alignMultilineImplements = "alignMultilineImplements"; //NOI18N
 193.137 +    public static final String alignMultilineThrows = "alignMultilineThrows"; //NOI18N
 193.138 +    public static final String alignMultilineParenthesized = "alignMultilineParenthesized"; //NOI18N
 193.139 +    public static final String alignMultilineBinaryOp = "alignMultilineBinaryOp"; //NOI18N
 193.140 +    public static final String alignMultilineTernaryOp = "alignMultilineTernaryOp"; //NOI18N
 193.141 +    public static final String alignMultilineAssignment = "alignMultilineAssignment"; //NOI18N
 193.142 +    public static final String alignMultilineFor = "alignMultilineFor"; //NOI18N
 193.143 +    public static final String alignMultilineArrayInit = "alignMultilineArrayInit"; //NOI18N
 193.144 +    public static final String placeElseOnNewLine = "placeElseOnNewLine"; //NOI18N
 193.145 +    public static final String placeWhileOnNewLine = "placeWhileOnNewLine"; //NOI18N
 193.146 +    public static final String placeCatchOnNewLine = "placeCatchOnNewLine"; //NOI18N
 193.147 +    public static final String placeFinallyOnNewLine = "placeFinallyOnNewLine"; //NOI18N
 193.148 +    public static final String placeNewLineAfterModifiers = "placeNewLineAfterModifiers"; //NOI18N
 193.149 +    
 193.150 +    public static final String wrapExtendsImplementsKeyword = "wrapExtendsImplementsKeyword"; //NOI18N
 193.151 +    public static final String wrapExtendsImplementsList = "wrapExtendsImplementsList"; //NOI18N
 193.152 +    public static final String wrapMethodParams = "wrapMethodParams"; //NOI18N
 193.153 +    public static final String wrapThrowsKeyword = "wrapThrowsKeyword"; //NOI18N
 193.154 +    public static final String wrapThrowsList = "wrapThrowsList"; //NOI18N
 193.155 +    public static final String wrapMethodCallArgs = "wrapMethodCallArgs"; //NOI18N
 193.156 +    public static final String wrapAnnotationArgs = "wrapAnnotationArgs"; //NOI18N
 193.157 +    public static final String wrapChainedMethodCalls = "wrapChainedMethodCalls"; //NOI18N
 193.158 +    public static final String wrapArrayInit = "wrapArrayInit"; //NOI18N
 193.159 +    public static final String wrapFor = "wrapFor"; //NOI18N
 193.160 +    public static final String wrapForStatement = "wrapForStatement"; //NOI18N
 193.161 +    public static final String wrapIfStatement = "wrapIfStatement"; //NOI18N
 193.162 +    public static final String wrapWhileStatement = "wrapWhileStatement"; //NOI18N
 193.163 +    public static final String wrapDoWhileStatement = "wrapDoWhileStatement"; //NOI18N
 193.164 +    public static final String wrapAssert = "wrapAssert"; //NOI18N
 193.165 +    public static final String wrapEnumConstants = "wrapEnumConstants"; //NOI18N
 193.166 +    public static final String wrapAnnotations = "wrapAnnotations"; //NOI18N
 193.167 +    public static final String wrapBinaryOps = "wrapBinaryOps"; //NOI18N
 193.168 +    public static final String wrapTernaryOps = "wrapTernaryOps"; //NOI18N
 193.169 +    public static final String wrapAssignOps = "wrapAssignOps"; //NOI18N
 193.170 +    
 193.171 +    public static final String blankLinesBeforePackage = "blankLinesBeforePackage"; //NOI18N
 193.172 +    public static final String blankLinesAfterPackage = "blankLinesAfterPackage"; //NOI18N
 193.173 +    public static final String blankLinesBeforeImports = "blankLinesBeforeImports"; //NOI18N
 193.174 +    public static final String blankLinesAfterImports = "blankLinesAfterImports"; //NOI18N
 193.175 +    public static final String blankLinesBeforeClass = "blankLinesBeforeClass"; //NOI18N
 193.176 +    public static final String blankLinesAfterClass = "blankLinesAfterClass"; //NOI18N
 193.177 +    public static final String blankLinesAfterClassHeader = "blankLinesAfterClassHeader"; //NOI18N
 193.178 +    public static final String blankLinesBeforeFields = "blankLinesBeforeFields"; //NOI18N
 193.179 +    public static final String blankLinesAfterFields = "blankLinesAfterFields"; //NOI18N
 193.180 +    public static final String blankLinesBeforeMethods = "blankLinesBeforeMethods"; //NOI18N
 193.181 +    public static final String blankLinesAfterMethods = "blankLinesAfterMethods"; //NOI18N
 193.182 +    
 193.183 +    public static final String spaceBeforeWhile = "spaceBeforeWhile"; //NOI18N
 193.184 +    public static final String spaceBeforeElse = "spaceBeforeElse"; //NOI18N
 193.185 +    public static final String spaceBeforeCatch = "spaceBeforeCatch"; //NOI18N
 193.186 +    public static final String spaceBeforeFinally = "spaceBeforeFinally"; //NOI18N
 193.187 +    public static final String spaceBeforeMethodDeclParen = "spaceBeforeMethodDeclParen"; //NOI18N
 193.188 +    public static final String spaceBeforeMethodCallParen = "spaceBeforeMethodCallParen"; //NOI18N
 193.189 +    public static final String spaceBeforeIfParen = "spaceBeforeIfParen"; //NOI18N
 193.190 +    public static final String spaceBeforeForParen = "spaceBeforeForParen"; //NOI18N
 193.191 +    public static final String spaceBeforeWhileParen = "spaceBeforeWhileParen"; //NOI18N
 193.192 +    public static final String spaceBeforeCatchParen = "spaceBeforeCatchParen"; //NOI18N
 193.193 +    public static final String spaceBeforeSwitchParen = "spaceBeforeSwitchParen"; //NOI18N
 193.194 +    public static final String spaceBeforeSynchronizedParen = "spaceBeforeSynchronizedParen"; //NOI18N
 193.195 +    public static final String spaceBeforeAnnotationParen = "spaceBeforeAnnotationParen"; //NOI18N    
 193.196 +    public static final String spaceAroundUnaryOps = "spaceAroundUnaryOps"; //NOI18N
 193.197 +    public static final String spaceAroundBinaryOps = "spaceAroundBinaryOps"; //NOI18N
 193.198 +    public static final String spaceAroundTernaryOps = "spaceAroundTernaryOps"; //NOI18N
 193.199 +    public static final String spaceAroundAssignOps = "spaceAroundAssignOps"; //NOI18N
 193.200 +    public static final String spaceBeforeClassDeclLeftBrace = "spaceBeforeClassDeclLeftBrace"; //NOI18N
 193.201 +    public static final String spaceBeforeMethodDeclLeftBrace = "spaceBeforeMethodDeclLeftBrace"; //NOI18N
 193.202 +    public static final String spaceBeforeIfLeftBrace = "spaceBeforeIfLeftBrace"; //NOI18N
 193.203 +    public static final String spaceBeforeElseLeftBrace = "spaceBeforeElseLeftBrace"; //NOI18N
 193.204 +    public static final String spaceBeforeWhileLeftBrace = "spaceBeforeWhileLeftBrace"; //NOI18N
 193.205 +    public static final String spaceBeforeForLeftBrace = "spaceBeforeForLeftBrace"; //NOI18N
 193.206 +    public static final String spaceBeforeDoLeftBrace = "spaceBeforeDoLeftBrace"; //NOI18N
 193.207 +    public static final String spaceBeforeSwitchLeftBrace = "spaceBeforeSwitchLeftBrace"; //NOI18N
 193.208 +    public static final String spaceBeforeTryLeftBrace = "spaceBeforeTryLeftBrace"; //NOI18N
 193.209 +    public static final String spaceBeforeCatchLeftBrace = "spaceBeforeCatchLeftBrace"; //NOI18N
 193.210 +    public static final String spaceBeforeFinallyLeftBrace = "spaceBeforeFinallyLeftBrace"; //NOI18N
 193.211 +    public static final String spaceBeforeSynchronizedLeftBrace = "spaceBeforeSynchronizedLeftBrace"; //NOI18N
 193.212 +    public static final String spaceBeforeStaticInitLeftBrace = "spaceBeforeStaticInitLeftBrace"; //NOI18N
 193.213 +    public static final String spaceBeforeArrayInitLeftBrace = "spaceBeforeArrayInitLeftBrace"; //NOI18N
 193.214 +    public static final String spaceWithinParens = "spaceWithinParens"; //NOI18N
 193.215 +    public static final String spaceWithinMethodDeclParens = "spaceWithinMethodDeclParens"; //NOI18N
 193.216 +    public static final String spaceWithinMethodCallParens = "spaceWithinMethodCallParens"; //NOI18N
 193.217 +    public static final String spaceWithinIfParens = "spaceWithinIfParens"; //NOI18N
 193.218 +    public static final String spaceWithinForParens = "spaceWithinForParens"; //NOI18N
 193.219 +    public static final String spaceWithinWhileParens = "spaceWithinWhileParens"; //NOI18N
 193.220 +    public static final String spaceWithinSwitchParens = "spaceWithinSwitchParens"; //NOI18N
 193.221 +    public static final String spaceWithinCatchParens = "spaceWithinCatchParens"; //NOI18N
 193.222 +    public static final String spaceWithinSynchronizedParens = "spaceWithinSynchronizedParens"; //NOI18N
 193.223 +    public static final String spaceWithinTypeCastParens = "spaceWithinTypeCastParens"; //NOI18N
 193.224 +    public static final String spaceWithinAnnotationParens = "spaceWithinAnnotationParens"; //NOI18N
 193.225 +    public static final String spaceWithinBraces = "spaceWithinBraces"; //NOI18N
 193.226 +    public static final String spaceWithinArrayInitBrackets = "spaceWithinArrayInitBrackets"; //NOI18N
 193.227 +    public static final String spaceBeforeComma = "spaceBeforeComma"; //NOI18N
 193.228 +    public static final String spaceAfterComma = "spaceAfterComma"; //NOI18N
 193.229 +    public static final String spaceBeforeSemi = "spaceBeforeSemi"; //NOI18N
 193.230 +    public static final String spaceAfterSemi = "spaceAfterSemi"; //NOI18N
 193.231 +    public static final String spaceBeforeColon = "spaceBeforeColon"; //NOI18N
 193.232 +    public static final String spaceAfterColon = "spaceAfterColon"; //NOI18N
 193.233 +    public static final String spaceAfterTypeCast = "spaceAfterTypeCast"; //NOI18N
 193.234 +     */
 193.235 +
 193.236 +    // Spaces
 193.237 +    public static final String addSpaceAroundOperators = "spaceAroundOperators"; //NOI18N
 193.238 +    public static final String removeSpaceInParens = "spaceInsideParens"; //NOI18N
 193.239 +    public static final String addSpaceAfterComma = "spaceAfterComma"; //NOI18N
 193.240 +    public static final String removeSpaceBeforeSep = "spaceBeforeSeparator"; //NOI18N
 193.241 +    public static final String removeSpaceInParamAssign = "spaceInKeywordAssign"; //NOI18N
 193.242 +    public static final String collapseSpaces = "collapseSpaces"; //NOI18N
 193.243 +    // Imports
 193.244 +    public static final String formatImports = "formatImports"; //NOI18N
 193.245 +    public static final String oneImportPerLine = "oneImportPerLine"; //NOI18N
 193.246 +    public static final String removeDuplicates = "removeDuplicates"; //NOI18N
 193.247 +    public static final String systemLibsFirst = "systemLibsFirst"; //NOI18N
 193.248 +    public static final String cleanupUnusedImports = "cleanupUnusedImports"; //NOI18N
 193.249 +    public static final String preferSymbolImports = "preferSymbolImports"; //NOI18N
 193.250 +    public static final String sortImports = "sortImports"; //NOI18N
 193.251 +    public static final String separateFromImps = "separateFromImps"; //NOI18N
 193.252 +    public static CodeStyleProducer codeStyleProducer;
 193.253 +    static final String CODE_STYLE_PROFILE = "CodeStyle"; // NOI18N
 193.254 +    static final String DEFAULT_PROFILE = "default"; // NOI18N
 193.255 +    static final String PROJECT_PROFILE = "project"; // NOI18N
 193.256 +    static final String usedProfile = "usedProfile"; // NOI18N
 193.257 +
 193.258 +    private FmtOptions() {
 193.259 +    }
 193.260 +
 193.261 +    public static int getDefaultAsInt(String key) {
 193.262 +        return Integer.parseInt(defaults.get(key));
 193.263 +    }
 193.264 +
 193.265 +    public static boolean getDefaultAsBoolean(String key) {
 193.266 +        return Boolean.parseBoolean(defaults.get(key));
 193.267 +    }
 193.268 +
 193.269 +    public static String getDefaultAsString(String key) {
 193.270 +        return defaults.get(key);
 193.271 +    }
 193.272 +
 193.273 +    public static boolean isInteger(String optionID) {
 193.274 +        String value = defaults.get(optionID);
 193.275 +
 193.276 +        try {
 193.277 +            Integer.parseInt(value);
 193.278 +            return true;
 193.279 +        } catch (NumberFormatException numberFormatException) {
 193.280 +            return false;
 193.281 +        }
 193.282 +    }
 193.283 +    // Private section ---------------------------------------------------------
 193.284 +    private static final String TRUE = "true";      // NOI18N
 193.285 +    private static final String FALSE = "false";    // NOI18N
 193.286 +    private static final String WRAP_ALWAYS = WrapStyle.WRAP_ALWAYS.name();
 193.287 +    //private static final String WRAP_IF_LONG  = WrapStyle.WRAP_IF_LONG.name();
 193.288 +    private static final String WRAP_NEVER = WrapStyle.WRAP_NEVER.name();
 193.289 +
 193.290 +    //private static final String CLEANUP_COMMENT  = ImportCleanupStyle.COMMENT_OUT.name();
 193.291 +    private static final String IMP_LEAVE_ALONE = ImportCleanupStyle.LEAVE_ALONE.name();
 193.292 +    private static Map<String, String> defaults;
 193.293 +
 193.294 +
 193.295 +    static {
 193.296 +        createDefaults();
 193.297 +    }
 193.298 +
 193.299 +    private static void createDefaults() {
 193.300 +        String defaultValues[][] = {
 193.301 +            {expandTabToSpaces, TRUE}, //NOI18N
 193.302 +            {tabSize, "4"}, //NOI18N
 193.303 +            {spacesPerTab, "4"}, //NOI18N
 193.304 +            {indentSize, "4"}, //NOI18N
 193.305 +            {continuationIndentSize, "8"}, //NOI18N
 193.306 +            {labelIndent, "0"}, //NOI18N
 193.307 +            {absoluteLabelIndent, FALSE}, //NOI18N
 193.308 +            {indentTopLevelClassMembers, TRUE}, //NOI18N
 193.309 +            {indentCasesFromSwitch, TRUE}, //NOI18N
 193.310 +            {rightMargin, "80"}, //NOI18N
 193.311 +
 193.312 +            /*
 193.313 +            { addLeadingStarInComment, TRUE}, //NOI18N
 193.314 +
 193.315 +            { preferLongerNames, TRUE}, //NOI18N
 193.316 +            { fieldNamePrefix, ""}, //NOI18N // XXX null
 193.317 +            { fieldNameSuffix, ""}, //NOI18N // XXX null
 193.318 +            { staticFieldNamePrefix, ""}, //NOI18N // XXX null
 193.319 +            { staticFieldNameSuffix, ""}, //NOI18N // XXX null
 193.320 +            { parameterNamePrefix, ""}, //NOI18N // XXX null
 193.321 +            { parameterNameSuffix, ""}, //NOI18N // XXX null
 193.322 +            { localVarNamePrefix, ""}, //NOI18N // XXX null
 193.323 +            { localVarNameSuffix, ""}, //NOI18N // XXX null
 193.324 +            { qualifyFieldAccess, FALSE}, //NOI18N // XXX
 193.325 +            { useIsForBooleanGetters, TRUE}, //NOI18N
 193.326 +            { addOverrideAnnotation, TRUE}, //NOI18N
 193.327 +            { makeLocalVarsFinal, FALSE}, //NOI18N
 193.328 +            { makeParametersFinal, FALSE}, //NOI18N
 193.329 +            { classMembersOrder, ""}, //NOI18N // XXX
 193.330 +
 193.331 +            { alignMultilineMethodParams, FALSE}, //NOI18N
 193.332 +            { alignMultilineCallArgs, FALSE}, //NOI18N
 193.333 +            { alignMultilineAnnotationArgs, FALSE}, //NOI18N
 193.334 +            { alignMultilineImplements, FALSE}, //NOI18N
 193.335 +            { alignMultilineThrows, FALSE}, //NOI18N
 193.336 +            { alignMultilineParenthesized, FALSE}, //NOI18N
 193.337 +            { alignMultilineBinaryOp, FALSE}, //NOI18N
 193.338 +            { alignMultilineTernaryOp, FALSE}, //NOI18N
 193.339 +            { alignMultilineAssignment, FALSE}, //NOI18N
 193.340 +            { alignMultilineFor, FALSE}, //NOI18N
 193.341 +            { alignMultilineArrayInit, FALSE}, //NOI18N
 193.342 +            { placeElseOnNewLine, FALSE}, //NOI18N 
 193.343 +            { placeWhileOnNewLine, FALSE}, //NOI18N
 193.344 +            { placeCatchOnNewLine, FALSE}, //NOI18N 
 193.345 +            { placeFinallyOnNewLine, FALSE}, //NOI18N 
 193.346 +            { placeNewLineAfterModifiers, FALSE}, //NOI18N
 193.347 +
 193.348 +            { wrapExtendsImplementsKeyword, WRAP_NEVER}, //NOI18N
 193.349 +            { wrapExtendsImplementsList, WRAP_NEVER}, //NOI18N
 193.350 +            { wrapMethodParams, WRAP_NEVER}, //NOI18N
 193.351 +            { wrapThrowsKeyword, WRAP_NEVER}, //NOI18N
 193.352 +            { wrapThrowsList, WRAP_NEVER}, //NOI18N
 193.353 +            { wrapMethodCallArgs, WRAP_NEVER}, //NOI18N
 193.354 +            { wrapAnnotationArgs, WRAP_NEVER}, //NOI18N
 193.355 +            { wrapChainedMethodCalls, WRAP_NEVER}, //NOI18N
 193.356 +            { wrapArrayInit, WRAP_NEVER}, //NOI18N
 193.357 +            { wrapFor, WRAP_NEVER}, //NOI18N
 193.358 +            { wrapForStatement, WRAP_ALWAYS}, //NOI18N
 193.359 +            { wrapIfStatement, WRAP_ALWAYS}, //NOI18N
 193.360 +            { wrapWhileStatement, WRAP_ALWAYS}, //NOI18N
 193.361 +            { wrapDoWhileStatement, WRAP_ALWAYS}, //NOI18N
 193.362 +            { wrapAssert, WRAP_NEVER}, //NOI18N
 193.363 +            { wrapEnumConstants, WRAP_NEVER}, //NOI18N
 193.364 +            { wrapAnnotations, WRAP_ALWAYS}, //NOI18N
 193.365 +            { wrapBinaryOps, WRAP_NEVER}, //NOI18N
 193.366 +            { wrapTernaryOps, WRAP_NEVER}, //NOI18N
 193.367 +            { wrapAssignOps, WRAP_NEVER}, //NOI18N
 193.368 +
 193.369 +            { blankLinesBeforePackage, "0"}, //NOI18N
 193.370 +            { blankLinesAfterPackage, "1"}, //NOI18N
 193.371 +            { blankLinesBeforeImports, "1"}, //NOI18N 
 193.372 +            { blankLinesAfterImports, "1"}, //NOI18N
 193.373 +            { blankLinesBeforeClass, "1"}, //NOI18N 
 193.374 +            { blankLinesAfterClass, "0"}, //NOI18N
 193.375 +            { blankLinesAfterClassHeader, "1"}, //NOI18N 
 193.376 +            { blankLinesBeforeFields, "0"}, //NOI18N 
 193.377 +            { blankLinesAfterFields, "0"}, //NOI18N
 193.378 +            { blankLinesBeforeMethods, "1"}, //NOI18N
 193.379 +            { blankLinesAfterMethods, "0"}, //NOI18N
 193.380 +
 193.381 +            { spaceBeforeWhile, TRUE}, //NOI18N // XXX
 193.382 +            { spaceBeforeElse, TRUE}, //NOI18N // XXX
 193.383 +            { spaceBeforeCatch, TRUE}, //NOI18N // XXX
 193.384 +            { spaceBeforeFinally, TRUE}, //NOI18N // XXX
 193.385 +            { spaceBeforeMethodDeclParen, FALSE}, //NOI18N
 193.386 +            { spaceBeforeMethodCallParen, FALSE}, //NOI18N
 193.387 +            { spaceBeforeIfParen, TRUE}, //NOI18N
 193.388 +            { spaceBeforeForParen, TRUE}, //NOI18N
 193.389 +            { spaceBeforeWhileParen, TRUE}, //NOI18N
 193.390 +            { spaceBeforeCatchParen, TRUE}, //NOI18N
 193.391 +            { spaceBeforeSwitchParen, TRUE}, //NOI18N
 193.392 +            { spaceBeforeSynchronizedParen, TRUE}, //NOI18N
 193.393 +            { spaceBeforeAnnotationParen, FALSE}, //NOI18N    
 193.394 +            { spaceAroundUnaryOps, FALSE}, //NOI18N
 193.395 +            { spaceAroundBinaryOps, TRUE}, //NOI18N
 193.396 +            { spaceAroundTernaryOps, TRUE}, //NOI18N
 193.397 +            { spaceAroundAssignOps, TRUE}, //NOI18N
 193.398 +            { spaceBeforeClassDeclLeftBrace, TRUE}, //NOI18N
 193.399 +            { spaceBeforeMethodDeclLeftBrace, TRUE}, //NOI18N
 193.400 +            { spaceBeforeIfLeftBrace, TRUE}, //NOI18N
 193.401 +            { spaceBeforeElseLeftBrace, TRUE}, //NOI18N
 193.402 +            { spaceBeforeWhileLeftBrace, TRUE}, //NOI18N
 193.403 +            { spaceBeforeForLeftBrace, TRUE}, //NOI18N
 193.404 +            { spaceBeforeDoLeftBrace, TRUE}, //NOI18N
 193.405 +            { spaceBeforeSwitchLeftBrace, TRUE}, //NOI18N
 193.406 +            { spaceBeforeTryLeftBrace, TRUE}, //NOI18N
 193.407 +            { spaceBeforeCatchLeftBrace, TRUE}, //NOI18N
 193.408 +            { spaceBeforeFinallyLeftBrace, TRUE}, //NOI18N
 193.409 +            { spaceBeforeSynchronizedLeftBrace, TRUE}, //NOI18N
 193.410 +            { spaceBeforeStaticInitLeftBrace, TRUE}, //NOI18N
 193.411 +            { spaceBeforeArrayInitLeftBrace, FALSE}, //NOI18N
 193.412 +            { spaceWithinParens, FALSE}, //NOI18N
 193.413 +            { spaceWithinMethodDeclParens, FALSE}, //NOI18N
 193.414 +            { spaceWithinMethodCallParens, FALSE}, //NOI18N
 193.415 +            { spaceWithinIfParens, FALSE}, //NOI18N
 193.416 +            { spaceWithinForParens, FALSE}, //NOI18N
 193.417 +            { spaceWithinWhileParens, FALSE}, //NOI18N
 193.418 +            { spaceWithinSwitchParens, FALSE}, //NOI18N
 193.419 +            { spaceWithinCatchParens, FALSE}, //NOI18N
 193.420 +            { spaceWithinSynchronizedParens, FALSE}, //NOI18N
 193.421 +            { spaceWithinTypeCastParens, FALSE}, //NOI18N
 193.422 +            { spaceWithinAnnotationParens, FALSE}, //NOI18N
 193.423 +            { spaceWithinBraces, FALSE}, //NOI18N
 193.424 +            { spaceWithinArrayInitBrackets, FALSE}, //NOI18N
 193.425 +            { spaceBeforeComma, FALSE}, //NOI18N
 193.426 +            { spaceAfterComma, TRUE}, //NOI18N
 193.427 +            { spaceBeforeSemi, FALSE}, //NOI18N
 193.428 +            { spaceAfterSemi, TRUE}, //NOI18N
 193.429 +            { spaceBeforeColon, TRUE}, //NOI18N
 193.430 +            { spaceAfterColon, TRUE}, //NOI18N
 193.431 +            { spaceAfterTypeCast, TRUE}, //NOI18N
 193.432 +             */
 193.433 +            // Spaces
 193.434 +            {addSpaceAroundOperators, TRUE},
 193.435 +            {removeSpaceInParens, TRUE},
 193.436 +            {addSpaceAfterComma, TRUE},
 193.437 +            {removeSpaceBeforeSep, TRUE},
 193.438 +            {removeSpaceInParamAssign, TRUE},
 193.439 +            {collapseSpaces, TRUE},
 193.440 +            // Imports
 193.441 +            {formatImports, TRUE},
 193.442 +            {oneImportPerLine, TRUE},
 193.443 +            {removeDuplicates, TRUE},
 193.444 +            {systemLibsFirst, TRUE},
 193.445 +            {preferSymbolImports, TRUE},
 193.446 +            {sortImports, TRUE},
 193.447 +            {cleanupUnusedImports, IMP_LEAVE_ALONE},
 193.448 +            {separateFromImps, FALSE},};
 193.449 +
 193.450 +        defaults = new HashMap<>();
 193.451 +
 193.452 +        for (java.lang.String[] strings : defaultValues) {
 193.453 +            defaults.put(strings[0], strings[1]);
 193.454 +        }
 193.455 +
 193.456 +    }
 193.457 +
 193.458 +    // Support section ---------------------------------------------------------
 193.459 +    public static class CategorySupport implements ActionListener, DocumentListener, PreviewProvider, PreferencesCustomizer {
 193.460 +        public static final String OPTION_ID = "org.netbeans.modules.python.editor.options.FormatingOptions.ID";
 193.461 +        private static final int LOAD = 0;
 193.462 +        private static final int STORE = 1;
 193.463 +        private static final int ADD_LISTENERS = 2;
 193.464 +        private static final ComboItem wrap[] = new ComboItem[]{
 193.465 +            new ComboItem(WrapStyle.WRAP_ALWAYS.name(), "LBL_wrp_WRAP_ALWAYS"), // NOI18N
 193.466 +            new ComboItem(WrapStyle.WRAP_IF_LONG.name(), "LBL_wrp_WRAP_IF_LONG"), // NOI18N
 193.467 +            new ComboItem(WrapStyle.WRAP_NEVER.name(), "LBL_wrp_WRAP_NEVER") // NOI18N
 193.468 +        };
 193.469 +        private static final ComboItem cleanupImports[] = new ComboItem[]{
 193.470 +            new ComboItem(ImportCleanupStyle.LEAVE_ALONE.name(), "LBL_imp_LEAVE_ALONE"), // NOI18N
 193.471 +            new ComboItem(ImportCleanupStyle.COMMENT_OUT.name(), "LBL_imp_COMMENT_OUT"), // NOI18N
 193.472 +            new ComboItem(ImportCleanupStyle.DELETE.name(), "LBL_imp_DELETE") // NOI18N
 193.473 +        };
 193.474 +        private final String previewText;
 193.475 +        private final String id;
 193.476 +        protected final JPanel panel;
 193.477 +        private final List<JComponent> components = new LinkedList<>();
 193.478 +        private JEditorPane previewPane;
 193.479 +        private final Preferences preferences;
 193.480 +        private final Preferences previewPrefs;
 193.481 +
 193.482 +        protected CategorySupport(Preferences preferences, String id, JPanel panel, String previewText, String[]... forcedOptions) {
 193.483 +            this.preferences = preferences;
 193.484 +            this.id = id;
 193.485 +            this.panel = panel;
 193.486 +            this.previewText = previewText != null ? previewText : NbBundle.getMessage(FmtOptions.class, "SAMPLE_Default"); //NOI18N
 193.487 +
 193.488 +            // Scan the panel for its components
 193.489 +            scan(panel, components);
 193.490 +
 193.491 +            // Initialize the preview preferences
 193.492 +            Preferences forcedPrefs = new PreviewPreferences();
 193.493 +            for (String[] option : forcedOptions) {
 193.494 +                forcedPrefs.put(option[0], option[1]);
 193.495 +            }
 193.496 +            this.previewPrefs = new ProxyPreferences(preferences, forcedPrefs);
 193.497 +
 193.498 +            // Load and hook up all the components
 193.499 +            loadFrom(preferences);
 193.500 +            addListeners();
 193.501 +        }
 193.502 +
 193.503 +        protected void addListeners() {
 193.504 +            scan(ADD_LISTENERS, null);
 193.505 +        }
 193.506 +
 193.507 +        protected void loadFrom(Preferences preferences) {
 193.508 +//            loaded = true;
 193.509 +            scan(LOAD, preferences);
 193.510 +//            loaded = false;
 193.511 +        }
 193.512 +//
 193.513 +//        public void applyChanges() {
 193.514 +//            storeTo(preferences);
 193.515 +//        }
 193.516 +//
 193.517 +
 193.518 +        protected void storeTo(Preferences p) {
 193.519 +            scan(STORE, p);
 193.520 +        }
 193.521 +
 193.522 +        protected void notifyChanged() {
 193.523 +//            if (loaded)
 193.524 +//                return;
 193.525 +            storeTo(preferences);
 193.526 +            refreshPreview();
 193.527 +        }
 193.528 +
 193.529 +        // ActionListener implementation ---------------------------------------
 193.530 +        @Override
 193.531 +        public void actionPerformed(ActionEvent e) {
 193.532 +            notifyChanged();
 193.533 +        }
 193.534 +
 193.535 +        // DocumentListener implementation -------------------------------------
 193.536 +        @Override
 193.537 +        public void insertUpdate(DocumentEvent e) {
 193.538 +            notifyChanged();
 193.539 +        }
 193.540 +
 193.541 +        @Override
 193.542 +        public void removeUpdate(DocumentEvent e) {
 193.543 +            notifyChanged();
 193.544 +        }
 193.545 +
 193.546 +        @Override
 193.547 +        public void changedUpdate(DocumentEvent e) {
 193.548 +            notifyChanged();
 193.549 +        }
 193.550 +
 193.551 +        // PreviewProvider methods -----------------------------------------------------
 193.552 +        @Override
 193.553 +        public JComponent getPreviewComponent() {
 193.554 +            if (previewPane == null) {
 193.555 +                previewPane = new JEditorPane();
 193.556 +                previewPane.getAccessibleContext().setAccessibleName(NbBundle.getMessage(FmtOptions.class, "AN_Preview")); //NOI18N
 193.557 +                previewPane.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(FmtOptions.class, "AD_Preview")); //NOI18N
 193.558 +                previewPane.putClientProperty("HighlightsLayerIncludes", "^org\\.netbeans\\.modules\\.editor\\.lib2\\.highlighting\\.SyntaxHighlighting$"); //NOI18N
 193.559 +                previewPane.setEditorKit(CloneableEditorSupport.getEditorKit(PythonMIMEResolver.PYTHON_MIME_TYPE));
 193.560 +                previewPane.setEditable(false);
 193.561 +            }
 193.562 +            return previewPane;
 193.563 +        }
 193.564 +
 193.565 +        @Override
 193.566 +        public void refreshPreview() {
 193.567 +            JEditorPane jep = (JEditorPane)getPreviewComponent();
 193.568 +            try {
 193.569 +                int rm = previewPrefs.getInt(rightMargin, getDefaultAsInt(rightMargin));
 193.570 +                jep.putClientProperty("TextLimitLine", rm); //NOI18N
 193.571 +            } catch (NumberFormatException e) {
 193.572 +                // Ignore it
 193.573 +            }
 193.574 +            try {
 193.575 +                Class.forName(CodeStyle.class.getName(), true, CodeStyle.class.getClassLoader());
 193.576 +            } catch (ClassNotFoundException cnfe) {
 193.577 +                // ignore
 193.578 +            }
 193.579 +
 193.580 +            CodeStyle codeStyle = codeStyleProducer.create(previewPrefs);
 193.581 +            jep.setIgnoreRepaint(true);
 193.582 +
 193.583 +//            if (jep.getDocument() instanceof BaseDocument) {
 193.584 +//                BaseDocument document = (BaseDocument) jep.getDocument();
 193.585 +//                final org.netbeans.editor.Formatter f = document.getFormatter();
 193.586 +//                try {
 193.587 +//                    f.reformatLock();
 193.588 +//                    try {
 193.589 +//                        int reformattedLen = f.reformat(document, 0, document.getLength());
 193.590 +//                    } catch (BadLocationException ex) {
 193.591 +//                        Exceptions.printStackTrace(ex);
 193.592 +//                    }
 193.593 +//                } finally {
 193.594 +//                    f.reformatUnlock();
 193.595 +//                }
 193.596 +//            }
 193.597 +
 193.598 +            // Hacky code to do preview: We want to preview blank text without
 193.599 +            // a data object... this doesn't work very well so requires some hacks
 193.600 +            // to create a temp file, format it, then save it and delete it
 193.601 +            // (to avoid save confirmation dialogs on the modified file etc)
 193.602 +            PythonFormatter formatter = new PythonFormatter(codeStyle);
 193.603 +            PythonParserResult info = null;
 193.604 +            File tmp = null;
 193.605 +            FileObject tmpFo = null;
 193.606 +            if (formatter.needsParserResult()) {
 193.607 +                try {
 193.608 +                    tmp = File.createTempFile("preview", ".py"); // NOI18N
 193.609 +                    BufferedWriter writer = new BufferedWriter(new FileWriter(tmp));
 193.610 +                    writer.write(previewText);
 193.611 +                    writer.close();
 193.612 +                    final FileObject fo = FileUtil.toFileObject(FileUtil.normalizeFile(tmp));
 193.613 +                    tmpFo = fo;
 193.614 +                    // TODO - I need to get the classpath involved here such that it can
 193.615 +                    // find used/unused libraries
 193.616 +//                    if (!SourceUtils.isScanInProgress()) {
 193.617 +//                        // I'm using custom GSF code here because I want to set up an explicit
 193.618 +//                        // source path for the fake file object which includes the Python
 193.619 +//                        // libraries (since we need them for the isSystemModule lookup
 193.620 +//                        //SourceModel model = SourceModelFactory.getInstance().getModel(fo);
 193.621 +//                        //if (model != null && !model.isScanInProgress()) {
 193.622 +//                        List<FileObject> roots = new ArrayList<FileObject>(new PythonLanguage().getCoreLibraries());
 193.623 +//
 193.624 +//                        final PythonPlatformManager manager = PythonPlatformManager.getInstance();
 193.625 +//                        final String platformName = manager.getDefaultPlatform();
 193.626 +//                        PythonPlatform activePlatform = manager.getPlatform(platformName);
 193.627 +//                        if (activePlatform != null) {
 193.628 +//                            roots.addAll(activePlatform.getUniqueLibraryRoots());
 193.629 +//                            ClassPath boot = ClassPathSupport.createClassPath(roots.toArray(new FileObject[roots.size()]));
 193.630 +//                            ClassPath source = ClassPathSupport.createClassPath(new FileObject[]{fo.getParent()});
 193.631 +//                            ClassPath compile = source;
 193.632 +//
 193.633 +//                            ClasspathInfo cpInfo = ClasspathInfo.create(boot, compile, source);
 193.634 +//                            Source model = Source.create(cpInfo, fo);
 193.635 +//                            if (model != null) {
 193.636 +//                                final CompilationInfo[] infoHolder = new CompilationInfo[1];
 193.637 +//                                //model.runUserActionTask(new CancellableTask<CompilationInfo>() {
 193.638 +//                                model.runUserActionTask(new CancellableTask<CompilationController>() {
 193.639 +//                                    public void cancel() {
 193.640 +//                                    }
 193.641 +//
 193.642 +//                                    //public void run(CompilationInfo info) throws Exception {
 193.643 +//                                    public void run(CompilationController info) throws Exception {
 193.644 +//                                        info.toPhase(Phase.RESOLVED);
 193.645 +//                                        infoHolder[0] = info;
 193.646 +//                                        // Force open so info.getFileObject will succeed
 193.647 +//                                        GsfUtilities.getDocument(fo, true);
 193.648 +//                                    }
 193.649 +//                                }, false);
 193.650 +//                                info = infoHolder[0];
 193.651 +//                            }
 193.652 +//                        }
 193.653 +//                    }
 193.654 +                } catch (IOException ex) {
 193.655 +                    Exceptions.printStackTrace(ex);
 193.656 +                }
 193.657 +            }
 193.658 +            try {
 193.659 +                if (info != null && info.getSnapshot().getSource().getDocument(false) != null) {
 193.660 +                    Document doc = info.getSnapshot().getSource().getDocument(false);
 193.661 +                    formatter.reformat(null, doc, 0, doc.getLength(), info);
 193.662 +                    jep.setText(doc.getText(0, doc.getLength()));
 193.663 +                    // Save file to avoid warning on exit
 193.664 +                    DataObject dobj = DataObject.find(info.getSnapshot().getSource().getFileObject());
 193.665 +                    SaveCookie cookie = dobj.getCookie(SaveCookie.class);
 193.666 +                    if (cookie != null) {
 193.667 +                        cookie.save();
 193.668 +                    }
 193.669 +                } else {
 193.670 +                    Document doc = jep.getDocument();
 193.671 +                    if (doc.getLength() > 0) {
 193.672 +                        doc.remove(0, doc.getLength());
 193.673 +                    }
 193.674 +                    doc.insertString(0, previewText, null);
 193.675 +                    formatter.reformat(null, doc, 0, doc.getLength(), null);
 193.676 +                    jep.setText(doc.getText(0, doc.getLength()));
 193.677 +                }
 193.678 +            } catch (DataObjectNotFoundException dof) {
 193.679 +                Exceptions.printStackTrace(dof);
 193.680 +            } catch (IOException | BadLocationException ioe) {
 193.681 +                Exceptions.printStackTrace(ioe);
 193.682 +            }
 193.683 +
 193.684 +            if (tmpFo != null) {
 193.685 +                try {
 193.686 +                    tmpFo.delete();
 193.687 +                } catch (IOException ex) {
 193.688 +                    Exceptions.printStackTrace(ex);
 193.689 +                }
 193.690 +            } else if (tmp != null) {
 193.691 +                tmp.delete();
 193.692 +            }
 193.693 +
 193.694 +
 193.695 +            jep.setIgnoreRepaint(false);
 193.696 +            jep.scrollRectToVisible(new Rectangle(0, 0, 10, 10));
 193.697 +            jep.repaint(100);
 193.698 +        }
 193.699 +
 193.700 +        // PreferencesCustomizer implementation --------------------------------
 193.701 +        @Override
 193.702 +        public JComponent getComponent() {
 193.703 +            return panel;
 193.704 +        }
 193.705 +
 193.706 +        @Override
 193.707 +        public String getDisplayName() {
 193.708 +            return panel.getName();
 193.709 +        }
 193.710 +
 193.711 +        @Override
 193.712 +        public String getId() {
 193.713 +            return id;
 193.714 +        }
 193.715 +
 193.716 +        @Override
 193.717 +        public HelpCtx getHelpCtx() {
 193.718 +            return null;
 193.719 +        }
 193.720 +
 193.721 +        // PreferencesCustomizer.Factory implementation ------------------------
 193.722 +        public static final class Factory implements PreferencesCustomizer.Factory {
 193.723 +            private final String id;
 193.724 +            private final Class<? extends JPanel> panelClass;
 193.725 +            private final String previewText;
 193.726 +            private final String[][] forcedOptions;
 193.727 +
 193.728 +            public Factory(String id, Class<? extends JPanel> panelClass, String previewText, String[]... forcedOptions) {
 193.729 +                this.id = id;
 193.730 +                this.panelClass = panelClass;
 193.731 +                this.previewText = previewText;
 193.732 +                this.forcedOptions = forcedOptions;
 193.733 +            }
 193.734 +
 193.735 +            @Override
 193.736 +            public PreferencesCustomizer create(Preferences preferences) {
 193.737 +                try {
 193.738 +                    return new CategorySupport(preferences, id, panelClass.newInstance(), previewText, forcedOptions);
 193.739 +                } catch (IllegalAccessException | InstantiationException e) {
 193.740 +                    return null;
 193.741 +                }
 193.742 +            }
 193.743 +        } // End of CategorySupport.Factory class
 193.744 +
 193.745 +        // Private methods -----------------------------------------------------
 193.746 +        private void performOperation(int operation, JComponent jc, String optionID, Preferences p) {
 193.747 +            switch (operation) {
 193.748 +            case LOAD:
 193.749 +                loadData(jc, optionID, p);
 193.750 +                break;
 193.751 +            case STORE:
 193.752 +                storeData(jc, optionID, p);
 193.753 +                break;
 193.754 +            case ADD_LISTENERS:
 193.755 +                addListener(jc);
 193.756 +                break;
 193.757 +            }
 193.758 +        }
 193.759 +
 193.760 +        private void scan(int what, Preferences p) {
 193.761 +            for (JComponent jc : components) {
 193.762 +                Object o = jc.getClientProperty(OPTION_ID);
 193.763 +                if (o instanceof String) {
 193.764 +                    performOperation(what, jc, (String)o, p);
 193.765 +                } else if (o instanceof String[]) {
 193.766 +                    for (String oid : (String[])o) {
 193.767 +                        performOperation(what, jc, oid, p);
 193.768 +                    }
 193.769 +                }
 193.770 +            }
 193.771 +        }
 193.772 +
 193.773 +        private void scan(Container container, List<JComponent> components) {
 193.774 +            for (Component c : container.getComponents()) {
 193.775 +                if (c instanceof JComponent) {
 193.776 +                    JComponent jc = (JComponent)c;
 193.777 +                    Object o = jc.getClientProperty(OPTION_ID);
 193.778 +                    if (o instanceof String || o instanceof String[]) {
 193.779 +                        components.add(jc);
 193.780 +                    }
 193.781 +                }
 193.782 +                if (c instanceof Container) {
 193.783 +                    scan((Container)c, components);
 193.784 +                }
 193.785 +            }
 193.786 +        }
 193.787 +
 193.788 +        /** Very smart method which tries to set the values in the components correctly
 193.789 +         */
 193.790 +        private void loadData(JComponent jc, String optionID, Preferences node) {
 193.791 +
 193.792 +            if (jc instanceof JTextField) {
 193.793 +                JTextField field = (JTextField)jc;
 193.794 +                field.setText(node.get(optionID, getDefaultAsString(optionID)));
 193.795 +            } else if (jc instanceof JCheckBox) {
 193.796 +                JCheckBox checkBox = (JCheckBox)jc;
 193.797 +                boolean df = getDefaultAsBoolean(optionID);
 193.798 +                checkBox.setSelected(node.getBoolean(optionID, df));
 193.799 +            } else if (jc instanceof JComboBox) {
 193.800 +                JComboBox cb = (JComboBox)jc;
 193.801 +                String value = node.get(optionID, getDefaultAsString(optionID));
 193.802 +                ComboBoxModel model = createModel(value);
 193.803 +                cb.setModel(model);
 193.804 +                ComboItem item = whichItem(value, model);
 193.805 +                cb.setSelectedItem(item);
 193.806 +            }
 193.807 +
 193.808 +        }
 193.809 +
 193.810 +        private void storeData(JComponent jc, String optionID, Preferences node) {
 193.811 +
 193.812 +            if (jc instanceof JTextField) {
 193.813 +                JTextField field = (JTextField)jc;
 193.814 +
 193.815 +                String text = field.getText();
 193.816 +
 193.817 +                // XXX test for numbers
 193.818 +                if (isInteger(optionID)) {
 193.819 +                    try {
 193.820 +                        int i = Integer.parseInt(text);
 193.821 +                    } catch (NumberFormatException e) {
 193.822 +                        return;
 193.823 +                    }
 193.824 +                }
 193.825 +
 193.826 +                // XXX: watch out, tabSize, spacesPerTab, indentSize and expandTabToSpaces
 193.827 +                // fall back on getGlopalXXX() values and not getDefaultAsXXX value,
 193.828 +                // which is why we must not remove them. Proper solution would be to
 193.829 +                // store formatting preferences to MimeLookup and not use NbPreferences.
 193.830 +                // The problem currently is that MimeLookup based Preferences do not support subnodes.
 193.831 +                if (!optionID.equals(tabSize) &&
 193.832 +                        !optionID.equals(spacesPerTab) && !optionID.equals(indentSize) &&
 193.833 +                        getDefaultAsString(optionID).equals(text)) {
 193.834 +                    node.remove(optionID);
 193.835 +                } else {
 193.836 +                    node.put(optionID, text);
 193.837 +                }
 193.838 +            } else if (jc instanceof JCheckBox) {
 193.839 +                JCheckBox checkBox = (JCheckBox)jc;
 193.840 +                if (!optionID.equals(expandTabToSpaces) && getDefaultAsBoolean(optionID) == checkBox.isSelected()) {
 193.841 +                    node.remove(optionID);
 193.842 +                } else {
 193.843 +                    node.putBoolean(optionID, checkBox.isSelected());
 193.844 +                }
 193.845 +            } else if (jc instanceof JComboBox) {
 193.846 +                JComboBox cb = (JComboBox)jc;
 193.847 +                // Logger.global.info( cb.getSelectedItem() + " " + optionID);
 193.848 +                String value = ((ComboItem)cb.getSelectedItem()).value;
 193.849 +                if (getDefaultAsString(optionID).equals(value)) {
 193.850 +                    node.remove(optionID);
 193.851 +                } else {
 193.852 +                    node.put(optionID, value);
 193.853 +                }
 193.854 +            }
 193.855 +        }
 193.856 +
 193.857 +        private void addListener(JComponent jc) {
 193.858 +            if (jc instanceof JTextField) {
 193.859 +                JTextField field = (JTextField)jc;
 193.860 +                field.addActionListener(this);
 193.861 +                field.getDocument().addDocumentListener(this);
 193.862 +            } else if (jc instanceof JCheckBox) {
 193.863 +                JCheckBox checkBox = (JCheckBox)jc;
 193.864 +                checkBox.addActionListener(this);
 193.865 +            } else if (jc instanceof JComboBox) {
 193.866 +                JComboBox cb = (JComboBox)jc;
 193.867 +                cb.addActionListener(this);
 193.868 +            }
 193.869 +        }
 193.870 +
 193.871 +        private ComboBoxModel createModel(String value) {
 193.872 +
 193.873 +            // is it imports?
 193.874 +            for (ComboItem comboItem : cleanupImports) {
 193.875 +                if (value.equals(comboItem.value)) {
 193.876 +                    return new DefaultComboBoxModel(cleanupImports);
 193.877 +                }
 193.878 +            }
 193.879 +
 193.880 +            // is it wrap
 193.881 +            for (ComboItem comboItem : wrap) {
 193.882 +                if (value.equals(comboItem.value)) {
 193.883 +                    return new DefaultComboBoxModel(wrap);
 193.884 +                }
 193.885 +            }
 193.886 +
 193.887 +            return null;
 193.888 +        }
 193.889 +
 193.890 +        private static ComboItem whichItem(String value, ComboBoxModel model) {
 193.891 +
 193.892 +            for (int i = 0; i < model.getSize(); i++) {
 193.893 +                ComboItem item = (ComboItem)model.getElementAt(i);
 193.894 +                if (value.equals(item.value)) {
 193.895 +                    return item;
 193.896 +                }
 193.897 +            }
 193.898 +            return null;
 193.899 +        }
 193.900 +
 193.901 +        private static class ComboItem {
 193.902 +            String value;
 193.903 +            String displayName;
 193.904 +
 193.905 +            public ComboItem(String value, String key) {
 193.906 +                this.value = value;
 193.907 +                this.displayName = NbBundle.getMessage(FmtOptions.class, key);
 193.908 +            }
 193.909 +
 193.910 +            @Override
 193.911 +            public String toString() {
 193.912 +                return displayName;
 193.913 +            }
 193.914 +        }
 193.915 +    }
 193.916 +
 193.917 +    public static class PreviewPreferences extends AbstractPreferences {
 193.918 +        private Map<String, Object> map = new HashMap<>();
 193.919 +
 193.920 +        public PreviewPreferences() {
 193.921 +            super(null, ""); // NOI18N
 193.922 +        }
 193.923 +
 193.924 +        @Override
 193.925 +        protected void putSpi(String key, String value) {
 193.926 +            map.put(key, value);
 193.927 +        }
 193.928 +
 193.929 +        @Override
 193.930 +        protected String getSpi(String key) {
 193.931 +            return (String)map.get(key);
 193.932 +        }
 193.933 +
 193.934 +        @Override
 193.935 +        protected void removeSpi(String key) {
 193.936 +            map.remove(key);
 193.937 +        }
 193.938 +
 193.939 +        @Override
 193.940 +        protected void removeNodeSpi() throws BackingStoreException {
 193.941 +            throw new UnsupportedOperationException("Not supported yet.");
 193.942 +        }
 193.943 +
 193.944 +        @Override
 193.945 +        protected String[] keysSpi() throws BackingStoreException {
 193.946 +            String array[] = new String[map.keySet().size()];
 193.947 +            return map.keySet().toArray(array);
 193.948 +        }
 193.949 +
 193.950 +        @Override
 193.951 +        protected String[] childrenNamesSpi() throws BackingStoreException {
 193.952 +            throw new UnsupportedOperationException("Not supported yet.");
 193.953 +        }
 193.954 +
 193.955 +        @Override
 193.956 +        protected AbstractPreferences childSpi(String name) {
 193.957 +            throw new UnsupportedOperationException("Not supported yet.");
 193.958 +        }
 193.959 +
 193.960 +        @Override
 193.961 +        protected void syncSpi() throws BackingStoreException {
 193.962 +            throw new UnsupportedOperationException("Not supported yet.");
 193.963 +        }
 193.964 +
 193.965 +        @Override
 193.966 +        protected void flushSpi() throws BackingStoreException {
 193.967 +            throw new UnsupportedOperationException("Not supported yet.");
 193.968 +        }
 193.969 +    }
 193.970 +
 193.971 +    // read-only, no subnodes
 193.972 +    public static final class ProxyPreferences extends AbstractPreferences {
 193.973 +        private final Preferences[] delegates;
 193.974 +
 193.975 +        public ProxyPreferences(Preferences... delegates) {
 193.976 +            super(null, ""); // NOI18N
 193.977 +            this.delegates = delegates;
 193.978 +        }
 193.979 +
 193.980 +        @Override
 193.981 +        protected void putSpi(String key, String value) {
 193.982 +            throw new UnsupportedOperationException("Not supported yet.");
 193.983 +        }
 193.984 +
 193.985 +        @Override
 193.986 +        protected String getSpi(String key) {
 193.987 +            for (Preferences p : delegates) {
 193.988 +                String value = p.get(key, null);
 193.989 +                if (value != null) {
 193.990 +                    return value;
 193.991 +                }
 193.992 +            }
 193.993 +            return null;
 193.994 +        }
 193.995 +
 193.996 +        @Override
 193.997 +        protected void removeSpi(String key) {
 193.998 +            throw new UnsupportedOperationException("Not supported yet.");
 193.999 +        }
193.1000 +
193.1001 +        @Override
193.1002 +        protected void removeNodeSpi() throws BackingStoreException {
193.1003 +            throw new UnsupportedOperationException("Not supported yet.");
193.1004 +        }
193.1005 +
193.1006 +        @Override
193.1007 +        protected String[] keysSpi() throws BackingStoreException {
193.1008 +            Set<String> keys = new HashSet<>();
193.1009 +            for (Preferences p : delegates) {
193.1010 +                keys.addAll(Arrays.asList(p.keys()));
193.1011 +            }
193.1012 +            return keys.toArray(new String[keys.size()]);
193.1013 +        }
193.1014 +
193.1015 +        @Override
193.1016 +        protected String[] childrenNamesSpi() throws BackingStoreException {
193.1017 +            throw new UnsupportedOperationException("Not supported yet.");
193.1018 +        }
193.1019 +
193.1020 +        @Override
193.1021 +        protected AbstractPreferences childSpi(String name) {
193.1022 +            throw new UnsupportedOperationException("Not supported yet.");
193.1023 +        }
193.1024 +
193.1025 +        @Override
193.1026 +        protected void syncSpi() throws BackingStoreException {
193.1027 +            throw new UnsupportedOperationException("Not supported yet.");
193.1028 +        }
193.1029 +
193.1030 +        @Override
193.1031 +        protected void flushSpi() throws BackingStoreException {
193.1032 +            throw new UnsupportedOperationException("Not supported yet.");
193.1033 +        }
193.1034 +    } // End of ProxyPreferences class
193.1035 +
193.1036 +    public static interface CodeStyleProducer {
193.1037 +        public CodeStyle create(Preferences preferences);
193.1038 +    }
193.1039 +}
   194.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   194.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtSpaces.form	Sun Sep 13 11:47:42 2015 +0200
   194.3 @@ -0,0 +1,104 @@
   194.4 +<?xml version="1.0" encoding="UTF-8" ?>
   194.5 +
   194.6 +<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   194.7 +  <Properties>
   194.8 +    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   194.9 +      <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_Spaces" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  194.10 +    </Property>
  194.11 +    <Property name="opaque" type="boolean" value="false"/>
  194.12 +  </Properties>
  194.13 +  <AuxValues>
  194.14 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
  194.15 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  194.16 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  194.17 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
  194.18 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  194.19 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
  194.20 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
  194.21 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  194.22 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  194.23 +  </AuxValues>
  194.24 +
  194.25 +  <Layout>
  194.26 +    <DimensionLayout dim="0">
  194.27 +      <Group type="103" groupAlignment="0" attributes="0">
  194.28 +          <Group type="102" attributes="0">
  194.29 +              <Group type="103" groupAlignment="0" attributes="0">
  194.30 +                  <Component id="addAroundOp" alignment="0" min="-2" max="-2" attributes="0"/>
  194.31 +                  <Group type="102" alignment="0" attributes="0">
  194.32 +                      <EmptySpace min="27" pref="27" max="27" attributes="0"/>
  194.33 +                      <Component id="removeInParam" min="-2" max="-2" attributes="0"/>
  194.34 +                  </Group>
  194.35 +                  <Component id="removeInParen" alignment="0" min="-2" max="-2" attributes="0"/>
  194.36 +                  <Component id="addAfterComma" alignment="0" min="-2" max="-2" attributes="0"/>
  194.37 +                  <Component id="removeBeforeSep" alignment="0" min="-2" max="-2" attributes="0"/>
  194.38 +                  <Component id="collapseSpacesCb" alignment="0" min="-2" max="-2" attributes="0"/>
  194.39 +              </Group>
  194.40 +              <EmptySpace max="32767" attributes="0"/>
  194.41 +          </Group>
  194.42 +      </Group>
  194.43 +    </DimensionLayout>
  194.44 +    <DimensionLayout dim="1">
  194.45 +      <Group type="103" groupAlignment="0" attributes="0">
  194.46 +          <Group type="102" alignment="0" attributes="0">
  194.47 +              <Component id="addAroundOp" min="-2" max="-2" attributes="0"/>
  194.48 +              <EmptySpace max="-2" attributes="0"/>
  194.49 +              <Component id="removeInParam" min="-2" max="-2" attributes="0"/>
  194.50 +              <EmptySpace max="-2" attributes="0"/>
  194.51 +              <Component id="removeInParen" min="-2" max="-2" attributes="0"/>
  194.52 +              <EmptySpace max="-2" attributes="0"/>
  194.53 +              <Component id="addAfterComma" min="-2" max="-2" attributes="0"/>
  194.54 +              <EmptySpace max="-2" attributes="0"/>
  194.55 +              <Component id="removeBeforeSep" min="-2" max="-2" attributes="0"/>
  194.56 +              <EmptySpace max="-2" attributes="0"/>
  194.57 +              <Component id="collapseSpacesCb" min="-2" max="-2" attributes="0"/>
  194.58 +              <EmptySpace max="32767" attributes="0"/>
  194.59 +          </Group>
  194.60 +      </Group>
  194.61 +    </DimensionLayout>
  194.62 +  </Layout>
  194.63 +  <SubComponents>
  194.64 +    <Component class="javax.swing.JCheckBox" name="addAroundOp">
  194.65 +      <Properties>
  194.66 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  194.67 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtSpaces.addAroundOp.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  194.68 +        </Property>
  194.69 +      </Properties>
  194.70 +    </Component>
  194.71 +    <Component class="javax.swing.JCheckBox" name="removeInParam">
  194.72 +      <Properties>
  194.73 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  194.74 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtSpaces.removeInParam.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  194.75 +        </Property>
  194.76 +      </Properties>
  194.77 +    </Component>
  194.78 +    <Component class="javax.swing.JCheckBox" name="removeInParen">
  194.79 +      <Properties>
  194.80 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  194.81 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtSpaces.removeInParen.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  194.82 +        </Property>
  194.83 +      </Properties>
  194.84 +    </Component>
  194.85 +    <Component class="javax.swing.JCheckBox" name="addAfterComma">
  194.86 +      <Properties>
  194.87 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  194.88 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtSpaces.addAfterComma.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  194.89 +        </Property>
  194.90 +      </Properties>
  194.91 +    </Component>
  194.92 +    <Component class="javax.swing.JCheckBox" name="removeBeforeSep">
  194.93 +      <Properties>
  194.94 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  194.95 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtSpaces.removeBeforeSep.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  194.96 +        </Property>
  194.97 +      </Properties>
  194.98 +    </Component>
  194.99 +    <Component class="javax.swing.JCheckBox" name="collapseSpacesCb">
 194.100 +      <Properties>
 194.101 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 194.102 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="FmtSpaces.collapseSpacesCb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 194.103 +        </Property>
 194.104 +      </Properties>
 194.105 +    </Component>
 194.106 +  </SubComponents>
 194.107 +</Form>
   195.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   195.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtSpaces.java	Sun Sep 13 11:47:42 2015 +0200
   195.3 @@ -0,0 +1,143 @@
   195.4 +/*
   195.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   195.6 + *
   195.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   195.8 + *
   195.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  195.10 + * Other names may be trademarks of their respective owners.
  195.11 + *
  195.12 + * The contents of this file are subject to the terms of either the GNU
  195.13 + * General Public License Version 2 only ("GPL") or the Common
  195.14 + * Development and Distribution License("CDDL") (collectively, the
  195.15 + * "License"). You may not use this file except in compliance with the
  195.16 + * License. You can obtain a copy of the License at
  195.17 + * http://www.netbeans.org/cddl-gplv2.html
  195.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  195.19 + * specific language governing permissions and limitations under the
  195.20 + * License.  When distributing the software, include this License Header
  195.21 + * Notice in each file and include the License file at
  195.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  195.23 + * particular file as subject to the "Classpath" exception as provided
  195.24 + * by Oracle in the GPL Version 2 section of the License file that
  195.25 + * accompanied this code. If applicable, add the following below the
  195.26 + * License Header, with the fields enclosed by brackets [] replaced by
  195.27 + * your own identifying information:
  195.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  195.29 + *
  195.30 + * Contributor(s):
  195.31 + *
  195.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  195.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  195.34 + * Microsystems, Inc. All Rights Reserved.
  195.35 + *
  195.36 + * If you wish your version of this file to be governed by only the CDDL
  195.37 + * or only the GPL Version 2, indicate your decision by adding
  195.38 + * "[Contributor] elects to include this software in this distribution
  195.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  195.40 + * single choice of license, a recipient has the option to distribute
  195.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  195.42 + * to extend the choice of license to its licensees as provided above.
  195.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  195.44 + * Version 2 license, then the option applies only if the new code is
  195.45 + * made subject to such option by the copyright holder.
  195.46 + */
  195.47 +
  195.48 +package org.netbeans.modules.python.source.ui;
  195.49 +
  195.50 +import javax.swing.JPanel;
  195.51 +import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
  195.52 +import static org.netbeans.modules.python.source.ui.FmtOptions.*;
  195.53 +import static org.netbeans.modules.python.source.ui.FmtOptions.CategorySupport.OPTION_ID;
  195.54 +
  195.55 +/**
  195.56 + * Preferences for formatting related to spaces
  195.57 + * 
  195.58 + * @author  Tor Norbye
  195.59 + */
  195.60 +public class FmtSpaces extends JPanel {
  195.61 +    public FmtSpaces() {
  195.62 +        initComponents();
  195.63 +
  195.64 +        addAroundOp.putClientProperty(OPTION_ID, addSpaceAroundOperators);
  195.65 +        addAfterComma.putClientProperty(OPTION_ID, addSpaceAfterComma);
  195.66 +        removeBeforeSep.putClientProperty(OPTION_ID, removeSpaceBeforeSep);
  195.67 +        removeInParam.putClientProperty(OPTION_ID, removeSpaceInParamAssign);
  195.68 +        removeInParen.putClientProperty(OPTION_ID, removeSpaceInParens);
  195.69 +        collapseSpacesCb.putClientProperty(OPTION_ID, collapseSpaces);
  195.70 +    }
  195.71 +
  195.72 +    public static PreferencesCustomizer.Factory getController() {
  195.73 +        return new CategorySupport.Factory("spaces", FmtSpaces.class, // NOI18N
  195.74 +                org.openide.util.NbBundle.getMessage(FmtSpaces.class, "SAMPLE_Spaces"));
  195.75 +    }
  195.76 +    
  195.77 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  195.78 +    private void initComponents() {
  195.79 +
  195.80 +        addAroundOp = new javax.swing.JCheckBox();
  195.81 +        removeInParam = new javax.swing.JCheckBox();
  195.82 +        removeInParen = new javax.swing.JCheckBox();
  195.83 +        addAfterComma = new javax.swing.JCheckBox();
  195.84 +        removeBeforeSep = new javax.swing.JCheckBox();
  195.85 +        collapseSpacesCb = new javax.swing.JCheckBox();
  195.86 +
  195.87 +        setName(org.openide.util.NbBundle.getMessage(FmtSpaces.class, "LBL_Spaces")); // NOI18N
  195.88 +        setOpaque(false);
  195.89 +
  195.90 +        org.openide.awt.Mnemonics.setLocalizedText(addAroundOp, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.addAroundOp.text")); // NOI18N
  195.91 +
  195.92 +        org.openide.awt.Mnemonics.setLocalizedText(removeInParam, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.removeInParam.text")); // NOI18N
  195.93 +
  195.94 +        org.openide.awt.Mnemonics.setLocalizedText(removeInParen, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.removeInParen.text")); // NOI18N
  195.95 +
  195.96 +        org.openide.awt.Mnemonics.setLocalizedText(addAfterComma, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.addAfterComma.text")); // NOI18N
  195.97 +
  195.98 +        org.openide.awt.Mnemonics.setLocalizedText(removeBeforeSep, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.removeBeforeSep.text")); // NOI18N
  195.99 +
 195.100 +        org.openide.awt.Mnemonics.setLocalizedText(collapseSpacesCb, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.collapseSpacesCb.text")); // NOI18N
 195.101 +
 195.102 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
 195.103 +        this.setLayout(layout);
 195.104 +        layout.setHorizontalGroup(
 195.105 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 195.106 +            .addGroup(layout.createSequentialGroup()
 195.107 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 195.108 +                    .addComponent(addAroundOp)
 195.109 +                    .addGroup(layout.createSequentialGroup()
 195.110 +                        .addGap(27, 27, 27)
 195.111 +                        .addComponent(removeInParam))
 195.112 +                    .addComponent(removeInParen)
 195.113 +                    .addComponent(addAfterComma)
 195.114 +                    .addComponent(removeBeforeSep)
 195.115 +                    .addComponent(collapseSpacesCb))
 195.116 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 195.117 +        );
 195.118 +        layout.setVerticalGroup(
 195.119 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 195.120 +            .addGroup(layout.createSequentialGroup()
 195.121 +                .addComponent(addAroundOp)
 195.122 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 195.123 +                .addComponent(removeInParam)
 195.124 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 195.125 +                .addComponent(removeInParen)
 195.126 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 195.127 +                .addComponent(addAfterComma)
 195.128 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 195.129 +                .addComponent(removeBeforeSep)
 195.130 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 195.131 +                .addComponent(collapseSpacesCb)
 195.132 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 195.133 +        );
 195.134 +    }// </editor-fold>//GEN-END:initComponents
 195.135 +    
 195.136 +    
 195.137 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 195.138 +    private javax.swing.JCheckBox addAfterComma;
 195.139 +    private javax.swing.JCheckBox addAroundOp;
 195.140 +    private javax.swing.JCheckBox collapseSpacesCb;
 195.141 +    private javax.swing.JCheckBox removeBeforeSep;
 195.142 +    private javax.swing.JCheckBox removeInParam;
 195.143 +    private javax.swing.JCheckBox removeInParen;
 195.144 +    // End of variables declaration//GEN-END:variables
 195.145 +    
 195.146 +}
   196.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   196.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtTabsIndents.form	Sun Sep 13 11:47:42 2015 +0200
   196.3 @@ -0,0 +1,127 @@
   196.4 +<?xml version="1.0" encoding="UTF-8" ?>
   196.5 +
   196.6 +<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   196.7 +  <Properties>
   196.8 +    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   196.9 +      <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_TabsAndIndents" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  196.10 +    </Property>
  196.11 +    <Property name="opaque" type="boolean" value="false"/>
  196.12 +  </Properties>
  196.13 +  <AuxValues>
  196.14 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
  196.15 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  196.16 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  196.17 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
  196.18 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  196.19 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
  196.20 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
  196.21 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  196.22 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  196.23 +  </AuxValues>
  196.24 +
  196.25 +  <Layout>
  196.26 +    <DimensionLayout dim="0">
  196.27 +      <Group type="103" groupAlignment="0" attributes="0">
  196.28 +          <Group type="102" alignment="0" attributes="0">
  196.29 +              <Group type="103" groupAlignment="0" attributes="0">
  196.30 +                  <Component id="continuationIndentSizeLabel" max="32767" attributes="0"/>
  196.31 +                  <Component id="labelIndentLabel" min="-2" max="-2" attributes="0"/>
  196.32 +              </Group>
  196.33 +              <EmptySpace max="-2" attributes="0"/>
  196.34 +              <Group type="103" groupAlignment="1" attributes="0">
  196.35 +                  <Component id="continuationIndentSizeField" linkSize="2" min="-2" pref="36" max="-2" attributes="1"/>
  196.36 +                  <Component id="labelIndentField" linkSize="2" min="-2" pref="36" max="-2" attributes="1"/>
  196.37 +              </Group>
  196.38 +          </Group>
  196.39 +          <Component id="indentCasesFromSwitchCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
  196.40 +          <Component id="indentTopLevelClassMembersCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
  196.41 +          <Component id="absoluteLabelIndentCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
  196.42 +      </Group>
  196.43 +    </DimensionLayout>
  196.44 +    <DimensionLayout dim="1">
  196.45 +      <Group type="103" groupAlignment="0" attributes="0">
  196.46 +          <Group type="102" attributes="0">
  196.47 +              <EmptySpace max="-2" attributes="0"/>
  196.48 +              <Group type="103" groupAlignment="3" attributes="0">
  196.49 +                  <Component id="continuationIndentSizeLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  196.50 +                  <Component id="continuationIndentSizeField" alignment="3" min="-2" max="-2" attributes="0"/>
  196.51 +              </Group>
  196.52 +              <EmptySpace min="-2" max="-2" attributes="0"/>
  196.53 +              <Group type="103" groupAlignment="3" attributes="0">
  196.54 +                  <Component id="labelIndentLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  196.55 +                  <Component id="labelIndentField" alignment="3" min="-2" max="-2" attributes="0"/>
  196.56 +              </Group>
  196.57 +              <EmptySpace type="unrelated" max="-2" attributes="0"/>
  196.58 +              <Component id="absoluteLabelIndentCheckBox" min="-2" max="-2" attributes="0"/>
  196.59 +              <EmptySpace max="-2" attributes="0"/>
  196.60 +              <Component id="indentTopLevelClassMembersCheckBox" min="-2" max="-2" attributes="0"/>
  196.61 +              <EmptySpace max="-2" attributes="0"/>
  196.62 +              <Component id="indentCasesFromSwitchCheckBox" min="-2" max="-2" attributes="0"/>
  196.63 +              <EmptySpace max="32767" attributes="0"/>
  196.64 +          </Group>
  196.65 +      </Group>
  196.66 +    </DimensionLayout>
  196.67 +  </Layout>
  196.68 +  <SubComponents>
  196.69 +    <Component class="javax.swing.JLabel" name="continuationIndentSizeLabel">
  196.70 +      <Properties>
  196.71 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  196.72 +          <ComponentRef name="continuationIndentSizeField"/>
  196.73 +        </Property>
  196.74 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  196.75 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_ContinuationIndentSize" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  196.76 +        </Property>
  196.77 +      </Properties>
  196.78 +    </Component>
  196.79 +    <Component class="javax.swing.JTextField" name="continuationIndentSizeField">
  196.80 +    </Component>
  196.81 +    <Component class="javax.swing.JLabel" name="labelIndentLabel">
  196.82 +      <Properties>
  196.83 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  196.84 +          <ComponentRef name="labelIndentField"/>
  196.85 +        </Property>
  196.86 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  196.87 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_LabelIndent" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  196.88 +        </Property>
  196.89 +      </Properties>
  196.90 +    </Component>
  196.91 +    <Component class="javax.swing.JTextField" name="labelIndentField">
  196.92 +    </Component>
  196.93 +    <Component class="javax.swing.JCheckBox" name="absoluteLabelIndentCheckBox">
  196.94 +      <Properties>
  196.95 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  196.96 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_AbsoluteLabelIndent" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  196.97 +        </Property>
  196.98 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  196.99 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 196.100 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 196.101 +          </Border>
 196.102 +        </Property>
 196.103 +      </Properties>
 196.104 +    </Component>
 196.105 +    <Component class="javax.swing.JCheckBox" name="indentTopLevelClassMembersCheckBox">
 196.106 +      <Properties>
 196.107 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 196.108 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_IndentTopLevelClassMemberts" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 196.109 +        </Property>
 196.110 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 196.111 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 196.112 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 196.113 +          </Border>
 196.114 +        </Property>
 196.115 +      </Properties>
 196.116 +    </Component>
 196.117 +    <Component class="javax.swing.JCheckBox" name="indentCasesFromSwitchCheckBox">
 196.118 +      <Properties>
 196.119 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 196.120 +          <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_IndentCasesFromSwitch" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 196.121 +        </Property>
 196.122 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 196.123 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 196.124 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 196.125 +          </Border>
 196.126 +        </Property>
 196.127 +      </Properties>
 196.128 +    </Component>
 196.129 +  </SubComponents>
 196.130 +</Form>
   197.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   197.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtTabsIndents.java	Sun Sep 13 11:47:42 2015 +0200
   197.3 @@ -0,0 +1,196 @@
   197.4 +/*
   197.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   197.6 + *
   197.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   197.8 + *
   197.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  197.10 + * Other names may be trademarks of their respective owners.
  197.11 + *
  197.12 + * The contents of this file are subject to the terms of either the GNU
  197.13 + * General Public License Version 2 only ("GPL") or the Common
  197.14 + * Development and Distribution License("CDDL") (collectively, the
  197.15 + * "License"). You may not use this file except in compliance with the
  197.16 + * License. You can obtain a copy of the License at
  197.17 + * http://www.netbeans.org/cddl-gplv2.html
  197.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  197.19 + * specific language governing permissions and limitations under the
  197.20 + * License.  When distributing the software, include this License Header
  197.21 + * Notice in each file and include the License file at
  197.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  197.23 + * particular file as subject to the "Classpath" exception as provided
  197.24 + * by Oracle in the GPL Version 2 section of the License file that
  197.25 + * accompanied this code. If applicable, add the following below the
  197.26 + * License Header, with the fields enclosed by brackets [] replaced by
  197.27 + * your own identifying information:
  197.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  197.29 + *
  197.30 + * Contributor(s):
  197.31 + *
  197.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  197.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  197.34 + * Microsystems, Inc. All Rights Reserved.
  197.35 + *
  197.36 + * If you wish your version of this file to be governed by only the CDDL
  197.37 + * or only the GPL Version 2, indicate your decision by adding
  197.38 + * "[Contributor] elects to include this software in this distribution
  197.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  197.40 + * single choice of license, a recipient has the option to distribute
  197.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  197.42 + * to extend the choice of license to its licensees as provided above.
  197.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  197.44 + * Version 2 license, then the option applies only if the new code is
  197.45 + * made subject to such option by the copyright holder.
  197.46 + */
  197.47 +
  197.48 +package org.netbeans.modules.python.source.ui;
  197.49 +
  197.50 +//import org.netbeans.modules.python.source.CodeStyle.WrapStyle;
  197.51 +//import static org.netbeans.modules.python.source.ui.FmtOptions.*;
  197.52 +//import static org.netbeans.modules.python.source.ui.FmtOptions.CategorySupport.OPTION_ID;
  197.53 +//import org.netbeans.modules.python.source.ui.FmtOptions.CategorySupport;
  197.54 +//import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
  197.55 +
  197.56 +/**
  197.57 + *
  197.58 + * @author  phrebejk
  197.59 + */
  197.60 +public class FmtTabsIndents extends javax.swing.JPanel {
  197.61 +   
  197.62 +    /** Creates new form FmtTabsIndents */
  197.63 +    public FmtTabsIndents() {
  197.64 +        initComponents();
  197.65 +/*
  197.66 +//        expandTabCheckBox.putClientProperty(OPTION_ID, expandTabToSpaces);
  197.67 +//        tabSizeField.putClientProperty(OPTION_ID, tabSize);
  197.68 +//        indentSizeField.putClientProperty(OPTION_ID, new String [] { indentSize, spacesPerTab });
  197.69 +        continuationIndentSizeField.putClientProperty(OPTION_ID, continuationIndentSize);
  197.70 +        labelIndentField.putClientProperty(OPTION_ID, labelIndent);
  197.71 +        absoluteLabelIndentCheckBox.putClientProperty(OPTION_ID, absoluteLabelIndent);
  197.72 +        indentTopLevelClassMembersCheckBox.putClientProperty(OPTION_ID, indentTopLevelClassMembers);
  197.73 +        indentCasesFromSwitchCheckBox.putClientProperty(OPTION_ID, indentCasesFromSwitch);
  197.74 +//        rightMarginField.putClientProperty(OPTION_ID, rightMargin);
  197.75 +    }
  197.76 +    
  197.77 +    public static PreferencesCustomizer.Factory getController() {
  197.78 +        return new CategorySupport.Factory(PreferencesCustomizer.TABS_AND_INDENTS_ID, FmtTabsIndents.class, //NOI18N
  197.79 +                org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "SAMPLE_TabsIndents"), // NOI18N
  197.80 +                new String[] { FmtOptions.rightMargin, "30" }, //NOI18N
  197.81 +                new String[] { FmtOptions.wrapAnnotations, WrapStyle.WRAP_ALWAYS.name() },
  197.82 +                new String[] { FmtOptions.wrapArrayInit, WrapStyle.WRAP_ALWAYS.name() },
  197.83 +                new String[] { FmtOptions.wrapAssert, WrapStyle.WRAP_ALWAYS.name() },
  197.84 +                new String[] { FmtOptions.wrapAssignOps, WrapStyle.WRAP_ALWAYS.name() },
  197.85 +                new String[] { FmtOptions.wrapBinaryOps, WrapStyle.WRAP_ALWAYS.name() },
  197.86 +                new String[] { FmtOptions.wrapChainedMethodCalls, WrapStyle.WRAP_ALWAYS.name() },
  197.87 +                new String[] { FmtOptions.wrapDoWhileStatement, WrapStyle.WRAP_ALWAYS.name() },
  197.88 +                new String[] { FmtOptions.wrapEnumConstants, WrapStyle.WRAP_ALWAYS.name() },
  197.89 +                new String[] { FmtOptions.wrapExtendsImplementsKeyword, WrapStyle.WRAP_ALWAYS.name() },
  197.90 +                new String[] { FmtOptions.wrapExtendsImplementsList, WrapStyle.WRAP_ALWAYS.name() },
  197.91 +                new String[] { FmtOptions.wrapFor, WrapStyle.WRAP_ALWAYS.name() },
  197.92 +                new String[] { FmtOptions.wrapForStatement, WrapStyle.WRAP_ALWAYS.name() },
  197.93 +                new String[] { FmtOptions.wrapIfStatement, WrapStyle.WRAP_ALWAYS.name() },
  197.94 +                new String[] { FmtOptions.wrapMethodCallArgs, WrapStyle.WRAP_ALWAYS.name() },
  197.95 +                new String[] { FmtOptions.wrapMethodParams, WrapStyle.WRAP_ALWAYS.name() },
  197.96 +                new String[] { FmtOptions.wrapTernaryOps, WrapStyle.WRAP_ALWAYS.name() },
  197.97 +                new String[] { FmtOptions.wrapThrowsKeyword, WrapStyle.WRAP_ALWAYS.name() },
  197.98 +                new String[] { FmtOptions.wrapThrowsList, WrapStyle.WRAP_ALWAYS.name() },
  197.99 +                new String[] { FmtOptions.wrapWhileStatement, WrapStyle.WRAP_ALWAYS.name() },
 197.100 +                new String[] { FmtOptions.alignMultilineArrayInit, Boolean.FALSE.toString() },
 197.101 +                new String[] { FmtOptions.alignMultilineAssignment, Boolean.FALSE.toString() },
 197.102 +                new String[] { FmtOptions.alignMultilineBinaryOp, Boolean.FALSE.toString() },
 197.103 +                new String[] { FmtOptions.alignMultilineCallArgs, Boolean.FALSE.toString() },
 197.104 +                new String[] { FmtOptions.alignMultilineFor, Boolean.FALSE.toString() },
 197.105 +                new String[] { FmtOptions.alignMultilineImplements, Boolean.FALSE.toString() },
 197.106 +                new String[] { FmtOptions.alignMultilineMethodParams, Boolean.FALSE.toString() },
 197.107 +                new String[] { FmtOptions.alignMultilineParenthesized, Boolean.FALSE.toString() },
 197.108 +                new String[] { FmtOptions.alignMultilineTernaryOp, Boolean.FALSE.toString() },
 197.109 +                new String[] { FmtOptions.alignMultilineThrows, Boolean.FALSE.toString() }
 197.110 +                );
 197.111 + */
 197.112 +    }
 197.113 +    
 197.114 +    /** This method is called from within the constructor to
 197.115 +     * initialize the form.
 197.116 +     * WARNING: Do NOT modify this code. The content of this method is
 197.117 +     * always regenerated by the Form Editor.
 197.118 +     */
 197.119 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
 197.120 +    private void initComponents() {
 197.121 +
 197.122 +        continuationIndentSizeLabel = new javax.swing.JLabel();
 197.123 +        continuationIndentSizeField = new javax.swing.JTextField();
 197.124 +        labelIndentLabel = new javax.swing.JLabel();
 197.125 +        labelIndentField = new javax.swing.JTextField();
 197.126 +        absoluteLabelIndentCheckBox = new javax.swing.JCheckBox();
 197.127 +        indentTopLevelClassMembersCheckBox = new javax.swing.JCheckBox();
 197.128 +        indentCasesFromSwitchCheckBox = new javax.swing.JCheckBox();
 197.129 +
 197.130 +        setName(org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_TabsAndIndents")); // NOI18N
 197.131 +        setOpaque(false);
 197.132 +
 197.133 +        continuationIndentSizeLabel.setLabelFor(continuationIndentSizeField);
 197.134 +        org.openide.awt.Mnemonics.setLocalizedText(continuationIndentSizeLabel, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_ContinuationIndentSize")); // NOI18N
 197.135 +
 197.136 +        labelIndentLabel.setLabelFor(labelIndentField);
 197.137 +        org.openide.awt.Mnemonics.setLocalizedText(labelIndentLabel, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_LabelIndent")); // NOI18N
 197.138 +
 197.139 +        org.openide.awt.Mnemonics.setLocalizedText(absoluteLabelIndentCheckBox, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_AbsoluteLabelIndent")); // NOI18N
 197.140 +        absoluteLabelIndentCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 197.141 +
 197.142 +        org.openide.awt.Mnemonics.setLocalizedText(indentTopLevelClassMembersCheckBox, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_IndentTopLevelClassMemberts")); // NOI18N
 197.143 +        indentTopLevelClassMembersCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 197.144 +
 197.145 +        org.openide.awt.Mnemonics.setLocalizedText(indentCasesFromSwitchCheckBox, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_IndentCasesFromSwitch")); // NOI18N
 197.146 +        indentCasesFromSwitchCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 197.147 +
 197.148 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
 197.149 +        this.setLayout(layout);
 197.150 +        layout.setHorizontalGroup(
 197.151 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 197.152 +            .addGroup(layout.createSequentialGroup()
 197.153 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 197.154 +                    .addComponent(continuationIndentSizeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 197.155 +                    .addComponent(labelIndentLabel))
 197.156 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 197.157 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
 197.158 +                    .addComponent(continuationIndentSizeField, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE)
 197.159 +                    .addComponent(labelIndentField, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE)))
 197.160 +            .addComponent(indentCasesFromSwitchCheckBox)
 197.161 +            .addComponent(indentTopLevelClassMembersCheckBox)
 197.162 +            .addComponent(absoluteLabelIndentCheckBox)
 197.163 +        );
 197.164 +
 197.165 +        layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {continuationIndentSizeField, labelIndentField});
 197.166 +
 197.167 +        layout.setVerticalGroup(
 197.168 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 197.169 +            .addGroup(layout.createSequentialGroup()
 197.170 +                .addContainerGap()
 197.171 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 197.172 +                    .addComponent(continuationIndentSizeLabel)
 197.173 +                    .addComponent(continuationIndentSizeField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 197.174 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 197.175 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 197.176 +                    .addComponent(labelIndentLabel)
 197.177 +                    .addComponent(labelIndentField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 197.178 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 197.179 +                .addComponent(absoluteLabelIndentCheckBox)
 197.180 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 197.181 +                .addComponent(indentTopLevelClassMembersCheckBox)
 197.182 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 197.183 +                .addComponent(indentCasesFromSwitchCheckBox)
 197.184 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 197.185 +        );
 197.186 +    }// </editor-fold>//GEN-END:initComponents
 197.187 +    
 197.188 +    
 197.189 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 197.190 +    private javax.swing.JCheckBox absoluteLabelIndentCheckBox;
 197.191 +    private javax.swing.JTextField continuationIndentSizeField;
 197.192 +    private javax.swing.JLabel continuationIndentSizeLabel;
 197.193 +    private javax.swing.JCheckBox indentCasesFromSwitchCheckBox;
 197.194 +    private javax.swing.JCheckBox indentTopLevelClassMembersCheckBox;
 197.195 +    private javax.swing.JTextField labelIndentField;
 197.196 +    private javax.swing.JLabel labelIndentLabel;
 197.197 +    // End of variables declaration//GEN-END:variables
 197.198 +    
 197.199 +}
   198.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   198.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtWrapping.form	Sun Sep 13 11:47:42 2015 +0200
   198.3 @@ -0,0 +1,706 @@
   198.4 +<?xml version="1.0" encoding="UTF-8" ?>
   198.5 +
   198.6 +<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   198.7 +  <Properties>
   198.8 +    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   198.9 +      <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_Wrapping" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  198.10 +    </Property>
  198.11 +    <Property name="opaque" type="boolean" value="false"/>
  198.12 +  </Properties>
  198.13 +  <AuxValues>
  198.14 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
  198.15 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  198.16 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  198.17 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
  198.18 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  198.19 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
  198.20 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
  198.21 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  198.22 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  198.23 +    <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,45,0,0,1,42"/>
  198.24 +  </AuxValues>
  198.25 +
  198.26 +  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
  198.27 +  <SubComponents>
  198.28 +    <Container class="javax.swing.JScrollPane" name="scrollPane">
  198.29 +      <Properties>
  198.30 +        <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
  198.31 +          <Dimension value="[300, 200]"/>
  198.32 +        </Property>
  198.33 +        <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
  198.34 +          <Dimension value="[350, 600]"/>
  198.35 +        </Property>
  198.36 +      </Properties>
  198.37 +      <Constraints>
  198.38 +        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
  198.39 +          <BorderConstraints direction="Center"/>
  198.40 +        </Constraint>
  198.41 +      </Constraints>
  198.42 +
  198.43 +      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
  198.44 +      <SubComponents>
  198.45 +        <Container class="javax.swing.JPanel" name="panel1">
  198.46 +          <Properties>
  198.47 +            <Property name="opaque" type="boolean" value="false"/>
  198.48 +          </Properties>
  198.49 +
  198.50 +          <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
  198.51 +          <SubComponents>
  198.52 +            <Component class="javax.swing.JLabel" name="extendsImplemetsKeywordLabel">
  198.53 +              <Properties>
  198.54 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  198.55 +                  <ComponentRef name="extendsImplementsKeywordCombo"/>
  198.56 +                </Property>
  198.57 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  198.58 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_extendsImplementsKeyword" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  198.59 +                </Property>
  198.60 +              </Properties>
  198.61 +              <Constraints>
  198.62 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  198.63 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="8" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  198.64 +                </Constraint>
  198.65 +              </Constraints>
  198.66 +            </Component>
  198.67 +            <Component class="javax.swing.JComboBox" name="extendsImplementsKeywordCombo">
  198.68 +              <Properties>
  198.69 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  198.70 +                  <StringArray count="4">
  198.71 +                    <StringItem index="0" value="Item 1"/>
  198.72 +                    <StringItem index="1" value="Item 2"/>
  198.73 +                    <StringItem index="2" value="Item 3"/>
  198.74 +                    <StringItem index="3" value="Item 4"/>
  198.75 +                  </StringArray>
  198.76 +                </Property>
  198.77 +              </Properties>
  198.78 +              <Constraints>
  198.79 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  198.80 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="8" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="1.0" weightY="0.0"/>
  198.81 +                </Constraint>
  198.82 +              </Constraints>
  198.83 +            </Component>
  198.84 +            <Component class="javax.swing.JLabel" name="extendsImplementsListLabel">
  198.85 +              <Properties>
  198.86 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  198.87 +                  <ComponentRef name="extendsImplementsListCombo"/>
  198.88 +                </Property>
  198.89 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  198.90 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_extendsImplementsList" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  198.91 +                </Property>
  198.92 +              </Properties>
  198.93 +              <Constraints>
  198.94 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  198.95 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
  198.96 +                </Constraint>
  198.97 +              </Constraints>
  198.98 +            </Component>
  198.99 +            <Component class="javax.swing.JComboBox" name="extendsImplementsListCombo">
 198.100 +              <Properties>
 198.101 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.102 +                  <StringArray count="4">
 198.103 +                    <StringItem index="0" value="Item 1"/>
 198.104 +                    <StringItem index="1" value="Item 2"/>
 198.105 +                    <StringItem index="2" value="Item 3"/>
 198.106 +                    <StringItem index="3" value="Item 4"/>
 198.107 +                  </StringArray>
 198.108 +                </Property>
 198.109 +              </Properties>
 198.110 +              <Constraints>
 198.111 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.112 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.113 +                </Constraint>
 198.114 +              </Constraints>
 198.115 +            </Component>
 198.116 +            <Component class="javax.swing.JLabel" name="methodParamsLabel">
 198.117 +              <Properties>
 198.118 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.119 +                  <ComponentRef name="methodParamsCombo"/>
 198.120 +                </Property>
 198.121 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.122 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_methodParameters" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.123 +                </Property>
 198.124 +              </Properties>
 198.125 +              <Constraints>
 198.126 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.127 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.128 +                </Constraint>
 198.129 +              </Constraints>
 198.130 +            </Component>
 198.131 +            <Component class="javax.swing.JComboBox" name="methodParamsCombo">
 198.132 +              <Properties>
 198.133 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.134 +                  <StringArray count="4">
 198.135 +                    <StringItem index="0" value="Item 1"/>
 198.136 +                    <StringItem index="1" value="Item 2"/>
 198.137 +                    <StringItem index="2" value="Item 3"/>
 198.138 +                    <StringItem index="3" value="Item 4"/>
 198.139 +                  </StringArray>
 198.140 +                </Property>
 198.141 +              </Properties>
 198.142 +              <Constraints>
 198.143 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.144 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.145 +                </Constraint>
 198.146 +              </Constraints>
 198.147 +            </Component>
 198.148 +            <Component class="javax.swing.JLabel" name="methodCallArgsLabel">
 198.149 +              <Properties>
 198.150 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.151 +                  <ComponentRef name="methodCallArgsCombo"/>
 198.152 +                </Property>
 198.153 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.154 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_methodCallArgs" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.155 +                </Property>
 198.156 +              </Properties>
 198.157 +              <Constraints>
 198.158 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.159 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.160 +                </Constraint>
 198.161 +              </Constraints>
 198.162 +            </Component>
 198.163 +            <Component class="javax.swing.JComboBox" name="methodCallArgsCombo">
 198.164 +              <Properties>
 198.165 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.166 +                  <StringArray count="4">
 198.167 +                    <StringItem index="0" value="Item 1"/>
 198.168 +                    <StringItem index="1" value="Item 2"/>
 198.169 +                    <StringItem index="2" value="Item 3"/>
 198.170 +                    <StringItem index="3" value="Item 4"/>
 198.171 +                  </StringArray>
 198.172 +                </Property>
 198.173 +              </Properties>
 198.174 +              <Constraints>
 198.175 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.176 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.177 +                </Constraint>
 198.178 +              </Constraints>
 198.179 +            </Component>
 198.180 +            <Component class="javax.swing.JLabel" name="annotationArgsLabel">
 198.181 +              <Properties>
 198.182 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.183 +                  <ComponentRef name="annotationArgsCombo"/>
 198.184 +                </Property>
 198.185 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.186 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_annotationArgs" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.187 +                </Property>
 198.188 +              </Properties>
 198.189 +              <Constraints>
 198.190 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.191 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.192 +                </Constraint>
 198.193 +              </Constraints>
 198.194 +            </Component>
 198.195 +            <Component class="javax.swing.JComboBox" name="annotationArgsCombo">
 198.196 +              <Properties>
 198.197 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.198 +                  <StringArray count="4">
 198.199 +                    <StringItem index="0" value="Item 1"/>
 198.200 +                    <StringItem index="1" value="Item 2"/>
 198.201 +                    <StringItem index="2" value="Item 3"/>
 198.202 +                    <StringItem index="3" value="Item 4"/>
 198.203 +                  </StringArray>
 198.204 +                </Property>
 198.205 +              </Properties>
 198.206 +              <Constraints>
 198.207 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.208 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.209 +                </Constraint>
 198.210 +              </Constraints>
 198.211 +            </Component>
 198.212 +            <Component class="javax.swing.JLabel" name="chainedMethodCallsLabel">
 198.213 +              <Properties>
 198.214 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.215 +                  <ComponentRef name="chainedMethodCallsCombo"/>
 198.216 +                </Property>
 198.217 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.218 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_chainedMethodCalls" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.219 +                </Property>
 198.220 +              </Properties>
 198.221 +              <Constraints>
 198.222 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.223 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.224 +                </Constraint>
 198.225 +              </Constraints>
 198.226 +            </Component>
 198.227 +            <Component class="javax.swing.JComboBox" name="chainedMethodCallsCombo">
 198.228 +              <Properties>
 198.229 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.230 +                  <StringArray count="4">
 198.231 +                    <StringItem index="0" value="Item 1"/>
 198.232 +                    <StringItem index="1" value="Item 2"/>
 198.233 +                    <StringItem index="2" value="Item 3"/>
 198.234 +                    <StringItem index="3" value="Item 4"/>
 198.235 +                  </StringArray>
 198.236 +                </Property>
 198.237 +              </Properties>
 198.238 +              <Constraints>
 198.239 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.240 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.241 +                </Constraint>
 198.242 +              </Constraints>
 198.243 +            </Component>
 198.244 +            <Component class="javax.swing.JLabel" name="throwsKeywordLabel">
 198.245 +              <Properties>
 198.246 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.247 +                  <ComponentRef name="throwsKeywordCombo"/>
 198.248 +                </Property>
 198.249 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.250 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_throwsKeyword" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.251 +                </Property>
 198.252 +              </Properties>
 198.253 +              <Constraints>
 198.254 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.255 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.256 +                </Constraint>
 198.257 +              </Constraints>
 198.258 +            </Component>
 198.259 +            <Component class="javax.swing.JComboBox" name="throwsKeywordCombo">
 198.260 +              <Properties>
 198.261 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.262 +                  <StringArray count="4">
 198.263 +                    <StringItem index="0" value="Item 1"/>
 198.264 +                    <StringItem index="1" value="Item 2"/>
 198.265 +                    <StringItem index="2" value="Item 3"/>
 198.266 +                    <StringItem index="3" value="Item 4"/>
 198.267 +                  </StringArray>
 198.268 +                </Property>
 198.269 +              </Properties>
 198.270 +              <Constraints>
 198.271 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.272 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.273 +                </Constraint>
 198.274 +              </Constraints>
 198.275 +            </Component>
 198.276 +            <Component class="javax.swing.JLabel" name="throwsListLabel">
 198.277 +              <Properties>
 198.278 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.279 +                  <ComponentRef name="throwsListCombo"/>
 198.280 +                </Property>
 198.281 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.282 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_throwsList" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.283 +                </Property>
 198.284 +              </Properties>
 198.285 +              <Constraints>
 198.286 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.287 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.288 +                </Constraint>
 198.289 +              </Constraints>
 198.290 +            </Component>
 198.291 +            <Component class="javax.swing.JComboBox" name="throwsListCombo">
 198.292 +              <Properties>
 198.293 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.294 +                  <StringArray count="4">
 198.295 +                    <StringItem index="0" value="Item 1"/>
 198.296 +                    <StringItem index="1" value="Item 2"/>
 198.297 +                    <StringItem index="2" value="Item 3"/>
 198.298 +                    <StringItem index="3" value="Item 4"/>
 198.299 +                  </StringArray>
 198.300 +                </Property>
 198.301 +              </Properties>
 198.302 +              <Constraints>
 198.303 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.304 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.305 +                </Constraint>
 198.306 +              </Constraints>
 198.307 +            </Component>
 198.308 +            <Component class="javax.swing.JLabel" name="arrayInitLabel">
 198.309 +              <Properties>
 198.310 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.311 +                  <ComponentRef name="arrayInitCombo"/>
 198.312 +                </Property>
 198.313 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.314 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_arrayInit" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.315 +                </Property>
 198.316 +              </Properties>
 198.317 +              <Constraints>
 198.318 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.319 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.320 +                </Constraint>
 198.321 +              </Constraints>
 198.322 +            </Component>
 198.323 +            <Component class="javax.swing.JComboBox" name="arrayInitCombo">
 198.324 +              <Properties>
 198.325 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.326 +                  <StringArray count="4">
 198.327 +                    <StringItem index="0" value="Item 1"/>
 198.328 +                    <StringItem index="1" value="Item 2"/>
 198.329 +                    <StringItem index="2" value="Item 3"/>
 198.330 +                    <StringItem index="3" value="Item 4"/>
 198.331 +                  </StringArray>
 198.332 +                </Property>
 198.333 +              </Properties>
 198.334 +              <Constraints>
 198.335 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.336 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.337 +                </Constraint>
 198.338 +              </Constraints>
 198.339 +            </Component>
 198.340 +            <Component class="javax.swing.JLabel" name="forLabel">
 198.341 +              <Properties>
 198.342 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.343 +                  <ComponentRef name="forCombo"/>
 198.344 +                </Property>
 198.345 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.346 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_for" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.347 +                </Property>
 198.348 +              </Properties>
 198.349 +              <Constraints>
 198.350 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.351 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.352 +                </Constraint>
 198.353 +              </Constraints>
 198.354 +            </Component>
 198.355 +            <Component class="javax.swing.JComboBox" name="forCombo">
 198.356 +              <Properties>
 198.357 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.358 +                  <StringArray count="4">
 198.359 +                    <StringItem index="0" value="Item 1"/>
 198.360 +                    <StringItem index="1" value="Item 2"/>
 198.361 +                    <StringItem index="2" value="Item 3"/>
 198.362 +                    <StringItem index="3" value="Item 4"/>
 198.363 +                  </StringArray>
 198.364 +                </Property>
 198.365 +              </Properties>
 198.366 +              <Constraints>
 198.367 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.368 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.369 +                </Constraint>
 198.370 +              </Constraints>
 198.371 +            </Component>
 198.372 +            <Component class="javax.swing.JLabel" name="forStatementLabel">
 198.373 +              <Properties>
 198.374 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.375 +                  <ComponentRef name="forStatementCombo"/>
 198.376 +                </Property>
 198.377 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.378 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_forStatement" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.379 +                </Property>
 198.380 +              </Properties>
 198.381 +              <Constraints>
 198.382 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.383 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.384 +                </Constraint>
 198.385 +              </Constraints>
 198.386 +            </Component>
 198.387 +            <Component class="javax.swing.JComboBox" name="forStatementCombo">
 198.388 +              <Properties>
 198.389 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.390 +                  <StringArray count="4">
 198.391 +                    <StringItem index="0" value="Item 1"/>
 198.392 +                    <StringItem index="1" value="Item 2"/>
 198.393 +                    <StringItem index="2" value="Item 3"/>
 198.394 +                    <StringItem index="3" value="Item 4"/>
 198.395 +                  </StringArray>
 198.396 +                </Property>
 198.397 +              </Properties>
 198.398 +              <Constraints>
 198.399 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.400 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="1.0" weightY="0.0"/>
 198.401 +                </Constraint>
 198.402 +              </Constraints>
 198.403 +            </Component>
 198.404 +            <Component class="javax.swing.JLabel" name="ifStatementLabel">
 198.405 +              <Properties>
 198.406 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.407 +                  <ComponentRef name="ifStatementCombo"/>
 198.408 +                </Property>
 198.409 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.410 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_ifStatement" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.411 +                </Property>
 198.412 +              </Properties>
 198.413 +              <Constraints>
 198.414 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.415 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.416 +                </Constraint>
 198.417 +              </Constraints>
 198.418 +            </Component>
 198.419 +            <Component class="javax.swing.JComboBox" name="ifStatementCombo">
 198.420 +              <Properties>
 198.421 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.422 +                  <StringArray count="4">
 198.423 +                    <StringItem index="0" value="Item 1"/>
 198.424 +                    <StringItem index="1" value="Item 2"/>
 198.425 +                    <StringItem index="2" value="Item 3"/>
 198.426 +                    <StringItem index="3" value="Item 4"/>
 198.427 +                  </StringArray>
 198.428 +                </Property>
 198.429 +              </Properties>
 198.430 +              <Constraints>
 198.431 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.432 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.433 +                </Constraint>
 198.434 +              </Constraints>
 198.435 +            </Component>
 198.436 +            <Component class="javax.swing.JLabel" name="whileStatementLabel">
 198.437 +              <Properties>
 198.438 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.439 +                  <ComponentRef name="whileStatementComboBox"/>
 198.440 +                </Property>
 198.441 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.442 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_whileStatement" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.443 +                </Property>
 198.444 +              </Properties>
 198.445 +              <Constraints>
 198.446 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.447 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.448 +                </Constraint>
 198.449 +              </Constraints>
 198.450 +            </Component>
 198.451 +            <Component class="javax.swing.JComboBox" name="whileStatementComboBox">
 198.452 +              <Properties>
 198.453 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.454 +                  <StringArray count="4">
 198.455 +                    <StringItem index="0" value="Item 1"/>
 198.456 +                    <StringItem index="1" value="Item 2"/>
 198.457 +                    <StringItem index="2" value="Item 3"/>
 198.458 +                    <StringItem index="3" value="Item 4"/>
 198.459 +                  </StringArray>
 198.460 +                </Property>
 198.461 +              </Properties>
 198.462 +              <Constraints>
 198.463 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.464 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.465 +                </Constraint>
 198.466 +              </Constraints>
 198.467 +            </Component>
 198.468 +            <Component class="javax.swing.JLabel" name="doWhileStatementLabel">
 198.469 +              <Properties>
 198.470 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.471 +                  <ComponentRef name="doWhileStatementCombo"/>
 198.472 +                </Property>
 198.473 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.474 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_doWhileStatement" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.475 +                </Property>
 198.476 +              </Properties>
 198.477 +              <Constraints>
 198.478 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.479 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.480 +                </Constraint>
 198.481 +              </Constraints>
 198.482 +            </Component>
 198.483 +            <Component class="javax.swing.JComboBox" name="doWhileStatementCombo">
 198.484 +              <Properties>
 198.485 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.486 +                  <StringArray count="4">
 198.487 +                    <StringItem index="0" value="Item 1"/>
 198.488 +                    <StringItem index="1" value="Item 2"/>
 198.489 +                    <StringItem index="2" value="Item 3"/>
 198.490 +                    <StringItem index="3" value="Item 4"/>
 198.491 +                  </StringArray>
 198.492 +                </Property>
 198.493 +              </Properties>
 198.494 +              <Constraints>
 198.495 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.496 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.497 +                </Constraint>
 198.498 +              </Constraints>
 198.499 +            </Component>
 198.500 +            <Component class="javax.swing.JLabel" name="assertLabel">
 198.501 +              <Properties>
 198.502 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.503 +                  <ComponentRef name="assertCombo"/>
 198.504 +                </Property>
 198.505 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.506 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_assert" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.507 +                </Property>
 198.508 +              </Properties>
 198.509 +              <Constraints>
 198.510 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.511 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.512 +                </Constraint>
 198.513 +              </Constraints>
 198.514 +            </Component>
 198.515 +            <Component class="javax.swing.JComboBox" name="assertCombo">
 198.516 +              <Properties>
 198.517 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.518 +                  <StringArray count="4">
 198.519 +                    <StringItem index="0" value="Item 1"/>
 198.520 +                    <StringItem index="1" value="Item 2"/>
 198.521 +                    <StringItem index="2" value="Item 3"/>
 198.522 +                    <StringItem index="3" value="Item 4"/>
 198.523 +                  </StringArray>
 198.524 +                </Property>
 198.525 +              </Properties>
 198.526 +              <Constraints>
 198.527 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.528 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.529 +                </Constraint>
 198.530 +              </Constraints>
 198.531 +            </Component>
 198.532 +            <Component class="javax.swing.JLabel" name="enumConstantsLabel">
 198.533 +              <Properties>
 198.534 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.535 +                  <ComponentRef name="enumConstantsCombo"/>
 198.536 +                </Property>
 198.537 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.538 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_enumConstants" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.539 +                </Property>
 198.540 +              </Properties>
 198.541 +              <Constraints>
 198.542 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.543 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.544 +                </Constraint>
 198.545 +              </Constraints>
 198.546 +            </Component>
 198.547 +            <Component class="javax.swing.JComboBox" name="enumConstantsCombo">
 198.548 +              <Properties>
 198.549 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.550 +                  <StringArray count="4">
 198.551 +                    <StringItem index="0" value="Item 1"/>
 198.552 +                    <StringItem index="1" value="Item 2"/>
 198.553 +                    <StringItem index="2" value="Item 3"/>
 198.554 +                    <StringItem index="3" value="Item 4"/>
 198.555 +                  </StringArray>
 198.556 +                </Property>
 198.557 +              </Properties>
 198.558 +              <Constraints>
 198.559 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.560 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.561 +                </Constraint>
 198.562 +              </Constraints>
 198.563 +            </Component>
 198.564 +            <Component class="javax.swing.JLabel" name="annotationsLabel">
 198.565 +              <Properties>
 198.566 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.567 +                  <ComponentRef name="annotationsCombo"/>
 198.568 +                </Property>
 198.569 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.570 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_annotations" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.571 +                </Property>
 198.572 +              </Properties>
 198.573 +              <Constraints>
 198.574 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.575 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.576 +                </Constraint>
 198.577 +              </Constraints>
 198.578 +            </Component>
 198.579 +            <Component class="javax.swing.JComboBox" name="annotationsCombo">
 198.580 +              <Properties>
 198.581 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.582 +                  <StringArray count="4">
 198.583 +                    <StringItem index="0" value="Item 1"/>
 198.584 +                    <StringItem index="1" value="Item 2"/>
 198.585 +                    <StringItem index="2" value="Item 3"/>
 198.586 +                    <StringItem index="3" value="Item 4"/>
 198.587 +                  </StringArray>
 198.588 +                </Property>
 198.589 +              </Properties>
 198.590 +              <Constraints>
 198.591 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.592 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.593 +                </Constraint>
 198.594 +              </Constraints>
 198.595 +            </Component>
 198.596 +            <Component class="javax.swing.JLabel" name="binaryOpsLabel">
 198.597 +              <Properties>
 198.598 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.599 +                  <ComponentRef name="binaryOpsCombo"/>
 198.600 +                </Property>
 198.601 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.602 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_binaryOps" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.603 +                </Property>
 198.604 +              </Properties>
 198.605 +              <Constraints>
 198.606 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.607 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.608 +                </Constraint>
 198.609 +              </Constraints>
 198.610 +            </Component>
 198.611 +            <Component class="javax.swing.JComboBox" name="binaryOpsCombo">
 198.612 +              <Properties>
 198.613 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.614 +                  <StringArray count="4">
 198.615 +                    <StringItem index="0" value="Item 1"/>
 198.616 +                    <StringItem index="1" value="Item 2"/>
 198.617 +                    <StringItem index="2" value="Item 3"/>
 198.618 +                    <StringItem index="3" value="Item 4"/>
 198.619 +                  </StringArray>
 198.620 +                </Property>
 198.621 +              </Properties>
 198.622 +              <Constraints>
 198.623 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.624 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.625 +                </Constraint>
 198.626 +              </Constraints>
 198.627 +            </Component>
 198.628 +            <Component class="javax.swing.JLabel" name="ternaryOpsLabel">
 198.629 +              <Properties>
 198.630 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.631 +                  <ComponentRef name="ternaryOpsCombo"/>
 198.632 +                </Property>
 198.633 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.634 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_ternaryOps" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.635 +                </Property>
 198.636 +              </Properties>
 198.637 +              <Constraints>
 198.638 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.639 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.640 +                </Constraint>
 198.641 +              </Constraints>
 198.642 +            </Component>
 198.643 +            <Component class="javax.swing.JComboBox" name="ternaryOpsCombo">
 198.644 +              <Properties>
 198.645 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.646 +                  <StringArray count="4">
 198.647 +                    <StringItem index="0" value="Item 1"/>
 198.648 +                    <StringItem index="1" value="Item 2"/>
 198.649 +                    <StringItem index="2" value="Item 3"/>
 198.650 +                    <StringItem index="3" value="Item 4"/>
 198.651 +                  </StringArray>
 198.652 +                </Property>
 198.653 +              </Properties>
 198.654 +              <Constraints>
 198.655 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.656 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.657 +                </Constraint>
 198.658 +              </Constraints>
 198.659 +            </Component>
 198.660 +            <Component class="javax.swing.JLabel" name="assignOpsLabel">
 198.661 +              <Properties>
 198.662 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 198.663 +                  <ComponentRef name="assignOpsCombo"/>
 198.664 +                </Property>
 198.665 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.666 +                  <ResourceString bundle="org/netbeans/modules/python/editor/options/Bundle.properties" key="LBL_wrp_assignOps" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
 198.667 +                </Property>
 198.668 +              </Properties>
 198.669 +              <Constraints>
 198.670 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.671 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="4" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
 198.672 +                </Constraint>
 198.673 +              </Constraints>
 198.674 +            </Component>
 198.675 +            <Component class="javax.swing.JComboBox" name="assignOpsCombo">
 198.676 +              <Properties>
 198.677 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 198.678 +                  <StringArray count="4">
 198.679 +                    <StringItem index="0" value="Item 1"/>
 198.680 +                    <StringItem index="1" value="Item 2"/>
 198.681 +                    <StringItem index="2" value="Item 3"/>
 198.682 +                    <StringItem index="3" value="Item 4"/>
 198.683 +                  </StringArray>
 198.684 +                </Property>
 198.685 +              </Properties>
 198.686 +              <Constraints>
 198.687 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.688 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="4" insetsRight="8" anchor="18" weightX="0.0" weightY="0.0"/>
 198.689 +                </Constraint>
 198.690 +              </Constraints>
 198.691 +            </Component>
 198.692 +            <Container class="javax.swing.JPanel" name="spacerPanel1">
 198.693 +              <Properties>
 198.694 +                <Property name="opaque" type="boolean" value="false"/>
 198.695 +              </Properties>
 198.696 +              <Constraints>
 198.697 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 198.698 +                  <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="0" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="8" insetsBottom="0" insetsRight="8" anchor="10" weightX="0.0" weightY="1.0"/>
 198.699 +                </Constraint>
 198.700 +              </Constraints>
 198.701 +
 198.702 +              <Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
 198.703 +            </Container>
 198.704 +          </SubComponents>
 198.705 +        </Container>
 198.706 +      </SubComponents>
 198.707 +    </Container>
 198.708 +  </SubComponents>
 198.709 +</Form>
   199.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   199.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtWrapping.java	Sun Sep 13 11:47:42 2015 +0200
   199.3 @@ -0,0 +1,505 @@
   199.4 +/*
   199.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   199.6 + *
   199.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   199.8 + *
   199.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  199.10 + * Other names may be trademarks of their respective owners.
  199.11 + *
  199.12 + * The contents of this file are subject to the terms of either the GNU
  199.13 + * General Public License Version 2 only ("GPL") or the Common
  199.14 + * Development and Distribution License("CDDL") (collectively, the
  199.15 + * "License"). You may not use this file except in compliance with the
  199.16 + * License. You can obtain a copy of the License at
  199.17 + * http://www.netbeans.org/cddl-gplv2.html
  199.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  199.19 + * specific language governing permissions and limitations under the
  199.20 + * License.  When distributing the software, include this License Header
  199.21 + * Notice in each file and include the License file at
  199.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  199.23 + * particular file as subject to the "Classpath" exception as provided
  199.24 + * by Oracle in the GPL Version 2 section of the License file that
  199.25 + * accompanied this code. If applicable, add the following below the
  199.26 + * License Header, with the fields enclosed by brackets [] replaced by
  199.27 + * your own identifying information:
  199.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  199.29 + *
  199.30 + * Contributor(s):
  199.31 + *
  199.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  199.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  199.34 + * Microsystems, Inc. All Rights Reserved.
  199.35 + *
  199.36 + * If you wish your version of this file to be governed by only the CDDL
  199.37 + * or only the GPL Version 2, indicate your decision by adding
  199.38 + * "[Contributor] elects to include this software in this distribution
  199.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  199.40 + * single choice of license, a recipient has the option to distribute
  199.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  199.42 + * to extend the choice of license to its licensees as provided above.
  199.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  199.44 + * Version 2 license, then the option applies only if the new code is
  199.45 + * made subject to such option by the copyright holder.
  199.46 + */
  199.47 +
  199.48 +package org.netbeans.modules.python.source.ui;
  199.49 +
  199.50 +//import org.netbeans.modules.python.source.CodeStyle;
  199.51 +//import static org.netbeans.modules.python.source.ui.FmtOptions.*;
  199.52 +//import static org.netbeans.modules.python.source.ui.FmtOptions.CategorySupport.OPTION_ID;
  199.53 +//import org.netbeans.modules.python.source.ui.FmtOptions.CategorySupport;
  199.54 +//import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
  199.55 +
  199.56 +
  199.57 +/**
  199.58 + *
  199.59 + * @author  phrebejk
  199.60 + */
  199.61 +public class FmtWrapping extends javax.swing.JPanel {
  199.62 +    
  199.63 +    /** Creates new form FmtWrapping */
  199.64 +    public FmtWrapping() {
  199.65 +        initComponents();
  199.66 +        
  199.67 +        scrollPane.getViewport().setBackground(java.awt.SystemColor.controlLtHighlight);
  199.68 +        
  199.69 +/*
  199.70 +        extendsImplementsKeywordCombo.putClientProperty(OPTION_ID, wrapExtendsImplementsKeyword);
  199.71 +        extendsImplementsListCombo.putClientProperty(OPTION_ID, wrapExtendsImplementsList);
  199.72 +        methodParamsCombo.putClientProperty(OPTION_ID, wrapMethodParams);
  199.73 +        methodCallArgsCombo.putClientProperty(OPTION_ID, wrapMethodCallArgs);
  199.74 +        annotationArgsCombo.putClientProperty(OPTION_ID, wrapAnnotationArgs);
  199.75 +        chainedMethodCallsCombo.putClientProperty(OPTION_ID, wrapChainedMethodCalls);
  199.76 +        throwsKeywordCombo.putClientProperty(OPTION_ID, wrapThrowsKeyword);
  199.77 +        throwsListCombo.putClientProperty(OPTION_ID, wrapThrowsList);
  199.78 +        arrayInitCombo.putClientProperty(OPTION_ID, wrapArrayInit);
  199.79 +        forCombo.putClientProperty(OPTION_ID, wrapFor);
  199.80 +        forStatementCombo.putClientProperty(OPTION_ID, wrapForStatement );
  199.81 +        ifStatementCombo.putClientProperty(OPTION_ID, wrapIfStatement);
  199.82 +        whileStatementComboBox.putClientProperty(OPTION_ID, wrapWhileStatement);
  199.83 +        doWhileStatementCombo.putClientProperty(OPTION_ID, wrapDoWhileStatement);
  199.84 +        assertCombo.putClientProperty(OPTION_ID, wrapAssert);
  199.85 +        enumConstantsCombo.putClientProperty(OPTION_ID, wrapEnumConstants);
  199.86 +        annotationsCombo.putClientProperty(OPTION_ID, wrapAnnotations);
  199.87 +        binaryOpsCombo.putClientProperty(OPTION_ID, wrapBinaryOps);
  199.88 +        ternaryOpsCombo.putClientProperty(OPTION_ID, wrapTernaryOps);
  199.89 +        assignOpsCombo.putClientProperty(OPTION_ID, wrapAssignOps);
  199.90 +    }
  199.91 +    
  199.92 +    public static PreferencesCustomizer.Factory getController() {
  199.93 +        return new CategorySupport.Factory("wrapping", FmtWrapping.class, //NOI18N
  199.94 +                org.openide.util.NbBundle.getMessage(FmtWrapping.class, "SAMPLE_Wrapping"), //NOI18N
  199.95 +                new String[] { FmtOptions.rightMargin, "30" } //NOI18N
  199.96 +//                new String[] { FmtOptions.redundantDoWhileBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() },
  199.97 +//                new String[] { FmtOptions.redundantForBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() },
  199.98 +//                new String[] { FmtOptions.redundantIfBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() },
  199.99 +//                new String[] { FmtOptions.redundantWhileBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() }
 199.100 +        ); // NOI18N
 199.101 + */
 199.102 +    }
 199.103 +    
 199.104 +    /** This method is called from within the constructor to
 199.105 +     * initialize the form.
 199.106 +     * WARNING: Do NOT modify this code. The content of this method is
 199.107 +     * always regenerated by the Form Editor.
 199.108 +     */
 199.109 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
 199.110 +    private void initComponents() {
 199.111 +        java.awt.GridBagConstraints gridBagConstraints;
 199.112 +
 199.113 +        scrollPane = new javax.swing.JScrollPane();
 199.114 +        panel1 = new javax.swing.JPanel();
 199.115 +        extendsImplemetsKeywordLabel = new javax.swing.JLabel();
 199.116 +        extendsImplementsKeywordCombo = new javax.swing.JComboBox();
 199.117 +        extendsImplementsListLabel = new javax.swing.JLabel();
 199.118 +        extendsImplementsListCombo = new javax.swing.JComboBox();
 199.119 +        methodParamsLabel = new javax.swing.JLabel();
 199.120 +        methodParamsCombo = new javax.swing.JComboBox();
 199.121 +        methodCallArgsLabel = new javax.swing.JLabel();
 199.122 +        methodCallArgsCombo = new javax.swing.JComboBox();
 199.123 +        annotationArgsLabel = new javax.swing.JLabel();
 199.124 +        annotationArgsCombo = new javax.swing.JComboBox();
 199.125 +        chainedMethodCallsLabel = new javax.swing.JLabel();
 199.126 +        chainedMethodCallsCombo = new javax.swing.JComboBox();
 199.127 +        throwsKeywordLabel = new javax.swing.JLabel();
 199.128 +        throwsKeywordCombo = new javax.swing.JComboBox();
 199.129 +        throwsListLabel = new javax.swing.JLabel();
 199.130 +        throwsListCombo = new javax.swing.JComboBox();
 199.131 +        arrayInitLabel = new javax.swing.JLabel();
 199.132 +        arrayInitCombo = new javax.swing.JComboBox();
 199.133 +        forLabel = new javax.swing.JLabel();
 199.134 +        forCombo = new javax.swing.JComboBox();
 199.135 +        forStatementLabel = new javax.swing.JLabel();
 199.136 +        forStatementCombo = new javax.swing.JComboBox();
 199.137 +        ifStatementLabel = new javax.swing.JLabel();
 199.138 +        ifStatementCombo = new javax.swing.JComboBox();
 199.139 +        whileStatementLabel = new javax.swing.JLabel();
 199.140 +        whileStatementComboBox = new javax.swing.JComboBox();
 199.141 +        doWhileStatementLabel = new javax.swing.JLabel();
 199.142 +        doWhileStatementCombo = new javax.swing.JComboBox();
 199.143 +        assertLabel = new javax.swing.JLabel();
 199.144 +        assertCombo = new javax.swing.JComboBox();
 199.145 +        enumConstantsLabel = new javax.swing.JLabel();
 199.146 +        enumConstantsCombo = new javax.swing.JComboBox();
 199.147 +        annotationsLabel = new javax.swing.JLabel();
 199.148 +        annotationsCombo = new javax.swing.JComboBox();
 199.149 +        binaryOpsLabel = new javax.swing.JLabel();
 199.150 +        binaryOpsCombo = new javax.swing.JComboBox();
 199.151 +        ternaryOpsLabel = new javax.swing.JLabel();
 199.152 +        ternaryOpsCombo = new javax.swing.JComboBox();
 199.153 +        assignOpsLabel = new javax.swing.JLabel();
 199.154 +        assignOpsCombo = new javax.swing.JComboBox();
 199.155 +        spacerPanel1 = new javax.swing.JPanel();
 199.156 +
 199.157 +        setName(org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_Wrapping")); // NOI18N
 199.158 +        setOpaque(false);
 199.159 +        setLayout(new java.awt.BorderLayout());
 199.160 +
 199.161 +        scrollPane.setMinimumSize(new java.awt.Dimension(300, 200));
 199.162 +        scrollPane.setPreferredSize(new java.awt.Dimension(350, 600));
 199.163 +
 199.164 +        panel1.setOpaque(false);
 199.165 +        panel1.setLayout(new java.awt.GridBagLayout());
 199.166 +
 199.167 +        extendsImplemetsKeywordLabel.setLabelFor(extendsImplementsKeywordCombo);
 199.168 +        org.openide.awt.Mnemonics.setLocalizedText(extendsImplemetsKeywordLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_extendsImplementsKeyword")); // NOI18N
 199.169 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.170 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.171 +        gridBagConstraints.insets = new java.awt.Insets(8, 8, 4, 0);
 199.172 +        panel1.add(extendsImplemetsKeywordLabel, gridBagConstraints);
 199.173 +
 199.174 +        extendsImplementsKeywordCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.175 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.176 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.177 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.178 +        gridBagConstraints.weightx = 1.0;
 199.179 +        gridBagConstraints.insets = new java.awt.Insets(8, 6, 4, 8);
 199.180 +        panel1.add(extendsImplementsKeywordCombo, gridBagConstraints);
 199.181 +
 199.182 +        extendsImplementsListLabel.setLabelFor(extendsImplementsListCombo);
 199.183 +        org.openide.awt.Mnemonics.setLocalizedText(extendsImplementsListLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_extendsImplementsList")); // NOI18N
 199.184 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.185 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.186 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.187 +        panel1.add(extendsImplementsListLabel, gridBagConstraints);
 199.188 +
 199.189 +        extendsImplementsListCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.190 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.191 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.192 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.193 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.194 +        panel1.add(extendsImplementsListCombo, gridBagConstraints);
 199.195 +
 199.196 +        methodParamsLabel.setLabelFor(methodParamsCombo);
 199.197 +        org.openide.awt.Mnemonics.setLocalizedText(methodParamsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_methodParameters")); // NOI18N
 199.198 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.199 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.200 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.201 +        panel1.add(methodParamsLabel, gridBagConstraints);
 199.202 +
 199.203 +        methodParamsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.204 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.205 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.206 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.207 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.208 +        panel1.add(methodParamsCombo, gridBagConstraints);
 199.209 +
 199.210 +        methodCallArgsLabel.setLabelFor(methodCallArgsCombo);
 199.211 +        org.openide.awt.Mnemonics.setLocalizedText(methodCallArgsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_methodCallArgs")); // NOI18N
 199.212 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.213 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.214 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.215 +        panel1.add(methodCallArgsLabel, gridBagConstraints);
 199.216 +
 199.217 +        methodCallArgsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.218 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.219 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.220 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.221 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.222 +        panel1.add(methodCallArgsCombo, gridBagConstraints);
 199.223 +
 199.224 +        annotationArgsLabel.setLabelFor(annotationArgsCombo);
 199.225 +        org.openide.awt.Mnemonics.setLocalizedText(annotationArgsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_annotationArgs")); // NOI18N
 199.226 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.227 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.228 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.229 +        panel1.add(annotationArgsLabel, gridBagConstraints);
 199.230 +
 199.231 +        annotationArgsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.232 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.233 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.234 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.235 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.236 +        panel1.add(annotationArgsCombo, gridBagConstraints);
 199.237 +
 199.238 +        chainedMethodCallsLabel.setLabelFor(chainedMethodCallsCombo);
 199.239 +        org.openide.awt.Mnemonics.setLocalizedText(chainedMethodCallsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_chainedMethodCalls")); // NOI18N
 199.240 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.241 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.242 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.243 +        panel1.add(chainedMethodCallsLabel, gridBagConstraints);
 199.244 +
 199.245 +        chainedMethodCallsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.246 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.247 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.248 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.249 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.250 +        panel1.add(chainedMethodCallsCombo, gridBagConstraints);
 199.251 +
 199.252 +        throwsKeywordLabel.setLabelFor(throwsKeywordCombo);
 199.253 +        org.openide.awt.Mnemonics.setLocalizedText(throwsKeywordLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_throwsKeyword")); // NOI18N
 199.254 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.255 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.256 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.257 +        panel1.add(throwsKeywordLabel, gridBagConstraints);
 199.258 +
 199.259 +        throwsKeywordCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.260 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.261 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.262 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.263 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.264 +        panel1.add(throwsKeywordCombo, gridBagConstraints);
 199.265 +
 199.266 +        throwsListLabel.setLabelFor(throwsListCombo);
 199.267 +        org.openide.awt.Mnemonics.setLocalizedText(throwsListLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_throwsList")); // NOI18N
 199.268 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.269 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.270 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.271 +        panel1.add(throwsListLabel, gridBagConstraints);
 199.272 +
 199.273 +        throwsListCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.274 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.275 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.276 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.277 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.278 +        panel1.add(throwsListCombo, gridBagConstraints);
 199.279 +
 199.280 +        arrayInitLabel.setLabelFor(arrayInitCombo);
 199.281 +        org.openide.awt.Mnemonics.setLocalizedText(arrayInitLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_arrayInit")); // NOI18N
 199.282 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.283 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.284 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.285 +        panel1.add(arrayInitLabel, gridBagConstraints);
 199.286 +
 199.287 +        arrayInitCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.288 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.289 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.290 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.291 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.292 +        panel1.add(arrayInitCombo, gridBagConstraints);
 199.293 +
 199.294 +        forLabel.setLabelFor(forCombo);
 199.295 +        org.openide.awt.Mnemonics.setLocalizedText(forLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_for")); // NOI18N
 199.296 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.297 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.298 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.299 +        panel1.add(forLabel, gridBagConstraints);
 199.300 +
 199.301 +        forCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.302 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.303 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.304 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.305 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.306 +        panel1.add(forCombo, gridBagConstraints);
 199.307 +
 199.308 +        forStatementLabel.setLabelFor(forStatementCombo);
 199.309 +        org.openide.awt.Mnemonics.setLocalizedText(forStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_forStatement")); // NOI18N
 199.310 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.311 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.312 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.313 +        panel1.add(forStatementLabel, gridBagConstraints);
 199.314 +
 199.315 +        forStatementCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.316 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.317 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.318 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.319 +        gridBagConstraints.weightx = 1.0;
 199.320 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.321 +        panel1.add(forStatementCombo, gridBagConstraints);
 199.322 +
 199.323 +        ifStatementLabel.setLabelFor(ifStatementCombo);
 199.324 +        org.openide.awt.Mnemonics.setLocalizedText(ifStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_ifStatement")); // NOI18N
 199.325 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.326 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.327 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.328 +        panel1.add(ifStatementLabel, gridBagConstraints);
 199.329 +
 199.330 +        ifStatementCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.331 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.332 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.333 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.334 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.335 +        panel1.add(ifStatementCombo, gridBagConstraints);
 199.336 +
 199.337 +        whileStatementLabel.setLabelFor(whileStatementComboBox);
 199.338 +        org.openide.awt.Mnemonics.setLocalizedText(whileStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_whileStatement")); // NOI18N
 199.339 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.340 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.341 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.342 +        panel1.add(whileStatementLabel, gridBagConstraints);
 199.343 +
 199.344 +        whileStatementComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.345 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.346 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.347 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.348 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.349 +        panel1.add(whileStatementComboBox, gridBagConstraints);
 199.350 +
 199.351 +        doWhileStatementLabel.setLabelFor(doWhileStatementCombo);
 199.352 +        org.openide.awt.Mnemonics.setLocalizedText(doWhileStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_doWhileStatement")); // NOI18N
 199.353 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.354 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.355 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.356 +        panel1.add(doWhileStatementLabel, gridBagConstraints);
 199.357 +
 199.358 +        doWhileStatementCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.359 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.360 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.361 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.362 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.363 +        panel1.add(doWhileStatementCombo, gridBagConstraints);
 199.364 +
 199.365 +        assertLabel.setLabelFor(assertCombo);
 199.366 +        org.openide.awt.Mnemonics.setLocalizedText(assertLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_assert")); // NOI18N
 199.367 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.368 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.369 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.370 +        panel1.add(assertLabel, gridBagConstraints);
 199.371 +
 199.372 +        assertCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.373 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.374 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.375 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.376 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.377 +        panel1.add(assertCombo, gridBagConstraints);
 199.378 +
 199.379 +        enumConstantsLabel.setLabelFor(enumConstantsCombo);
 199.380 +        org.openide.awt.Mnemonics.setLocalizedText(enumConstantsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_enumConstants")); // NOI18N
 199.381 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.382 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.383 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.384 +        panel1.add(enumConstantsLabel, gridBagConstraints);
 199.385 +
 199.386 +        enumConstantsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.387 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.388 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.389 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.390 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.391 +        panel1.add(enumConstantsCombo, gridBagConstraints);
 199.392 +
 199.393 +        annotationsLabel.setLabelFor(annotationsCombo);
 199.394 +        org.openide.awt.Mnemonics.setLocalizedText(annotationsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_annotations")); // NOI18N
 199.395 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.396 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.397 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.398 +        panel1.add(annotationsLabel, gridBagConstraints);
 199.399 +
 199.400 +        annotationsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.401 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.402 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.403 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.404 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.405 +        panel1.add(annotationsCombo, gridBagConstraints);
 199.406 +
 199.407 +        binaryOpsLabel.setLabelFor(binaryOpsCombo);
 199.408 +        org.openide.awt.Mnemonics.setLocalizedText(binaryOpsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_binaryOps")); // NOI18N
 199.409 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.410 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.411 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.412 +        panel1.add(binaryOpsLabel, gridBagConstraints);
 199.413 +
 199.414 +        binaryOpsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.415 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.416 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.417 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.418 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.419 +        panel1.add(binaryOpsCombo, gridBagConstraints);
 199.420 +
 199.421 +        ternaryOpsLabel.setLabelFor(ternaryOpsCombo);
 199.422 +        org.openide.awt.Mnemonics.setLocalizedText(ternaryOpsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_ternaryOps")); // NOI18N
 199.423 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.424 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.425 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.426 +        panel1.add(ternaryOpsLabel, gridBagConstraints);
 199.427 +
 199.428 +        ternaryOpsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.429 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.430 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.431 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.432 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.433 +        panel1.add(ternaryOpsCombo, gridBagConstraints);
 199.434 +
 199.435 +        assignOpsLabel.setLabelFor(assignOpsCombo);
 199.436 +        org.openide.awt.Mnemonics.setLocalizedText(assignOpsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_assignOps")); // NOI18N
 199.437 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.438 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 199.439 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 199.440 +        panel1.add(assignOpsLabel, gridBagConstraints);
 199.441 +
 199.442 +        assignOpsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 199.443 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.444 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.445 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 199.446 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 199.447 +        panel1.add(assignOpsCombo, gridBagConstraints);
 199.448 +
 199.449 +        spacerPanel1.setOpaque(false);
 199.450 +        gridBagConstraints = new java.awt.GridBagConstraints();
 199.451 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 199.452 +        gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER;
 199.453 +        gridBagConstraints.weighty = 1.0;
 199.454 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 8);
 199.455 +        panel1.add(spacerPanel1, gridBagConstraints);
 199.456 +
 199.457 +        scrollPane.setViewportView(panel1);
 199.458 +
 199.459 +        add(scrollPane, java.awt.BorderLayout.CENTER);
 199.460 +    }// </editor-fold>//GEN-END:initComponents
 199.461 +    
 199.462 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 199.463 +    private javax.swing.JComboBox annotationArgsCombo;
 199.464 +    private javax.swing.JLabel annotationArgsLabel;
 199.465 +    private javax.swing.JComboBox annotationsCombo;
 199.466 +    private javax.swing.JLabel annotationsLabel;
 199.467 +    private javax.swing.JComboBox arrayInitCombo;
 199.468 +    private javax.swing.JLabel arrayInitLabel;
 199.469 +    private javax.swing.JComboBox assertCombo;
 199.470 +    private javax.swing.JLabel assertLabel;
 199.471 +    private javax.swing.JComboBox assignOpsCombo;
 199.472 +    private javax.swing.JLabel assignOpsLabel;
 199.473 +    private javax.swing.JComboBox binaryOpsCombo;
 199.474 +    private javax.swing.JLabel binaryOpsLabel;
 199.475 +    private javax.swing.JComboBox chainedMethodCallsCombo;
 199.476 +    private javax.swing.JLabel chainedMethodCallsLabel;
 199.477 +    private javax.swing.JComboBox doWhileStatementCombo;
 199.478 +    private javax.swing.JLabel doWhileStatementLabel;
 199.479 +    private javax.swing.JComboBox enumConstantsCombo;
 199.480 +    private javax.swing.JLabel enumConstantsLabel;
 199.481 +    private javax.swing.JComboBox extendsImplementsKeywordCombo;
 199.482 +    private javax.swing.JComboBox extendsImplementsListCombo;
 199.483 +    private javax.swing.JLabel extendsImplementsListLabel;
 199.484 +    private javax.swing.JLabel extendsImplemetsKeywordLabel;
 199.485 +    private javax.swing.JComboBox forCombo;
 199.486 +    private javax.swing.JLabel forLabel;
 199.487 +    private javax.swing.JComboBox forStatementCombo;
 199.488 +    private javax.swing.JLabel forStatementLabel;
 199.489 +    private javax.swing.JComboBox ifStatementCombo;
 199.490 +    private javax.swing.JLabel ifStatementLabel;
 199.491 +    private javax.swing.JComboBox methodCallArgsCombo;
 199.492 +    private javax.swing.JLabel methodCallArgsLabel;
 199.493 +    private javax.swing.JComboBox methodParamsCombo;
 199.494 +    private javax.swing.JLabel methodParamsLabel;
 199.495 +    private javax.swing.JPanel panel1;
 199.496 +    private javax.swing.JScrollPane scrollPane;
 199.497 +    private javax.swing.JPanel spacerPanel1;
 199.498 +    private javax.swing.JComboBox ternaryOpsCombo;
 199.499 +    private javax.swing.JLabel ternaryOpsLabel;
 199.500 +    private javax.swing.JComboBox throwsKeywordCombo;
 199.501 +    private javax.swing.JLabel throwsKeywordLabel;
 199.502 +    private javax.swing.JComboBox throwsListCombo;
 199.503 +    private javax.swing.JLabel throwsListLabel;
 199.504 +    private javax.swing.JComboBox whileStatementComboBox;
 199.505 +    private javax.swing.JLabel whileStatementLabel;
 199.506 +    // End of variables declaration//GEN-END:variables
 199.507 +    
 199.508 +}
   200.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   200.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/NumericKeyListener.java	Sun Sep 13 11:47:42 2015 +0200
   200.3 @@ -0,0 +1,74 @@
   200.4 +/*
   200.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   200.6 + *
   200.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   200.8 + *
   200.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  200.10 + * Other names may be trademarks of their respective owners.
  200.11 + *
  200.12 + * The contents of this file are subject to the terms of either the GNU
  200.13 + * General Public License Version 2 only ("GPL") or the Common
  200.14 + * Development and Distribution License("CDDL") (collectively, the
  200.15 + * "License"). You may not use this file except in compliance with the
  200.16 + * License. You can obtain a copy of the License at
  200.17 + * http://www.netbeans.org/cddl-gplv2.html
  200.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  200.19 + * specific language governing permissions and limitations under the
  200.20 + * License.  When distributing the software, include this License Header
  200.21 + * Notice in each file and include the License file at
  200.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  200.23 + * particular file as subject to the "Classpath" exception as provided
  200.24 + * by Oracle in the GPL Version 2 section of the License file that
  200.25 + * accompanied this code. If applicable, add the following below the
  200.26 + * License Header, with the fields enclosed by brackets [] replaced by
  200.27 + * your own identifying information:
  200.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  200.29 + *
  200.30 + * If you wish your version of this file to be governed by only the CDDL
  200.31 + * or only the GPL Version 2, indicate your decision by adding
  200.32 + * "[Contributor] elects to include this software in this distribution
  200.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  200.34 + * single choice of license, a recipient has the option to distribute
  200.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  200.36 + * to extend the choice of license to its licensees as provided above.
  200.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  200.38 + * Version 2 license, then the option applies only if the new code is
  200.39 + * made subject to such option by the copyright holder.
  200.40 + *
  200.41 + * Contributor(s):
  200.42 + *
  200.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  200.44 + */
  200.45 +package org.netbeans.modules.python.editor.options;
  200.46 +
  200.47 +import java.awt.Component;
  200.48 +import java.awt.event.KeyEvent;
  200.49 +import java.awt.event.KeyListener;
  200.50 +
  200.51 +/**
  200.52 + *
  200.53 + * @author tester
  200.54 + */
  200.55 +public class NumericKeyListener implements KeyListener {
  200.56 +    public NumericKeyListener() {
  200.57 +    }
  200.58 +
  200.59 +    @Override
  200.60 +    public void keyPressed(KeyEvent evt) {
  200.61 +    }
  200.62 +
  200.63 +    @Override
  200.64 +    public void keyReleased(KeyEvent evt) {
  200.65 +    }
  200.66 +
  200.67 +    @Override
  200.68 +    public void keyTyped(KeyEvent evt) {
  200.69 +        if (!Character.isDigit(evt.getKeyChar()) && !Character.isISOControl(evt.getKeyChar())) {
  200.70 +            evt.consume();
  200.71 +            Component c = evt.getComponent();
  200.72 +            if (c != null) {
  200.73 +                c.getToolkit().beep();
  200.74 +            }
  200.75 +        }
  200.76 +    }
  200.77 +}