Merge w/ trunk
authorRalph Benjamin Ruijs <ralphbenjamin@netbeans.org>
Mon, 21 Sep 2015 13:01:16 +0200
changeset 183173f9671d8810f
parent 18312 e917be5013e1
parent 18316 0474d60634b8
child 18318 d0199c9c06d5
Merge w/ trunk
o.jython/manifest.mf
python.editor/nbproject/project.xml
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/BuiltinException.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.hints/src/org/netbeans/modules/python/hints/UnresolvedDetector.java
python.source/src/org/netbeans/modules/python/source/PythonProjectSourceLevelQuery.java
python.source/src/org/netbeans/modules/python/source/PythonUtils.java
python.source/src/org/netbeans/modules/python/source/lexer/BuiltinException.java
python.source/src/org/netbeans/modules/python/source/lexer/PythonLexer.java
python.source/src/org/netbeans/modules/python/source/lexer/PythonLexerUtils.java
python.source/src/org/netbeans/modules/python/source/lexer/PythonTokenId.java
python.source/src/org/netbeans/modules/python/source/scopes/SymInfo.java
python.source/src/org/netbeans/modules/python/source/scopes/SymbolTable.java
     1.1 --- a/o.jython/manifest.mf	Fri Sep 18 16:20:24 2015 -0500
     1.2 +++ b/o.jython/manifest.mf	Mon Sep 21 13:01:16 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.7
     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	Fri Sep 18 16:20:24 2015 -0500
     2.2 +++ b/o.jython/nbproject/project.xml	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
     3.2 +++ b/python.editor/nbproject/project.properties	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
     4.2 +++ b/python.editor/nbproject/project.xml	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
     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	Fri Sep 18 16:20:24 2015 -0500
     6.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/GoToSuperTypeAction.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
     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	Fri Sep 18 16:20:24 2015 -0500
     8.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonCodeCompleter.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
     9.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonDeclarationFinder.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    17.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonInstantRename.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    18.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonKeystrokeHandler.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    19.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonLanguage.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    20.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonOccurrencesMarker.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    23.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonSemanticHighlighter.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    26.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonTypeAnalyzer.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    27.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.3 @@ -1,536 +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 -    // According to https://hg.python.org/cpython/file/3.5/Lib/keyword.py
  27.196 -    // and https://hg.python.org/cpython/file/2.7/Lib/keyword.py
  27.197 -    static final String[] PYTHON_KEYWORDS = new String[]{
  27.198 -        "False", // NOI18N
  27.199 -        "None", // NOI18N
  27.200 -        "True", // NOI18N
  27.201 -        "and", // NOI18N
  27.202 -        "as", // NOI18N
  27.203 -        "assert", // NOI18N
  27.204 -        "break", // NOI18N
  27.205 -        "class", // NOI18N
  27.206 -        "continue", // NOI18N
  27.207 -        "def", // NOI18N
  27.208 -        "del", // NOI18N
  27.209 -        "elif", // NOI18N
  27.210 -        "else", // NOI18N
  27.211 -        "except", // NOI18N
  27.212 -        "finally", // NOI18N
  27.213 -        "for", // NOI18N
  27.214 -        "from", // NOI18N
  27.215 -        "global", // NOI18N
  27.216 -        "if", // NOI18N
  27.217 -        "import", // NOI18N
  27.218 -        "in", // NOI18N
  27.219 -        "is", // NOI18N
  27.220 -        "lambda", // NOI18N
  27.221 -        "nonlocal", // NOI18N
  27.222 -        "not", // NOI18N
  27.223 -        "or", // NOI18N
  27.224 -        "pass", // NOI18N
  27.225 -        "raise", // NOI18N
  27.226 -        "return", // NOI18N
  27.227 -        "try", // NOI18N
  27.228 -        "while", // NOI18N
  27.229 -        "with", // NOI18N
  27.230 -        "yield", // NOI18N
  27.231 -        "async", // NOI18N, Python 3.5 only
  27.232 -        "await", // NOI18N, Python 3.5 only
  27.233 -        "exec", // NOI18N, Python 2 only
  27.234 -        "print", // NOI18N, Pytohn 2 only, function in python 3
  27.235 -    };
  27.236 -
  27.237 -    public static boolean isPythonKeyword(String name) {
  27.238 -        for (String s : PYTHON_KEYWORDS) {
  27.239 -            if (s.equals(name)) {
  27.240 -                return true;
  27.241 -            }
  27.242 -        }
  27.243 -
  27.244 -        return false;
  27.245 -    }
  27.246 -
  27.247 -    /**
  27.248 -     * Return true iff the name is a class name
  27.249 -     * @param name The name
  27.250 -     * @param emptyDefault Whether empty or _ names should be considered a class name or not
  27.251 -     * @return True iff the name looks like a class name
  27.252 -     */
  27.253 -    public static boolean isClassName(String name, boolean emptyDefault) {
  27.254 -        if (name == null || name.length() == 0) {
  27.255 -            return emptyDefault;
  27.256 -        }
  27.257 -        if (name.startsWith("_") && name.length() > 1) {
  27.258 -            return Character.isUpperCase(name.charAt(1));
  27.259 -        }
  27.260 -
  27.261 -        return Character.isUpperCase(name.charAt(0));
  27.262 -    }
  27.263 -
  27.264 -    /**
  27.265 -     * Return true iff the name is a method name
  27.266 -     * @param name The name
  27.267 -     * @param emptyDefault Whether empty or _ names should be considered a class name or not
  27.268 -     * @return True iff the name looks like a method name
  27.269 -     */
  27.270 -    public static boolean isMethodName(String name, boolean emptyDefault) {
  27.271 -        if (name == null || name.length() == 0) {
  27.272 -            return emptyDefault;
  27.273 -        }
  27.274 -        if (name.startsWith("__") && name.length() > 2) {
  27.275 -            return Character.isLowerCase(name.charAt(2));
  27.276 -        }
  27.277 -        if (name.startsWith("_") && name.length() > 1) {
  27.278 -            return Character.isLowerCase(name.charAt(1));
  27.279 -        }
  27.280 -
  27.281 -        return Character.isLowerCase(name.charAt(0));
  27.282 -    }
  27.283 -
  27.284 -    public static String getCodeTemplate(CodeTemplateManager ctm, String abbrev, String textPrefix, String wrongTextPrefix) {
  27.285 -        String templateText = null;
  27.286 -        for (CodeTemplate t : ctm.getCodeTemplates()) {
  27.287 -            if (abbrev.equals(t.getAbbreviation())) {
  27.288 -                templateText = t.getParametrizedText();
  27.289 -                break;
  27.290 -            }
  27.291 -        }
  27.292 -        if (templateText == null) {
  27.293 -            for (CodeTemplate t : ctm.getCodeTemplates()) {
  27.294 -                String text = t.getParametrizedText();
  27.295 -                if (text.startsWith(textPrefix) && (wrongTextPrefix == null || !text.startsWith(wrongTextPrefix))) {
  27.296 -                    templateText = text;
  27.297 -                    break;
  27.298 -                }
  27.299 -            }
  27.300 -        }
  27.301 -
  27.302 -        return templateText;
  27.303 -    }
  27.304 -
  27.305 -    public static boolean isValidPythonClassName(String name) {
  27.306 -        if (isPythonKeyword(name)) {
  27.307 -            return false;
  27.308 -        }
  27.309 -
  27.310 -        if (name.trim().length() == 0) {
  27.311 -            return false;
  27.312 -        }
  27.313 -
  27.314 -        if (!Character.isUpperCase(name.charAt(0))) {
  27.315 -            return false;
  27.316 -        }
  27.317 -
  27.318 -        for (int i = 1; i < name.length(); i++) {
  27.319 -            char c = name.charAt(i);
  27.320 -            if (!Character.isJavaIdentifierPart(c)) {
  27.321 -                return false;
  27.322 -            }
  27.323 -
  27.324 -        }
  27.325 -
  27.326 -        return true;
  27.327 -    }
  27.328 -
  27.329 -    /** Is this name a valid operator name? */
  27.330 -    public static boolean isOperator(String name) {
  27.331 -        // TODO - update to Python
  27.332 -        if (name.length() == 0) {
  27.333 -            return false;
  27.334 -        }
  27.335 -
  27.336 -        switch (name.charAt(0)) {
  27.337 -        case '+':
  27.338 -            return name.equals("+") || name.equals("+@");
  27.339 -        case '-':
  27.340 -            return name.equals("-") || name.equals("-@");
  27.341 -        case '*':
  27.342 -            return name.equals("*") || name.equals("**");
  27.343 -        case '<':
  27.344 -            return name.equals("<") || name.equals("<<") || name.equals("<=") || name.equals("<=>");
  27.345 -        case '>':
  27.346 -            return name.equals(">") || name.equals(">>") || name.equals(">=");
  27.347 -        case '=':
  27.348 -            return name.equals("=") || name.equals("==") || name.equals("===") || name.equals("=~");
  27.349 -        case '!':
  27.350 -            return name.equals("!=") || name.equals("!~");
  27.351 -        case '&':
  27.352 -            return name.equals("&") || name.equals("&&");
  27.353 -        case '|':
  27.354 -            return name.equals("|") || name.equals("||");
  27.355 -        case '[':
  27.356 -            return name.equals("[]") || name.equals("[]=");
  27.357 -        case '%':
  27.358 -            return name.equals("%");
  27.359 -        case '/':
  27.360 -            return name.equals("/");
  27.361 -        case '~':
  27.362 -            return name.equals("~");
  27.363 -        case '^':
  27.364 -            return name.equals("^");
  27.365 -        case '`':
  27.366 -            return name.equals("`");
  27.367 -        default:
  27.368 -            return false;
  27.369 -        }
  27.370 -    }
  27.371 -
  27.372 -    public static boolean isValidPythonMethodName(String name) {
  27.373 -        if (isPythonKeyword(name)) {
  27.374 -            return false;
  27.375 -        }
  27.376 -
  27.377 -        if (name.trim().length() == 0) {
  27.378 -            return false;
  27.379 -        }
  27.380 -
  27.381 -        // TODO - allow operators
  27.382 -        if (isOperator(name)) {
  27.383 -            return true;
  27.384 -        }
  27.385 -
  27.386 -        if (Character.isUpperCase(name.charAt(0)) || Character.isWhitespace(name.charAt(0))) {
  27.387 -            return false;
  27.388 -        }
  27.389 -
  27.390 -        for (int i = 0; i < name.length(); i++) {
  27.391 -            char c = name.charAt(i);
  27.392 -            if (!(Character.isLetterOrDigit(c) || c == '_')) {
  27.393 -                return false;
  27.394 -            }
  27.395 -
  27.396 -        }
  27.397 -
  27.398 -        return true;
  27.399 -    }
  27.400 -
  27.401 -    public static boolean isValidPythonIdentifier(String name) {
  27.402 -        if (isPythonKeyword(name)) {
  27.403 -            return false;
  27.404 -        }
  27.405 -
  27.406 -        if (name.trim().length() == 0) {
  27.407 -            return false;
  27.408 -        }
  27.409 -
  27.410 -        for (int i = 0; i < name.length(); i++) {
  27.411 -            // Identifier char isn't really accurate - I can have a function named "[]" etc.
  27.412 -            // so just look for -obvious- mistakes
  27.413 -            if (Character.isWhitespace(name.charAt(i))) {
  27.414 -                return false;
  27.415 -            }
  27.416 -
  27.417 -        // TODO - make this more accurate, like the method validifier
  27.418 -        }
  27.419 -
  27.420 -        return true;
  27.421 -    }
  27.422 -
  27.423 -    /**
  27.424 -     * Ruby identifiers should consist of [a-zA-Z0-9_]
  27.425 -     * http://www.headius.com/rubyspec/index.php/Variables
  27.426 -     * <p>
  27.427 -     * This method also accepts the field/global chars
  27.428 -     * since it's unlikely
  27.429 -     */
  27.430 -    public static boolean isSafeIdentifierName(String name, int fromIndex) {
  27.431 -        int i = fromIndex;
  27.432 -        for (; i < name.length(); i++) {
  27.433 -            char c = name.charAt(i);
  27.434 -            if (!(c == '$' || c == '@' || c == ':')) {
  27.435 -                break;
  27.436 -            }
  27.437 -        }
  27.438 -        for (; i < name.length(); i++) {
  27.439 -            char c = name.charAt(i);
  27.440 -            if (!((c >= 'a' && c <= 'z') || (c == '_') ||
  27.441 -                    (c >= 'A' && c <= 'Z') ||
  27.442 -                    (c >= '0' && c <= '9') ||
  27.443 -                    (c == '?') || (c == '=') || (c == '!'))) { // Method suffixes; only allowed on the last line
  27.444 -
  27.445 -                if (isOperator(name)) {
  27.446 -                    return true;
  27.447 -                }
  27.448 -
  27.449 -                return false;
  27.450 -            }
  27.451 -        }
  27.452 -
  27.453 -        return true;
  27.454 -    }
  27.455 -
  27.456 -    /**
  27.457 -     * Return null if the given identifier name is valid, otherwise a localized
  27.458 -     * error message explaining the problem.
  27.459 -     */
  27.460 -    public static String getIdentifierWarning(String name, int fromIndex) {
  27.461 -        if (isSafeIdentifierName(name, fromIndex)) {
  27.462 -            return null;
  27.463 -        } else {
  27.464 -            return NbBundle.getMessage(PythonUtils.class, "UnsafeIdentifierName");
  27.465 -        }
  27.466 -    }
  27.467 -
  27.468 -    /** @todo Move into GsfUtilities after 6.5 */
  27.469 -    public static int getOffsetByLineCol(String source, int line, int col) {
  27.470 -        int offset = 0;
  27.471 -        for (int i = 0; i < line; i++) {
  27.472 -            offset = source.indexOf('\n', offset);
  27.473 -            if (offset == -1) {
  27.474 -                offset = source.length();
  27.475 -                break;
  27.476 -            }
  27.477 -            offset++;
  27.478 -        }
  27.479 -        if (col > 0) { // -1: invalid
  27.480 -            offset += col;
  27.481 -        }
  27.482 -
  27.483 -        return offset;
  27.484 -    }
  27.485 -    public static Comparator NAME_NODE_COMPARATOR = new Comparator<Name>() {
  27.486 -        @Override
  27.487 -        public int compare(Name n1, Name n2) {
  27.488 -            return n1.getInternalId().compareTo(n2.getInternalId());
  27.489 -        }
  27.490 -    };
  27.491 -    public static Comparator ATTRIBUTE_NAME_NODE_COMPARATOR = new Comparator<Object>() {
  27.492 -        @SuppressWarnings("unchecked")
  27.493 -        @Override
  27.494 -        public int compare(Object n1, Object n2) {
  27.495 -            String s1 = "";
  27.496 -            String s2 = "";
  27.497 -
  27.498 -            if (n1 instanceof Name) {
  27.499 -                s1 = ((Name)n1).getInternalId();
  27.500 -            } else if (n1 instanceof Attribute) {
  27.501 -                Attribute a = (Attribute)n1;
  27.502 -                String v = PythonAstUtils.getName(a.getInternalValue());
  27.503 -                if (v != null) {
  27.504 -                    s1 = a.getInternalAttr() + "." + v;
  27.505 -                } else {
  27.506 -                    s1 = a.getInternalAttr();
  27.507 -                }
  27.508 -            }
  27.509 -
  27.510 -            if (n2 instanceof Name) {
  27.511 -                s2 = ((Name)n2).getInternalId();
  27.512 -            } else if (n2 instanceof Attribute) {
  27.513 -                Attribute a = (Attribute)n2;
  27.514 -                String v = PythonAstUtils.getName(a.getInternalValue());
  27.515 -                if (v != null) {
  27.516 -                    s2 = a.getInternalAttr() + "." + v;
  27.517 -                } else {
  27.518 -                    s2 = a.getInternalAttr();
  27.519 -                }
  27.520 -            }
  27.521 -
  27.522 -            return s1.compareTo(s2);
  27.523 -        }
  27.524 -    };
  27.525 -    public static Comparator NODE_POS_COMPARATOR = new Comparator<PythonTree>() {
  27.526 -        @Override
  27.527 -        public int compare(PythonTree p1, PythonTree p2) {
  27.528 -            int ret = p1.getCharStartIndex() - p2.getCharStartIndex();
  27.529 -            if (ret != 0) {
  27.530 -                return ret;
  27.531 -            }
  27.532 -            ret = p2.getCharStopIndex() - p1.getCharStopIndex();
  27.533 -            if (ret != 0) {
  27.534 -                return ret;
  27.535 -            }
  27.536 -            return p2.getAntlrType() - p1.getAntlrType();
  27.537 -        }
  27.538 -    };
  27.539 -}
    28.1 --- a/python.editor/src/org/netbeans/modules/python/editor/QuerySupportFactory.java	Fri Sep 18 16:20:24 2015 -0500
    28.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/QuerySupportFactory.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    30.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/codecoverage/PythonCoverageProvider.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    31.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/codegen/ClassCodeGenerator.java	Mon Sep 21 13:01:16 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	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    33.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/codegen/ConstructorGenerator.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    34.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/codegen/MethodCodeGenerator.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    62.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.3 @@ -1,233 +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 -                // Ignore keywords and builtin
  62.108 -                if (PythonLexerUtils.isKeywordOrBuiltin(name)) {
  62.109 -                    continue;
  62.110 -                }
  62.111 -
  62.112 -                List<HintFix> fixList = new ArrayList<>(3);
  62.113 -                // Is is a reference to a module?
  62.114 -                boolean tryModule = false;
  62.115 -                if (node.getParent() instanceof Call) {
  62.116 -                    Call call = (Call)node.getParent();
  62.117 -                    PythonTree t = call.getInternalFunc();
  62.118 -                    if (t instanceof Attribute) {
  62.119 -                        tryModule = true;
  62.120 -                    }
  62.121 -                }
  62.122 -                String message = NbBundle.getMessage(NameRule.class, "UnresolvedVariable", name);
  62.123 -                if (name.equals("true")) { // NOI18N
  62.124 -                    // Help for new language converts...
  62.125 -                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "True"); // NOI18N
  62.126 -                } else if (name.equals("false")) {
  62.127 -                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "False"); // NOI18N
  62.128 -                } else if (name.equals("nil") || name.equals("null")) {
  62.129 -                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "None"); // NOI18N
  62.130 -                } else if (name.equals("this")) {
  62.131 -                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "self"); // NOI18N
  62.132 -                } else if (tryModule) {
  62.133 -                    Set<IndexedElement> moduleElements = index.getModules(name, QuerySupport.Kind.EXACT);
  62.134 -                    if (moduleElements.size() > 0) {
  62.135 -                        fixList.add(new ImportFix(context, node, name));
  62.136 -                    }
  62.137 -                } else {
  62.138 -                    Set<String> modules = index.getImportsFor(name, true);
  62.139 -                    if (modules.size() > 0) {
  62.140 -                        for (String module : modules) {
  62.141 -                            fixList.add(new ImportFix(context, node, module));
  62.142 -                        }
  62.143 -                    }
  62.144 -                }
  62.145 -
  62.146 -                OffsetRange range = PythonAstUtils.getNameRange(info, node);
  62.147 -                range = PythonLexerUtils.getLexerOffsets(info, range);
  62.148 -                if (range != OffsetRange.NONE) {
  62.149 -                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
  62.150 -                    result.add(desc);
  62.151 -                }
  62.152 -            }
  62.153 -        }
  62.154 -    }
  62.155 -
  62.156 -    @Override
  62.157 -    public String getId() {
  62.158 -        return "Unresolved"; // NOI18N
  62.159 -    }
  62.160 -
  62.161 -    @Override
  62.162 -    public String getDisplayName() {
  62.163 -        return NbBundle.getMessage(NameRule.class, "Unresolved");
  62.164 -    }
  62.165 -
  62.166 -    @Override
  62.167 -    public String getDescription() {
  62.168 -        return NbBundle.getMessage(NameRule.class, "UnresolvedDesc");
  62.169 -    }
  62.170 -
  62.171 -    @Override
  62.172 -    public boolean getDefaultEnabled() {
  62.173 -        return false;
  62.174 -    }
  62.175 -
  62.176 -    @Override
  62.177 -    public boolean showInTasklist() {
  62.178 -        return true;
  62.179 -    }
  62.180 -
  62.181 -    @Override
  62.182 -    public HintSeverity getDefaultSeverity() {
  62.183 -        return HintSeverity.ERROR;
  62.184 -    }
  62.185 -
  62.186 -    @Override
  62.187 -    public JComponent getCustomizer(Preferences node) {
  62.188 -        return null;
  62.189 -    }
  62.190 -
  62.191 -    private static class ImportFix implements HintFix {
  62.192 -        private final PythonRuleContext context;
  62.193 -        private final PythonTree node;
  62.194 -        private final String module;
  62.195 -
  62.196 -        private ImportFix(PythonRuleContext context, PythonTree node, String module) {
  62.197 -            this.context = context;
  62.198 -            this.node = node;
  62.199 -            this.module = module;
  62.200 -        }
  62.201 -
  62.202 -        @Override
  62.203 -        public String getDescription() {
  62.204 -            return NbBundle.getMessage(CreateDocString.class, "FixImport", module);
  62.205 -        }
  62.206 -
  62.207 -        @Override
  62.208 -        public void implement() throws Exception {
  62.209 -            String mod = this.module;
  62.210 -            String symbol = null;
  62.211 -            int colon = mod.indexOf(':');
  62.212 -            if (colon != -1) {
  62.213 -                int end = mod.indexOf('(', colon + 1);
  62.214 -                if (end == -1) {
  62.215 -                    end = mod.indexOf(';', colon + 1);
  62.216 -                    if (end == -1) {
  62.217 -                        end = mod.length();
  62.218 -                    }
  62.219 -                }
  62.220 -                symbol = mod.substring(colon + 1, end).trim();
  62.221 -                mod = mod.substring(0, colon).trim();
  62.222 -            }
  62.223 -            new ImportManager((PythonParserResult) context.parserResult).ensureImported(mod, symbol, false, false, true);
  62.224 -        }
  62.225 -
  62.226 -        @Override
  62.227 -        public boolean isSafe() {
  62.228 -            return true;
  62.229 -        }
  62.230 -
  62.231 -        @Override
  62.232 -        public boolean isInteractive() {
  62.233 -            return false;
  62.234 -        }
  62.235 -    }
  62.236 -}
    63.1 --- a/python.editor/src/org/netbeans/modules/python/editor/hints/UnusedDetector.java	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    67.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/imports/FastImportAction.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    68.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/imports/FixImportsAction.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    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	Fri Sep 18 16:20:24 2015 -0500
    71.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/imports/ImportModulePanel.java	Mon Sep 21 13:01:16 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	Fri Sep 18 16:20:24 2015 -0500
    72.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/layer.xml	Mon Sep 21 13:01:16 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/BuiltinException.java	Fri Sep 18 16:20:24 2015 -0500
    73.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.3 @@ -1,127 +0,0 @@
    73.4 -/*
    73.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    73.6 - *
    73.7 - * Copyright 2015 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 - * If you wish your version of this file to be governed by only the CDDL
   73.31 - * or only the GPL Version 2, indicate your decision by adding
   73.32 - * "[Contributor] elects to include this software in this distribution
   73.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   73.34 - * single choice of license, a recipient has the option to distribute
   73.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   73.36 - * to extend the choice of license to its licensees as provided above.
   73.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   73.38 - * Version 2 license, then the option applies only if the new code is
   73.39 - * made subject to such option by the copyright holder.
   73.40 - *
   73.41 - * Contributor(s):
   73.42 - *
   73.43 - * Portions Copyrighted 2015 Sun Microsystems, Inc.
   73.44 - */
   73.45 -package org.netbeans.modules.python.editor.lexer;
   73.46 -
   73.47 -import java.util.Arrays;
   73.48 -import java.util.HashSet;
   73.49 -import java.util.Set;
   73.50 -
   73.51 -/**
   73.52 - *
   73.53 - * @author jenselme
   73.54 - */
   73.55 -public class BuiltinException {
   73.56 -    private final static String[] BUILTIN_EXCEPTIONS_ARRAY = {
   73.57 -        "ArithmeticError",
   73.58 -        "AssertionError",
   73.59 -        "AttributeError",
   73.60 -        "BaseException",
   73.61 -        "BlockingIOError",
   73.62 -        "BrokenPipeError",
   73.63 -        "BufferError",
   73.64 -        "BytesWarning",
   73.65 -        "BytesWarningBaseException",
   73.66 -        "ChildProcessError",
   73.67 -        "ConnectionAbortedError",
   73.68 -        "ConnectionError",
   73.69 -        "ConnectionRefusedError",
   73.70 -        "ConnectionResetError",
   73.71 -        "DeprecationWarning",
   73.72 -        "EnvironmentError",
   73.73 -        "EOFError",
   73.74 -        "Exception",
   73.75 -        "FileExistsError",
   73.76 -        "FileNotFoundError",
   73.77 -        "FloatingPointError",
   73.78 -        "FutureWarning",
   73.79 -        "GeneratorExit",
   73.80 -        "ImportError",
   73.81 -        "ImportWarning",
   73.82 -        "IndentationError",
   73.83 -        "IndexError",
   73.84 -        "InterruptedError",
   73.85 -        "IOError",
   73.86 -        "IsADirectoryError",
   73.87 -        "KeyboardInterrupt",
   73.88 -        "KeyError",
   73.89 -        "LookupError",
   73.90 -        "MemoryError",
   73.91 -        "NameError",
   73.92 -        "NotADirectoryError",
   73.93 -        "NotImplementedError",
   73.94 -        "OSError",
   73.95 -        "OverflowError",
   73.96 -        "PendingDeprecationWarning",
   73.97 -        "PermissionError",
   73.98 -        "ProcessLookupError",
   73.99 -        "ReferenceError",
  73.100 -        "ResourceWarning",
  73.101 -        "RuntimeError",
  73.102 -        "RuntimeWarning",
  73.103 -        "StandardError",
  73.104 -        "StopIteration",
  73.105 -        "SyntaxError",
  73.106 -        "SyntaxWarning",
  73.107 -        "SystemError",
  73.108 -        "SystemExit",
  73.109 -        "TabError",
  73.110 -        "TimeoutError",
  73.111 -        "TypeError",
  73.112 -        "UnboundLocalError",
  73.113 -        "UnicodeDecodeError",
  73.114 -        "UnicodeEncodeError",
  73.115 -        "UnicodeError",
  73.116 -        "UnicodeTranslateError",
  73.117 -        "UnicodeWarning",
  73.118 -        "UserWarning",
  73.119 -        "ValueError",
  73.120 -        "VMSError",
  73.121 -        "Warning",
  73.122 -        "WindowsError",
  73.123 -        "ZeroDivisionError"
  73.124 -    };
  73.125 -    private final static Set<String> BUILTIN_EXCEPTIONS = new HashSet<String>(Arrays.asList(BUILTIN_EXCEPTIONS_ARRAY));
  73.126 -
  73.127 -    public static boolean isBuiltInException(CharSequence name) {
  73.128 -        return BUILTIN_EXCEPTIONS.contains(name.toString());
  73.129 -    }
  73.130 -}
    74.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/Call.java	Fri Sep 18 16:20:24 2015 -0500
    74.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.3 @@ -1,322 +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 javax.swing.text.BadLocationException;
   74.50 -import javax.swing.text.Document;
   74.51 -import org.netbeans.api.annotations.common.NonNull;
   74.52 -
   74.53 -import org.netbeans.api.lexer.Token;
   74.54 -import org.netbeans.api.lexer.TokenHierarchy;
   74.55 -import org.netbeans.api.lexer.TokenId;
   74.56 -import org.netbeans.api.lexer.TokenSequence;
   74.57 -import org.netbeans.editor.BaseDocument;
   74.58 -import org.netbeans.editor.Utilities;
   74.59 -import org.openide.util.Exceptions;
   74.60 -
   74.61 -/**
   74.62 - * Class which represents a Call in the source
   74.63 - */
   74.64 -public class Call {
   74.65 -    public static final Call LOCAL = new Call(null, null, false, false);
   74.66 -    public static final Call NONE = new Call(null, null, false, false);
   74.67 -    public static final Call UNKNOWN = new Call(null, null, false, false);
   74.68 -    private final String type;
   74.69 -    private final String lhs;
   74.70 -    private final boolean isStatic;
   74.71 -    private final boolean methodExpected;
   74.72 -
   74.73 -    public Call(String type, String lhs, boolean isStatic, boolean methodExpected) {
   74.74 -        super();
   74.75 -        this.type = type;
   74.76 -        this.lhs = lhs;
   74.77 -        this.methodExpected = methodExpected;
   74.78 -        if (lhs == null) {
   74.79 -            lhs = type;
   74.80 -        }
   74.81 -        this.isStatic = isStatic;
   74.82 -    }
   74.83 -
   74.84 -    public String getType() {
   74.85 -        return type;
   74.86 -    }
   74.87 -
   74.88 -    public String getLhs() {
   74.89 -        return lhs;
   74.90 -    }
   74.91 -
   74.92 -    public boolean isStatic() {
   74.93 -        return isStatic;
   74.94 -    }
   74.95 -
   74.96 -    public boolean isSimpleIdentifier() {
   74.97 -        if (lhs == null) {
   74.98 -            return false;
   74.99 -        }
  74.100 -        // TODO - replace with the new PythonUtil validations
  74.101 -        for (int i = 0, n = lhs.length(); i < n; i++) {
  74.102 -            char c = lhs.charAt(i);
  74.103 -            if (Character.isJavaIdentifierPart(c)) {
  74.104 -                continue;
  74.105 -            }
  74.106 -            return false;
  74.107 -        }
  74.108 -        return true;
  74.109 -    }
  74.110 -
  74.111 -    @Override
  74.112 -    public String toString() {
  74.113 -        if (this == LOCAL) {
  74.114 -            return "LOCAL";
  74.115 -        } else if (this == NONE) {
  74.116 -            return "NONE";
  74.117 -        } else if (this == UNKNOWN) {
  74.118 -            return "UNKNOWN";
  74.119 -        } else {
  74.120 -            return "Call(" + type + "," + lhs + "," + isStatic + ")";
  74.121 -        }
  74.122 -    }
  74.123 -
  74.124 -    /** foo.| or foo.b|  -> we're expecting a method call. For Foo:: we don't know. */
  74.125 -    public boolean isMethodExpected() {
  74.126 -        return this.methodExpected;
  74.127 -    }
  74.128 -
  74.129 -    /**
  74.130 -     * Determine whether the given offset corresponds to a method call on another
  74.131 -     * object. This would happen in these cases:
  74.132 -     *    Foo::|, Foo::Bar::|, Foo.|, Foo.x|, foo.|, foo.x|
  74.133 -     * and not here:
  74.134 -     *   |, Foo|, foo|
  74.135 -     * The method returns the left hand side token, if any, such as "Foo", Foo::Bar",
  74.136 -     * and "foo". If not, it will return null.
  74.137 -     * Note that "self" and "super" are possible return values for the lhs, which mean
  74.138 -     * that you don't have a call on another object. Clients of this method should
  74.139 -     * handle that return value properly (I could return null here, but clients probably
  74.140 -     * want to distinguish self and super in this case so it's useful to return the info.)
  74.141 -     *
  74.142 -     * This method will also try to be smart such that if you have a block or array
  74.143 -     * call, it will return the relevant classnames (e.g. for [1,2].x| it returns "Array").
  74.144 -     */
  74.145 -    @SuppressWarnings("unchecked")
  74.146 -    @NonNull
  74.147 -    public static Call getCallType(BaseDocument doc, TokenHierarchy<Document> th, int offset) {
  74.148 -        TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(th, offset);
  74.149 -
  74.150 -        if (ts == null) {
  74.151 -            return Call.NONE;
  74.152 -        }
  74.153 -
  74.154 -        ts.move(offset);
  74.155 -
  74.156 -        boolean methodExpected = false;
  74.157 -
  74.158 -        if (!ts.moveNext() && !ts.movePrevious()) {
  74.159 -            return Call.NONE;
  74.160 -        }
  74.161 -
  74.162 -        if (ts.offset() == offset) {
  74.163 -            // We're looking at the offset to the RIGHT of the caret
  74.164 -            // position, which could be whitespace, e.g.
  74.165 -            //  "foo.x| " <-- looking at the whitespace
  74.166 -            ts.movePrevious();
  74.167 -        }
  74.168 -
  74.169 -        Token<? extends PythonTokenId> token = ts.token();
  74.170 -
  74.171 -        if (token != null) {
  74.172 -            TokenId id = token.id();
  74.173 -
  74.174 -            if (id == PythonTokenId.WHITESPACE) {
  74.175 -                return Call.LOCAL;
  74.176 -            }
  74.177 -
  74.178 -            // See if we're in the identifier - "x" in "foo.x"
  74.179 -            // I could also be a keyword in case the prefix happens to currently
  74.180 -            // match a keyword, such as "next"
  74.181 -            // However, if we're at the end of the document, x. will lex . as an
  74.182 -            // identifier of text ".", so handle this case specially
  74.183 -            if ((id == PythonTokenId.IDENTIFIER)/* || (id == PythonTokenId.CONSTANT)*/ ||
  74.184 -                    id.primaryCategory().equals("keyword")) {
  74.185 -                String tokenText = token.text().toString();
  74.186 -
  74.187 -                if (".".equals(tokenText)) {
  74.188 -                    // Special case - continue - we'll handle this part next
  74.189 -                    methodExpected = true;
  74.190 -                } else {
  74.191 -                    methodExpected = true;
  74.192 -
  74.193 -                    if (Character.isUpperCase(tokenText.charAt(0))) {
  74.194 -                        methodExpected = false;
  74.195 -                    }
  74.196 -
  74.197 -                    if (!ts.movePrevious()) {
  74.198 -                        return Call.LOCAL;
  74.199 -                    }
  74.200 -                }
  74.201 -
  74.202 -                token = ts.token();
  74.203 -                id = token.id();
  74.204 -            }
  74.205 -
  74.206 -            // If we're not in the identifier we need to be in the dot (in "foo.x").
  74.207 -            // I can't just check for tokens DOT and COLON3 because for unparseable source
  74.208 -            // (like "File.|") the lexer will return the "." as an identifier.
  74.209 -            if (id == PythonTokenId.DOT) {
  74.210 -                methodExpected = true;
  74.211 -            } else if (id == PythonTokenId.IDENTIFIER) {
  74.212 -                String t = token.text().toString();
  74.213 -
  74.214 -                if (t.equals(".")) {
  74.215 -                    methodExpected = true;
  74.216 -                } else {
  74.217 -                    return Call.LOCAL;
  74.218 -                }
  74.219 -            } else {
  74.220 -                return Call.LOCAL;
  74.221 -            }
  74.222 -
  74.223 -            int lastSeparatorOffset = ts.offset();
  74.224 -            int beginOffset = lastSeparatorOffset;
  74.225 -            int lineStart = 0;
  74.226 -
  74.227 -            try {
  74.228 -                if (offset > doc.getLength()) {
  74.229 -                    offset = doc.getLength();
  74.230 -                }
  74.231 -
  74.232 -                lineStart = Utilities.getRowStart(doc, offset);
  74.233 -            } catch (BadLocationException ble) {
  74.234 -                Exceptions.printStackTrace(ble);
  74.235 -            }
  74.236 -
  74.237 -            // Find the beginning of the expression. We'll go past keywords, identifiers
  74.238 -            // and dots or double-colons
  74.239 -            while (ts.movePrevious()) {
  74.240 -                // If we get to the previous line we're done
  74.241 -                if (ts.offset() < lineStart) {
  74.242 -                    break;
  74.243 -                }
  74.244 -
  74.245 -                token = ts.token();
  74.246 -                id = token.id();
  74.247 -
  74.248 -                String tokenText = null;
  74.249 -                if (id == PythonTokenId.ANY_KEYWORD || id == PythonTokenId.IDENTIFIER) {
  74.250 -                    tokenText = token.text().toString();
  74.251 -                }
  74.252 -
  74.253 -                if (id == PythonTokenId.WHITESPACE) {
  74.254 -                    break;
  74.255 -                } else if (id == PythonTokenId.RBRACKET) {
  74.256 -                    return new Call("ListType", null, false, methodExpected);
  74.257 -                } else if (id == PythonTokenId.RBRACE) {
  74.258 -                    return new Call("DictType", null, false, methodExpected);
  74.259 -                } else if ((id == PythonTokenId.STRING_END)/* || (id == PythonTokenId.QUOTED_STRING_END)*/) {
  74.260 -                    return new Call("StringType", null, false, methodExpected);
  74.261 -                } else if ((id == PythonTokenId.IDENTIFIER) && "True".equals(tokenText)) { // NOI18N
  74.262 -                    return new Call("BooleanType", null, false, methodExpected);
  74.263 -                } else if ((id == PythonTokenId.IDENTIFIER) && "False".equals(tokenText)) { // NOI18N
  74.264 -                    return new Call("BooleanType", null, false, methodExpected);
  74.265 -                } else if (((id == PythonTokenId.IDENTIFIER)) ||
  74.266 -                        id.primaryCategory().equals("keyword") || (id == PythonTokenId.DOT)) {
  74.267 -
  74.268 -                    // We're building up a potential expression such as "Test::Unit" so continue looking
  74.269 -                    beginOffset = ts.offset();
  74.270 -
  74.271 -                    continue;
  74.272 -                } else if ((id == PythonTokenId.LPAREN) || (id == PythonTokenId.LBRACE) ||
  74.273 -                        (id == PythonTokenId.LBRACKET)) {
  74.274 -                    // It's an expression for example within a parenthesis, e.g.
  74.275 -                    // yield(^File.join())
  74.276 -                    // in this case we can do top level completion
  74.277 -                    // TODO: There are probably more valid contexts here
  74.278 -                    break;
  74.279 -                } else if (id == PythonTokenId.ANY_OPERATOR) {
  74.280 -                    break;
  74.281 -                } else {
  74.282 -                    // Something else - such as "getFoo().x|" - at this point we don't know the type
  74.283 -                    // so we'll just return unknown
  74.284 -                    return Call.UNKNOWN;
  74.285 -                }
  74.286 -            }
  74.287 -
  74.288 -            if (beginOffset < lastSeparatorOffset) {
  74.289 -                try {
  74.290 -                    String lhs = doc.getText(beginOffset, lastSeparatorOffset - beginOffset);
  74.291 -
  74.292 -                    if (lhs.equals("super") || lhs.equals("self")) { // NOI18N
  74.293 -
  74.294 -                        return new Call(lhs, lhs, false, true);
  74.295 -                    } else if (Character.isUpperCase(lhs.charAt(0))) {
  74.296 -
  74.297 -//                        // Detect constructor calls of the form String.new.^
  74.298 -//                        if (lhs.endsWith(".new")) { // NOI18N
  74.299 -//                            // See if it looks like a type prior to that
  74.300 -//                            String type = lhs.substring(0, lhs.length()-4); // 4=".new".length()
  74.301 -//                            if (PythonUtils.isValidPythonModuleName(type)) {
  74.302 -//                                return new Call(type, lhs, false, methodExpected);
  74.303 -//                            }
  74.304 -//                        }
  74.305 -
  74.306 -                        String type = null;
  74.307 -//                        if (PythonUtils.isValidPythonModuleName(lhs)) {
  74.308 -                        type = lhs;
  74.309 -//                        }
  74.310 -
  74.311 -                        return new Call(type, lhs, true, methodExpected);
  74.312 -                    } else {
  74.313 -                        return new Call(null, lhs, false, methodExpected);
  74.314 -                    }
  74.315 -                } catch (BadLocationException ble) {
  74.316 -                    Exceptions.printStackTrace(ble);
  74.317 -                }
  74.318 -            } else {
  74.319 -                return Call.UNKNOWN;
  74.320 -            }
  74.321 -        }
  74.322 -
  74.323 -        return Call.LOCAL;
  74.324 -    }
  74.325 -}
    75.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/PythonCommentLexer.java	Fri Sep 18 16:20:24 2015 -0500
    75.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.3 @@ -1,229 +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 org.netbeans.api.lexer.Token;
   75.50 -import org.netbeans.spi.lexer.Lexer;
   75.51 -import org.netbeans.spi.lexer.LexerInput;
   75.52 -import org.netbeans.spi.lexer.LexerRestartInfo;
   75.53 -import org.netbeans.spi.lexer.TokenFactory;
   75.54 -
   75.55 -/**
   75.56 - * A lexer for python comments.
   75.57 - *
   75.58 - * Highlights TODO items and certain keywords (like @-param and @-type (without -)).
   75.59 - *
   75.60 - * @author Tor Norbye
   75.61 - */
   75.62 -public class PythonCommentLexer implements Lexer<PythonCommentTokenId> {
   75.63 -    private static final int EOF = LexerInput.EOF;
   75.64 -    private final LexerInput input;
   75.65 -    private final TokenFactory<PythonCommentTokenId> tokenFactory;
   75.66 -    private final boolean substituting;
   75.67 -
   75.68 -    private static enum State {
   75.69 -        INIT,
   75.70 -        /** We've just seen @type */
   75.71 -        SEEN_TYPE_KEY,
   75.72 -        /** We've just seen @type< > */
   75.73 -        SEEN_TYPE_WS,
   75.74 -        /** We've just seen @type <varname> */
   75.75 -        SEEN_NAME,
   75.76 -        /** We've just seen @type varname< > */
   75.77 -        SEEN_NAME_WS
   75.78 -    };
   75.79 -    private State state;
   75.80 -
   75.81 -    /**
   75.82 -     * A Lexer for Python strings
   75.83 -     * @param substituting If true, handle substitution rules for double quoted strings, otherwise
   75.84 -     *    single quoted strings.
   75.85 -     */
   75.86 -    public PythonCommentLexer(LexerRestartInfo<PythonCommentTokenId> info, boolean substituting) {
   75.87 -        this.input = info.input();
   75.88 -        this.tokenFactory = info.tokenFactory();
   75.89 -        this.substituting = substituting;
   75.90 -        state = (State)info.state();
   75.91 -        if (state == null) {
   75.92 -            state = State.INIT;
   75.93 -        }
   75.94 -    }
   75.95 -
   75.96 -    @Override
   75.97 -    public Object state() {
   75.98 -        return state;
   75.99 -    }
  75.100 -
  75.101 -    @Override
  75.102 -    public Token<PythonCommentTokenId> nextToken() {
  75.103 -        switch (state) {
  75.104 -        case SEEN_NAME:
  75.105 -        case SEEN_TYPE_KEY:
  75.106 -            while (true) {
  75.107 -                int ch = input.read();
  75.108 -                if (ch == ':' && state == State.SEEN_NAME && input.readLength() == 1) {
  75.109 -                    continue;
  75.110 -                }
  75.111 -                if (ch == EOF || !Character.isWhitespace(ch)) {
  75.112 -                    if (ch != EOF) {
  75.113 -                        input.backup(1);
  75.114 -                    }
  75.115 -                    if (input.readLength() > 0) {
  75.116 -                        state = (state == State.SEEN_TYPE_KEY) ? State.SEEN_TYPE_WS : State.SEEN_NAME_WS;
  75.117 -                        return tokenFactory.createToken(PythonCommentTokenId.SEPARATOR,
  75.118 -                                input.readLength());
  75.119 -                    } else {
  75.120 -                        return null;
  75.121 -                    }
  75.122 -                }
  75.123 -            }
  75.124 -
  75.125 -        case SEEN_NAME_WS:
  75.126 -        case SEEN_TYPE_WS:
  75.127 -            while (true) {
  75.128 -                int ch = input.read();
  75.129 -                if (ch == EOF || Character.isWhitespace(ch) || ch == ':') {
  75.130 -                    if (ch != EOF) {
  75.131 -                        input.backup(1);
  75.132 -                    }
  75.133 -                    if (input.readLength() > 0) {
  75.134 -                        State nextState;
  75.135 -                        PythonCommentTokenId id;
  75.136 -                        if (state == State.SEEN_TYPE_WS) {
  75.137 -                            nextState = State.SEEN_NAME;
  75.138 -                            id = PythonCommentTokenId.VARNAME;
  75.139 -                        } else {
  75.140 -                            nextState = State.INIT;
  75.141 -                            id = PythonCommentTokenId.TYPE;
  75.142 -                        }
  75.143 -                        state = nextState;
  75.144 -                        return tokenFactory.createToken(id, input.readLength());
  75.145 -                    } else if (ch == EOF) {
  75.146 -                        return null;
  75.147 -                    } else {
  75.148 -                        // Error - : without an actual var name
  75.149 -                        state = State.INIT;
  75.150 -                        return nextToken(); // recurse
  75.151 -                    }
  75.152 -                }
  75.153 -            }
  75.154 -        default:
  75.155 -        case INIT: {
  75.156 -
  75.157 -            int last = EOF;
  75.158 -            while (true) {
  75.159 -                int ch = input.read();
  75.160 -
  75.161 -                switch (ch) {
  75.162 -                case EOF:
  75.163 -                    if (input.readLength() > 0) {
  75.164 -                        return tokenFactory.createToken(PythonCommentTokenId.TEXT,
  75.165 -                                input.readLength());
  75.166 -                    } else {
  75.167 -                        return null;
  75.168 -                    }
  75.169 -
  75.170 -                case '@': {
  75.171 -                    // Is it "@type"
  75.172 -                    int initialReadLength = input.readLength();
  75.173 -                    if (input.read() == 't' && input.read() == 'y' && input.read() == 'p' && input.read() == 'e') {
  75.174 -                        if (input.readLength() > 5) {
  75.175 -                            input.backup(5);
  75.176 -                            // Finish this token such that we can do a dedicated token for the @type item.
  75.177 -                            return tokenFactory.createToken(PythonCommentTokenId.TEXT,
  75.178 -                                    input.readLength());
  75.179 -                        }
  75.180 -                        state = State.SEEN_TYPE_KEY;
  75.181 -                        return tokenFactory.createToken(PythonCommentTokenId.TYPEKEY,
  75.182 -                                input.readLength());
  75.183 -                    }
  75.184 -                    if (input.readLength() > initialReadLength) {
  75.185 -                        input.backup(input.readLength() - initialReadLength);
  75.186 -                    } else {
  75.187 -                        return tokenFactory.createToken(PythonCommentTokenId.TEXT,
  75.188 -                                input.readLength());
  75.189 -                    }
  75.190 -                }
  75.191 -                break;
  75.192 -
  75.193 -                case 'T': {
  75.194 -                    if (last == EOF || !Character.isLetter(last)) {
  75.195 -                        // Is it "\wTODO\w" ?
  75.196 -                        int initialReadLength = input.readLength();
  75.197 -                        if (input.read() == 'O' && input.read() == 'D' && input.read() == 'O') {
  75.198 -                            int peek = input.read();
  75.199 -                            input.backup(1);
  75.200 -                            if (peek == EOF || !Character.isLetter(peek)) {
  75.201 -                                if (input.readLength() > 4) {
  75.202 -                                    input.backup(4);
  75.203 -                                    // Finish this token such that we can do a dedicated token for the @type item.
  75.204 -                                    return tokenFactory.createToken(PythonCommentTokenId.TEXT,
  75.205 -                                            input.readLength());
  75.206 -                                }
  75.207 -                                return tokenFactory.createToken(PythonCommentTokenId.TODO,
  75.208 -                                        input.readLength());
  75.209 -                            }
  75.210 -                        }
  75.211 -                        if (input.readLength() > initialReadLength) {
  75.212 -                            input.backup(input.readLength() - initialReadLength);
  75.213 -                        } else {
  75.214 -                            return tokenFactory.createToken(PythonCommentTokenId.TEXT,
  75.215 -                                    input.readLength());
  75.216 -                        }
  75.217 -                    }
  75.218 -                }
  75.219 -                break;
  75.220 -                }
  75.221 -
  75.222 -                last = ch;
  75.223 -            }
  75.224 -
  75.225 -        }
  75.226 -        }
  75.227 -    }
  75.228 -
  75.229 -    @Override
  75.230 -    public void release() {
  75.231 -    }
  75.232 -}
    76.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/PythonCommentTokenId.java	Fri Sep 18 16:20:24 2015 -0500
    76.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.3 @@ -1,120 +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 java.util.Collection;
   76.50 -import java.util.EnumSet;
   76.51 -import java.util.Map;
   76.52 -
   76.53 -import org.netbeans.api.lexer.InputAttributes;
   76.54 -import org.netbeans.api.lexer.Language;
   76.55 -import org.netbeans.api.lexer.LanguagePath;
   76.56 -import org.netbeans.api.lexer.Token;
   76.57 -import org.netbeans.api.lexer.TokenId;
   76.58 -import org.netbeans.spi.lexer.LanguageEmbedding;
   76.59 -import org.netbeans.spi.lexer.LanguageHierarchy;
   76.60 -import org.netbeans.spi.lexer.Lexer;
   76.61 -import org.netbeans.spi.lexer.LexerRestartInfo;
   76.62 -
   76.63 -/**
   76.64 - *
   76.65 - * @author Tor Norbye
   76.66 - */
   76.67 -public enum PythonCommentTokenId implements TokenId {
   76.68 -    TEXT("comment"),
   76.69 -    KEYWORD("comment"),
   76.70 -    SEPARATOR("comment"),
   76.71 -    TYPEKEY("comment"),
   76.72 -    VARNAME("comment"),
   76.73 -    TYPE("comment"),
   76.74 -    TODO("comment");
   76.75 -    private final String primaryCategory;
   76.76 -
   76.77 -    PythonCommentTokenId() {
   76.78 -        this(null);
   76.79 -    }
   76.80 -
   76.81 -    PythonCommentTokenId(String primaryCategory) {
   76.82 -        this.primaryCategory = primaryCategory;
   76.83 -    }
   76.84 -
   76.85 -    @Override
   76.86 -    public String primaryCategory() {
   76.87 -        return primaryCategory;
   76.88 -    }
   76.89 -    public static final Language<PythonCommentTokenId> language =
   76.90 -            new LanguageHierarchy<PythonCommentTokenId>() {
   76.91 -                @Override
   76.92 -                protected Collection<PythonCommentTokenId> createTokenIds() {
   76.93 -                    return EnumSet.allOf(PythonCommentTokenId.class);
   76.94 -                }
   76.95 -
   76.96 -                @Override
   76.97 -                protected Map<String, Collection<PythonCommentTokenId>> createTokenCategories() {
   76.98 -                    return null; // no extra categories
   76.99 -                }
  76.100 -
  76.101 -                @Override
  76.102 -                protected Lexer<PythonCommentTokenId> createLexer(
  76.103 -                        LexerRestartInfo<PythonCommentTokenId> info) {
  76.104 -                    return new PythonCommentLexer(info, true);
  76.105 -                }
  76.106 -
  76.107 -                @Override
  76.108 -                protected LanguageEmbedding<?> embedding(
  76.109 -                        Token<PythonCommentTokenId> token, LanguagePath languagePath,
  76.110 -                        InputAttributes inputAttributes) {
  76.111 -                    return null; // No embedding
  76.112 -                }
  76.113 -
  76.114 -                @Override
  76.115 -                public String mimeType() {
  76.116 -                    return "text/x-python-comment"; // NOI18N
  76.117 -                }
  76.118 -            }.language();
  76.119 -
  76.120 -    public static Language<PythonCommentTokenId> language() {
  76.121 -        return language;
  76.122 -    }
  76.123 -}
    77.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/PythonLexer.java	Fri Sep 18 16:20:24 2015 -0500
    77.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.3 @@ -1,1158 +0,0 @@
    77.4 -/*
    77.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    77.6 - *
    77.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    77.8 - *
    77.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   77.10 - * Other names may be trademarks of their respective owners.
   77.11 - *
   77.12 - * The contents of this file are subject to the terms of either the GNU
   77.13 - * General Public License Version 2 only ("GPL") or the Common
   77.14 - * Development and Distribution License("CDDL") (collectively, the
   77.15 - * "License"). You may not use this file except in compliance with the
   77.16 - * License. You can obtain a copy of the License at
   77.17 - * http://www.netbeans.org/cddl-gplv2.html
   77.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   77.19 - * specific language governing permissions and limitations under the
   77.20 - * License.  When distributing the software, include this License Header
   77.21 - * Notice in each file and include the License file at
   77.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   77.23 - * particular file as subject to the "Classpath" exception as provided
   77.24 - * by Oracle in the GPL Version 2 section of the License file that
   77.25 - * accompanied this code. If applicable, add the following below the
   77.26 - * License Header, with the fields enclosed by brackets [] replaced by
   77.27 - * your own identifying information:
   77.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   77.29 - *
   77.30 - * Contributor(s):
   77.31 - *
   77.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   77.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   77.34 - * Microsystems, Inc. All Rights Reserved.
   77.35 - *
   77.36 - * If you wish your version of this file to be governed by only the CDDL
   77.37 - * or only the GPL Version 2, indicate your decision by adding
   77.38 - * "[Contributor] elects to include this software in this distribution
   77.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   77.40 - * single choice of license, a recipient has the option to distribute
   77.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   77.42 - * to extend the choice of license to its licensees as provided above.
   77.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   77.44 - * Version 2 license, then the option applies only if the new code is
   77.45 - * made subject to such option by the copyright holder.
   77.46 - */
   77.47 -package org.netbeans.modules.python.editor.lexer;
   77.48 -
   77.49 -import org.netbeans.api.lexer.Token;
   77.50 -import org.netbeans.api.lexer.TokenUtilities;
   77.51 -import org.netbeans.spi.lexer.Lexer;
   77.52 -import org.netbeans.spi.lexer.LexerInput;
   77.53 -import org.netbeans.spi.lexer.LexerRestartInfo;
   77.54 -import org.netbeans.spi.lexer.TokenFactory;
   77.55 -
   77.56 -/**
   77.57 - * Lexer for Python.
   77.58 - *
   77.59 - * This is a hand written lexer for Python which recognizes the logical token types
   77.60 - * we care about within the IDE support.
   77.61 - *
   77.62 - * Initially, we were using Jython's lexer directly here. However, that had some
   77.63 - * problems:
   77.64 - *
   77.65 - * <ul>
   77.66 - *   <li>
   77.67 - *     In the IDE, we have to support incremental parsing. Not only is this a must
   77.68 - *     from a user performance perspective (typing a keystroke near the bottom of a
   77.69 - *     2,000 line file shouldn't cause complete re-lexing of the entire document), but
   77.70 - *     the NetBeans APIs require it; they restart the lexer on the nearest token
   77.71 - *     boundary.
   77.72 - *     ANTLR doesn't support incremental lexing. I looked into what it would take
   77.73 - *     to patch it to do so (as I have done for JRuby in the Ruby support), but
   77.74 - *     it (a) wasn't trivial, and (b) would require a LOT of data to be stored for
   77.75 - *     every token boundary.
   77.76 - *   </li>
   77.77 - *   <li>
   77.78 - *     Similarly, we need to put our lexer on top of a LexerInput, and it is not
   77.79 - *     particularly compatible with the way ANTLR handles input. We had an
   77.80 - *     adapter class for this which was jumping through various hoops to expose
   77.81 - *     the LexerInput as ANTLR input. However, it had some severe problems with
   77.82 - *     large inputs.
   77.83 - *   </li>
   77.84 - *   <li>
   77.85 - *     We need slightly different token divisions. For example, for matching bracket
   77.86 - *     purposes, we'd like to have strings split into string delimiters and the
   77.87 - *     string contents. Similarly, Jython did some things like coalesce all whitespace
   77.88 - *     around a newline into that newline token which causes some complications
   77.89 - *     for our token analysis.
   77.90 - *   </li>
   77.91 - *   <li>
   77.92 - *     For Ruby, I decided to use the JRuby lexer because JRuby lexing is very
   77.93 - *     difficult. They have a huge complicated class to do the lexing - and there's
   77.94 - *     no Ruby language spec.  Python on the other hand seems to have a very simple
   77.95 - *     lexing model, and a clear spec and grammar, so I don't feel worried that
   77.96 - *     our custom Python lexer is going to have a lot of corner case bugs.
   77.97 - *   </li>
   77.98 - * </ul>
   77.99 - *
  77.100 - * @author Tor Norbye
  77.101 - */
  77.102 -public final class PythonLexer implements Lexer<PythonTokenId> {
  77.103 -    public static final String COMMENT_CAT = "comment";
  77.104 -    public static final String KEYWORD_CAT = "keyword"; // NOI18N
  77.105 -    public static final String STRING_CAT = "string"; // NOI18N
  77.106 -    public static final String WHITESPACE_CAT = "whitespace"; // NOI18N
  77.107 -    public static final String OPERATOR_CAT = "operator"; // NOI18N
  77.108 -    public static final String SEPARATOR_CAT = "separator"; // NOI18N
  77.109 -    public static final String ERROR_CAT = "error"; // NOI18N
  77.110 -    public static final String NUMBER_CAT = "number"; // NOI18N
  77.111 -    public static final String IDENTIFIER_CAT = "identifier"; // NOI18N
  77.112 -    private static final int EOF = LexerInput.EOF;
  77.113 -    private final LexerInput input;
  77.114 -    private final TokenFactory<PythonTokenId> tokenFactory;
  77.115 -
  77.116 -    // Lexer state - preserved per token boundary
  77.117 -    private enum State {
  77.118 -        /** Normal state, same state as on entry into a Python file */
  77.119 -        INIT,
  77.120 -        /** We've processed the beginning string delimiter of a double-quoted short string */
  77.121 -        BEGIN_SHORTSTRING_DOUBLE,
  77.122 -        /** We've processed the beginning string delimiter of a single-quoted short string */
  77.123 -        BEGIN_SHORTSTRING_SINGLE,
  77.124 -        /** We've processed the beginning string delimiter of a double-quoted long string */
  77.125 -        BEGIN_LONGSTRING_DOUBLE,
  77.126 -        /** We've processed the beginning string delimiter of a singl-quoted long string */
  77.127 -        BEGIN_LONGSTRING_SINGLE,
  77.128 -        /** We've processed the string content in a double-quoted short string */
  77.129 -        END_SHORTSTRING_DOUBLE,
  77.130 -        /** We've processed the string content in a single-quoted short string */
  77.131 -        END_SHORTSTRING_SINGLE,
  77.132 -        /** We've processed the string content in a double-quoted long string */
  77.133 -        END_LONGSTRING_DOUBLE,
  77.134 -        /** We've processed the string content in a single-quoted long string */
  77.135 -        END_LONGSTRING_SINGLE,
  77.136 -    };
  77.137 -    private State state;
  77.138 -
  77.139 -    public PythonLexer(LexerRestartInfo<PythonTokenId> info) {
  77.140 -        this.input = info.input();
  77.141 -        this.tokenFactory = info.tokenFactory();
  77.142 -
  77.143 -        state = (State)info.state();
  77.144 -        if (state == null) {
  77.145 -            state = State.INIT;
  77.146 -        }
  77.147 -    }
  77.148 -
  77.149 -    @Override
  77.150 -    public Object state() {
  77.151 -        return state;
  77.152 -    }
  77.153 -
  77.154 -    private Token<PythonTokenId> createToken(PythonTokenId id, int tokenLength) {
  77.155 -        String fixedText = id.fixedText();
  77.156 -        return (fixedText != null) ? tokenFactory.getFlyweightToken(id, fixedText)
  77.157 -                : tokenFactory.createToken(id, tokenLength);
  77.158 -    }
  77.159 -
  77.160 -    @SuppressWarnings("fallthrough")
  77.161 -    @Override
  77.162 -    public Token<PythonTokenId> nextToken() {
  77.163 -        switch (state) {
  77.164 -        case INIT: {
  77.165 -            int ch = input.read();
  77.166 -            switch (ch) {
  77.167 -            case EOF:
  77.168 -                return null;
  77.169 -
  77.170 -            // Newline
  77.171 -            case '\n':
  77.172 -                assert input.readLength() == 1;
  77.173 -                return createToken(PythonTokenId.NEWLINE, 1);
  77.174 -
  77.175 -            // Whitespace
  77.176 -            case ' ':
  77.177 -            case '\t': {
  77.178 -                for (; ch != EOF; ch = input.read()) {
  77.179 -                    if (ch != ' ' && ch != '\t') {
  77.180 -                        break;
  77.181 -                    }
  77.182 -                }
  77.183 -                input.backup(1);
  77.184 -                return createToken(PythonTokenId.WHITESPACE, input.readLength());
  77.185 -            }
  77.186 -
  77.187 -            // Comment
  77.188 -            case '#': {
  77.189 -                ch = input.read();
  77.190 -                while (ch != EOF && ch != '\n') {
  77.191 -                    ch = input.read();
  77.192 -                }
  77.193 -                input.backup(1);
  77.194 -                return createToken(PythonTokenId.COMMENT, input.readLength());
  77.195 -            }
  77.196 -
  77.197 -            case '.': {
  77.198 -                assert input.readLength() == 1;
  77.199 -                int peek = input.read();
  77.200 -                input.backup(1);
  77.201 -                if (!Character.isDigit(peek)) {
  77.202 -                    return createToken(PythonTokenId.DOT, 1);
  77.203 -                } // else: Fallthrough to process the number!!
  77.204 -            } // FALLTHROUGH
  77.205 -            // FALLTHROUGH!!!!
  77.206 -
  77.207 -            // Number (integer, float, complex)
  77.208 -            case '0':
  77.209 -            case '1':
  77.210 -            case '2':
  77.211 -            case '3':
  77.212 -            case '4':
  77.213 -            case '5':
  77.214 -            case '6':
  77.215 -            case '7':
  77.216 -            case '8':
  77.217 -            case '9': {
  77.218 -                if (ch == '0') {
  77.219 -                    int peek = input.read();
  77.220 -                    if (peek == 'x' || peek == 'X') {
  77.221 -                        // Hex
  77.222 -                        ch = input.read();
  77.223 -                        while (ch != EOF) {
  77.224 -                            if (!(Character.isDigit(ch) ||
  77.225 -                                    (ch >= 'a' && ch <= 'f') ||
  77.226 -                                    (ch >= 'A' && ch <= 'F'))) {
  77.227 -                                break;
  77.228 -                            }
  77.229 -                            ch = input.read();
  77.230 -                        }
  77.231 -                        if (ch != 'l' && (ch != 'L')) {
  77.232 -                            input.backup(1);
  77.233 -                        }
  77.234 -                        return createToken(PythonTokenId.INT_LITERAL, input.readLength());
  77.235 -                    }
  77.236 -                    input.backup(1);
  77.237 -                }
  77.238 -                boolean isFloat = false;
  77.239 -                digitLoop:
  77.240 -                for (; ch != EOF; ch = input.read()) {
  77.241 -                    switch (ch) {
  77.242 -                    case '0':
  77.243 -                    case '1':
  77.244 -                    case '2':
  77.245 -                    case '3':
  77.246 -                    case '4':
  77.247 -                    case '5':
  77.248 -                    case '6':
  77.249 -                    case '7':
  77.250 -                    case '8':
  77.251 -                    case '9':
  77.252 -                        continue;
  77.253 -                    case '.':
  77.254 -                        isFloat = true;
  77.255 -                        continue;
  77.256 -                    case 'e': // Exponent
  77.257 -                    case 'E': {
  77.258 -                        int peek = input.read();
  77.259 -                        if (peek != '+' && peek != '-') {
  77.260 -                            input.backup(1);
  77.261 -                        }
  77.262 -                        ch = input.read();
  77.263 -                        while (ch != EOF) {
  77.264 -                            if (!Character.isDigit(ch)) {
  77.265 -                                break;
  77.266 -                            }
  77.267 -                            ch = input.read();
  77.268 -                        }
  77.269 -                        if (ch != 'j' && ch != 'J') {
  77.270 -                            input.backup(1);
  77.271 -                        }
  77.272 -                        return createToken(PythonTokenId.FLOAT_LITERAL, input.readLength());
  77.273 -                    }
  77.274 -                    case 'j': // Imaginary
  77.275 -                    case 'J':
  77.276 -                        isFloat = true;
  77.277 -                        break digitLoop;
  77.278 -                    case 'l': // Long
  77.279 -                    case 'L':
  77.280 -                        break digitLoop;
  77.281 -                    case EOF:
  77.282 -                    default:
  77.283 -                        input.backup(1);
  77.284 -                        break digitLoop;
  77.285 -
  77.286 -                    }
  77.287 -                }
  77.288 -
  77.289 -                return createToken(isFloat ? PythonTokenId.FLOAT_LITERAL : PythonTokenId.INT_LITERAL, input.readLength());
  77.290 -            }
  77.291 -
  77.292 -            // Operators and delimiters
  77.293 -            case '+': // +,+=
  77.294 -                if (input.read() != '=') {
  77.295 -                    input.backup(1);
  77.296 -                }
  77.297 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  77.298 -            case '-': // -,-=
  77.299 -                if (input.read() != '=') {
  77.300 -                    input.backup(1);
  77.301 -                }
  77.302 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  77.303 -            case '*': { // *,**,*=, **=
  77.304 -                int peek = input.read();
  77.305 -                if (peek == '=') {
  77.306 -                    // No need to back up, include it
  77.307 -                } else if (peek == '*') {
  77.308 -                    peek = input.read();
  77.309 -                    if (peek != '=') {
  77.310 -                        input.backup(1);
  77.311 -                    }
  77.312 -                } else {
  77.313 -                    input.backup(1);
  77.314 -                }
  77.315 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  77.316 -            }
  77.317 -            case '/': {
  77.318 -                // Look for /,//, /=, //=
  77.319 -                int peek = input.read();
  77.320 -                if (peek == '=') {
  77.321 -                    // No need to back up, include it
  77.322 -                } else if (peek == '/') {
  77.323 -                    peek = input.read();
  77.324 -                    if (peek != '=') {
  77.325 -                        input.backup(1);
  77.326 -                    }
  77.327 -                } else {
  77.328 -                    input.backup(1);
  77.329 -                }
  77.330 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  77.331 -            }
  77.332 -            case '%': { // Look for %,   %=
  77.333 -                if (input.read() != '=') {
  77.334 -                    input.backup(1);
  77.335 -                }
  77.336 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  77.337 -            }
  77.338 -            case '<': {
  77.339 -                // Look for <, <<, <=, <>, <<=
  77.340 -                int peek = input.read();
  77.341 -                if (peek == '=') {
  77.342 -                    // No need to back up, include it
  77.343 -                } else if (peek == '<') {
  77.344 -                    peek = input.read();
  77.345 -                    if (peek != '=') {
  77.346 -                        input.backup(1);
  77.347 -                    }
  77.348 -                } else if (peek != '>') {
  77.349 -                    input.backup(1);
  77.350 -                }
  77.351 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  77.352 -            }
  77.353 -            case '>': {
  77.354 -                // Look for >, >>, >=, >>=
  77.355 -                int peek = input.read();
  77.356 -                if (peek == '=') {
  77.357 -                    // No need to back up, include it
  77.358 -                } else if (peek == '>') {
  77.359 -                    peek = input.read();
  77.360 -                    if (peek != '=') {
  77.361 -                        input.backup(1);
  77.362 -                    }
  77.363 -                } else {
  77.364 -                    input.backup(1);
  77.365 -                }
  77.366 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  77.367 -            }
  77.368 -            case '&': { // Look for &,&=
  77.369 -                if (input.read() != '=') {
  77.370 -                    input.backup(1);
  77.371 -                }
  77.372 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  77.373 -            }
  77.374 -            case '|': { // Look for |, |=
  77.375 -                if (input.read() != '=') {
  77.376 -                    input.backup(1);
  77.377 -                }
  77.378 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  77.379 -            }
  77.380 -            case '^': { // ^,^=
  77.381 -                if (input.read() != '=') {
  77.382 -                    input.backup(1);
  77.383 -                }
  77.384 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  77.385 -            }
  77.386 -            case '=': {
  77.387 -                // Look for =,==
  77.388 -                if (input.read() != '=') {
  77.389 -                    input.backup(1);
  77.390 -                }
  77.391 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  77.392 -            }
  77.393 -            case '!': {
  77.394 -                // Look for !=
  77.395 -                if (input.read() != '=') {
  77.396 -                    input.backup(1);
  77.397 -                }
  77.398 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  77.399 -            }
  77.400 -            case '~':
  77.401 -            case '`':
  77.402 -            case ';':
  77.403 -                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
  77.404 -
  77.405 -            case ':':
  77.406 -                assert input.readLength() == 1;
  77.407 -                return createToken(PythonTokenId.COLON, 1);
  77.408 -            case '(':
  77.409 -                assert input.readLength() == 1;
  77.410 -                return createToken(PythonTokenId.LPAREN, 1);
  77.411 -            case ')':
  77.412 -                assert input.readLength() == 1;
  77.413 -                return createToken(PythonTokenId.RPAREN, 1);
  77.414 -            case '[':
  77.415 -                assert input.readLength() == 1;
  77.416 -                return createToken(PythonTokenId.LBRACKET, 1);
  77.417 -            case ']':
  77.418 -                assert input.readLength() == 1;
  77.419 -                return createToken(PythonTokenId.RBRACKET, 1);
  77.420 -            case '{':
  77.421 -                assert input.readLength() == 1;
  77.422 -                return createToken(PythonTokenId.LBRACE, 1);
  77.423 -            case '}':
  77.424 -                assert input.readLength() == 1;
  77.425 -                return createToken(PythonTokenId.RBRACE, 1);
  77.426 -            case ',':
  77.427 -                assert input.readLength() == 1;
  77.428 -                return createToken(PythonTokenId.COMMA, 1);
  77.429 -            case '\\':
  77.430 -                assert input.readLength() == 1;
  77.431 -                return createToken(PythonTokenId.ESC, 1);
  77.432 -
  77.433 -            case '$':
  77.434 -            case '?':
  77.435 -                assert input.readLength() == 1;
  77.436 -                return createToken(PythonTokenId.ERROR, 1);
  77.437 -
  77.438 -            // String?
  77.439 -            case '\'':
  77.440 -            case '"': {
  77.441 -                int peek = input.read();
  77.442 -                if (peek != ch) {
  77.443 -                    input.backup(1);
  77.444 -                    assert input.readLength() == 1;
  77.445 -                    state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
  77.446 -                    return createToken(PythonTokenId.STRING_BEGIN, 1);
  77.447 -                }
  77.448 -                // We've seen two quotes... it's either an empty string,
  77.449 -                // or the beginning of a longstring
  77.450 -                int peek2 = input.read();
  77.451 -                if (peek2 == peek) {
  77.452 -                    // It's a longstring!
  77.453 -                    assert input.readLength() == 3;
  77.454 -                    state = (ch == '"') ? State.BEGIN_LONGSTRING_DOUBLE : State.BEGIN_LONGSTRING_SINGLE;
  77.455 -                    return createToken(PythonTokenId.STRING_BEGIN, 3);
  77.456 -                } else {
  77.457 -                    input.backup(2);
  77.458 -                    assert input.readLength() == 1;
  77.459 -                    state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
  77.460 -                    return createToken(PythonTokenId.STRING_BEGIN, 1);
  77.461 -                }
  77.462 -            }
  77.463 -            case '@': { // Decorator
  77.464 -                // Identifier or keyword?
  77.465 -                ch = input.read();
  77.466 -                if (Character.isJavaIdentifierStart(ch)) {
  77.467 -                    while (ch != EOF && Character.isJavaIdentifierPart(ch) && ch != '$') {
  77.468 -                        ch = input.read();
  77.469 -                    }
  77.470 -                    input.backup(1);
  77.471 -
  77.472 -                    return createToken(PythonTokenId.DECORATOR, input.readLength());
  77.473 -                }
  77.474 -                input.backup(1); // Remove the peeked char
  77.475 -
  77.476 -                assert input.readLength() == 1;
  77.477 -                return createToken(PythonTokenId.DECORATOR, 1);
  77.478 -            }
  77.479 -
  77.480 -            case 'r':
  77.481 -            case 'R':
  77.482 -            case 'u':
  77.483 -            case 'U': {
  77.484 -                // Digest the "u" and the "r" and position the input
  77.485 -                // before the following ' or "
  77.486 -                boolean isStringPrefix = false;
  77.487 -                int peek = input.read();
  77.488 -                if (ch == 'r' || ch == 'R') {
  77.489 -                    if (peek == '\'' || peek == '"') {
  77.490 -                        isStringPrefix = true;
  77.491 -                    }
  77.492 -                    input.backup(1);
  77.493 -                } else {
  77.494 -                    assert ch == 'u' || ch == 'U';
  77.495 -                    if (peek == 'r' || peek == 'R') {
  77.496 -                        int peek2 = input.read();
  77.497 -                        if (peek2 == '\'' || peek2 == '"') {
  77.498 -                            isStringPrefix = true;
  77.499 -                        }
  77.500 -                        input.backup(1);
  77.501 -                    } else if (peek == '\'' || peek == '"') {
  77.502 -                        isStringPrefix = true;
  77.503 -                        input.backup(1);
  77.504 -                    }
  77.505 -                    if (!isStringPrefix) {
  77.506 -                        input.backup(1);
  77.507 -                    }
  77.508 -                }
  77.509 -                if (isStringPrefix) {
  77.510 -                    ch = input.read();
  77.511 -                    assert ch == '\'' || ch == '"';
  77.512 -
  77.513 -                    peek = input.read();
  77.514 -                    if (peek != ch) {
  77.515 -                        input.backup(1);
  77.516 -                        state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
  77.517 -                        return createToken(PythonTokenId.STRING_BEGIN, input.readLength());
  77.518 -                    }
  77.519 -                    // We've seen two quotes... it's either an empty string,
  77.520 -                    // or the beginning of a longstring
  77.521 -                    int peek2 = input.read();
  77.522 -                    if (peek2 == peek) {
  77.523 -                        // It's a longstring!
  77.524 -                        state = (ch == '"') ? State.BEGIN_LONGSTRING_DOUBLE : State.BEGIN_LONGSTRING_SINGLE;
  77.525 -                        return createToken(PythonTokenId.STRING_BEGIN, input.readLength());
  77.526 -                    } else {
  77.527 -                        input.backup(2);
  77.528 -                        state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
  77.529 -                        return createToken(PythonTokenId.STRING_BEGIN, input.readLength());
  77.530 -                    }
  77.531 -                }// else: FALLTHROUGH!!! The "u" or "r" is probably an identifier prefix!!
  77.532 -            }
  77.533 -            // Fallthrough...
  77.534 -
  77.535 -            default: {
  77.536 -                // Identifier or keyword?
  77.537 -                if (Character.isJavaIdentifierStart(ch)) {
  77.538 -                    while (ch != EOF && Character.isJavaIdentifierPart(ch) && ch != '$') {
  77.539 -                        ch = input.read();
  77.540 -                    }
  77.541 -                    input.backup(1);
  77.542 -
  77.543 -                    // See if it's a keyword
  77.544 -                    PythonTokenId pid = getKeywordToken(input.readText());
  77.545 -                    if (pid != null) {
  77.546 -                        return createToken(pid, input.readLength());
  77.547 -                    } else {
  77.548 -                        return createToken(PythonTokenId.IDENTIFIER, input.readLength());
  77.549 -                    }
  77.550 -                }
  77.551 -
  77.552 -                assert input.readLength() == 1;
  77.553 -                return createToken(PythonTokenId.ANY_OPERATOR, 1);
  77.554 -            }
  77.555 -            }
  77.556 -        }
  77.557 -
  77.558 -        case BEGIN_LONGSTRING_SINGLE:
  77.559 -        case BEGIN_LONGSTRING_DOUBLE: {
  77.560 -            // In a long string. Look for the end.
  77.561 -            int ch = input.read();
  77.562 -            if (ch == EOF) {
  77.563 -                return null;
  77.564 -            }
  77.565 -            int term = (state == State.BEGIN_LONGSTRING_DOUBLE) ? '"' : '\'';
  77.566 -            while (ch != EOF) {
  77.567 -                if (ch == '\\') {
  77.568 -                    // It's an escape - read escaped char
  77.569 -                    input.read();
  77.570 -                } else if (ch == term) {
  77.571 -                    int peek = input.read();
  77.572 -                    if (peek == term) {
  77.573 -                        int peek2 = input.read();
  77.574 -                        if (peek2 == term) {
  77.575 -                            // Found the end
  77.576 -                            if (input.readLength() == 3) {
  77.577 -                                // Empty string - go straight to closed state
  77.578 -                                state = State.INIT;
  77.579 -                                return createToken(PythonTokenId.STRING_END, input.readLength());
  77.580 -                            }
  77.581 -                            input.backup(3);
  77.582 -                            if (state == State.BEGIN_LONGSTRING_DOUBLE) {
  77.583 -                                state = State.END_LONGSTRING_DOUBLE;
  77.584 -                            } else {
  77.585 -                                assert state == State.BEGIN_LONGSTRING_SINGLE;
  77.586 -                                state = State.END_LONGSTRING_SINGLE;
  77.587 -                            }
  77.588 -                            return createToken(PythonTokenId.STRING_LITERAL, input.readLength());
  77.589 -                        }
  77.590 -                        input.backup(1);
  77.591 -                    }
  77.592 -                    input.backup(1);
  77.593 -                }
  77.594 -                ch = input.read();
  77.595 -            }
  77.596 -            // Literal not terminated
  77.597 -            state = State.INIT;
  77.598 -            return createToken(PythonTokenId.ERROR, input.readLength());
  77.599 -        }
  77.600 -        case BEGIN_SHORTSTRING_SINGLE:
  77.601 -        case BEGIN_SHORTSTRING_DOUBLE: {
  77.602 -            // In a short string. Look for the end.
  77.603 -            int ch = input.read();
  77.604 -            if (ch == EOF) {
  77.605 -                return null;
  77.606 -            }
  77.607 -            int term = (state == State.BEGIN_SHORTSTRING_DOUBLE) ? '"' : '\'';
  77.608 -            while (ch != EOF) {
  77.609 -                if (ch == '\\') {
  77.610 -                    // It's an escape - read escaped char
  77.611 -                    input.read();
  77.612 -                } else if (ch == '\n') {
  77.613 -                    // Literal not terminated
  77.614 -                    state = State.INIT;
  77.615 -                    return createToken(PythonTokenId.ERROR, input.readLength());
  77.616 -                } else if (ch == term) {
  77.617 -                    if (input.readLength() == 1) {
  77.618 -                        // It's an empty string! Skip straight to the end state
  77.619 -                        state = State.INIT;
  77.620 -                        return createToken(PythonTokenId.STRING_END, input.readLength());
  77.621 -                    }
  77.622 -                    input.backup(1);
  77.623 -                    if (state == State.BEGIN_SHORTSTRING_DOUBLE) {
  77.624 -                        state = State.END_SHORTSTRING_DOUBLE;
  77.625 -                    } else {
  77.626 -                        assert state == State.BEGIN_SHORTSTRING_SINGLE;
  77.627 -                        state = State.END_SHORTSTRING_SINGLE;
  77.628 -                    }
  77.629 -                    return createToken(PythonTokenId.STRING_LITERAL, input.readLength());
  77.630 -                }
  77.631 -                ch = input.read();
  77.632 -            }
  77.633 -            // Literal not terminated
  77.634 -            state = State.INIT;
  77.635 -            return createToken(PythonTokenId.ERROR, input.readLength());
  77.636 -        }
  77.637 -
  77.638 -        case END_LONGSTRING_SINGLE:
  77.639 -        case END_LONGSTRING_DOUBLE: {
  77.640 -            // In a long string. Look for the end.
  77.641 -            int ch = input.read();
  77.642 -            if (ch == EOF) {
  77.643 -                return null;
  77.644 -            }
  77.645 -            int term = (state == State.END_LONGSTRING_DOUBLE) ? '"' : '\'';
  77.646 -            while (ch != EOF) {
  77.647 -                if (ch == term) {
  77.648 -                    int peek = input.read();
  77.649 -                    if (peek == term) {
  77.650 -                        int peek2 = input.read();
  77.651 -                        if (peek2 == term) {
  77.652 -                            // Found the end
  77.653 -                            state = State.INIT;
  77.654 -                            return createToken(PythonTokenId.STRING_END, input.readLength());
  77.655 -                        }
  77.656 -                        input.backup(1);
  77.657 -                    }
  77.658 -                    input.backup(1);
  77.659 -                }
  77.660 -                ch = input.read();
  77.661 -            }
  77.662 -            // Literal not terminated
  77.663 -            state = State.INIT;
  77.664 -            return createToken(PythonTokenId.ERROR, input.readLength());
  77.665 -        }
  77.666 -        case END_SHORTSTRING_SINGLE:
  77.667 -        case END_SHORTSTRING_DOUBLE: {
  77.668 -            // In a short string. Look for the end.
  77.669 -            int ch = input.read();
  77.670 -            if (ch == EOF) {
  77.671 -                return null;
  77.672 -            }
  77.673 -            int term = (state == State.END_SHORTSTRING_DOUBLE) ? '"' : '\'';
  77.674 -            if (ch == term) {
  77.675 -                state = State.INIT;
  77.676 -                return createToken(PythonTokenId.STRING_END, input.readLength());
  77.677 -            }
  77.678 -            state = State.INIT;
  77.679 -            return createToken(PythonTokenId.ERROR, input.readLength());
  77.680 -        }
  77.681 -
  77.682 -        default:
  77.683 -            assert false : state;
  77.684 -        }
  77.685 -
  77.686 -        return null;
  77.687 -    }
  77.688 -
  77.689 -    @Override
  77.690 -    public void release() {
  77.691 -    }
  77.692 -
  77.693 -    private static PythonTokenId getKeywordToken(CharSequence s) {
  77.694 -        int length = s.length();
  77.695 -        if (length < 2) {
  77.696 -            return null;
  77.697 -        }
  77.698 -
  77.699 -        if (BuiltinException.isBuiltInException(s)) {
  77.700 -            return PythonTokenId.ERROR;
  77.701 -        }
  77.702 -
  77.703 -        char c1 = s.charAt(0);
  77.704 -        char c2 = s.charAt(1);
  77.705 -
  77.706 -        switch (c1) {
  77.707 -        case 'a': // and, as, assert, async, await
  77.708 -            switch (c2) {
  77.709 -            case 'b': // abs
  77.710 -                if (length == 3 && TokenUtilities.textEquals(s, "abs")) { // NOI18N
  77.711 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.712 -                }
  77.713 -            case 'l': // all
  77.714 -                if (length == 3 && TokenUtilities.textEquals(s, "all")) {  // NOI18N
  77.715 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.716 -                }
  77.717 -            case 'n': // and, any
  77.718 -                if (length == 3 && TokenUtilities.textEquals(s, "and")) { // NOI18N
  77.719 -                    return PythonTokenId.ANY_KEYWORD;
  77.720 -                } else if (TokenUtilities.textEquals(s, "any")) {  // NOI18N
  77.721 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.722 -                }
  77.723 -                break;
  77.724 -            case 's':  // as, ascii, assert, async
  77.725 -                if (length == 2) { // as
  77.726 -                    return PythonTokenId.ANY_KEYWORD;
  77.727 -                }
  77.728 -                if (length == 5 && TokenUtilities.textEquals(s, "ascii")) {  // NOI18N
  77.729 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.730 -                }
  77.731 -                if (length == 6 && TokenUtilities.textEquals(s, "assert")) { // NOI18N
  77.732 -                    return PythonTokenId.ANY_KEYWORD;
  77.733 -                }
  77.734 -                if (length == 5 && TokenUtilities.textEquals(s, "async")) { // NOI18N
  77.735 -                    return PythonTokenId.ANY_KEYWORD;
  77.736 -                }
  77.737 -                break;
  77.738 -            case 'w': // await
  77.739 -                if (length == 5 && TokenUtilities.textEquals(s, "await")) { // NOI18N
  77.740 -                    return PythonTokenId.ANY_KEYWORD;
  77.741 -                }
  77.742 -            }
  77.743 -            break;
  77.744 -        case 'b': // basestring, bin, bool, break, bytearray, bytes
  77.745 -            if (length == 10 && TokenUtilities.textEquals(s, "basestring")) {  // NOI18N
  77.746 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.747 -            }
  77.748 -            if (length == 3 && TokenUtilities.textEquals(s, "bin")) {  // NOI18N
  77.749 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.750 -            }
  77.751 -            if (length == 4 && TokenUtilities.textEquals(s, "bool")) {  // NOI18N
  77.752 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.753 -            }
  77.754 -            if (length == 5 && TokenUtilities.textEquals(s, "break")) { // NOI18N
  77.755 -                return PythonTokenId.ANY_KEYWORD;
  77.756 -            }
  77.757 -            if (length == 9 && TokenUtilities.textEquals(s, "bytearray")) {  // NOI18N
  77.758 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.759 -            }
  77.760 -            if (length == 5 && TokenUtilities.textEquals(s, "bytes")) { // NOI18N
  77.761 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.762 -            }
  77.763 -            break;
  77.764 -        case 'c': // callable, chr, class, classmethod, continue
  77.765 -            switch (c2) {
  77.766 -            case 'a': // callable
  77.767 -                if (length == 8 && TokenUtilities.textEquals(s, "callable")) {  // NOI18N
  77.768 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.769 -                }
  77.770 -                break;
  77.771 -            case 'h': // chr
  77.772 -                if (length == 3 && TokenUtilities.textEquals(s, "chr")) {  // NOI18N
  77.773 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.774 -                }
  77.775 -                break;
  77.776 -            case 'l': // class, classmethod
  77.777 -                if (length == 5 && TokenUtilities.textEquals(s, "class")) { // NOI18N
  77.778 -                    return PythonTokenId.CLASS;
  77.779 -                }
  77.780 -                if (length == 11 && TokenUtilities.textEquals(s, "classmethod")) {  // NOI18N
  77.781 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.782 -                }
  77.783 -                break;
  77.784 -            case 'm': // cmp
  77.785 -                if (length == 3 && TokenUtilities.textEquals(s, "cmp")) {  // NOI18N
  77.786 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.787 -                }
  77.788 -                break;
  77.789 -            case 'o':  // compile, complex, continue
  77.790 -                if (length == 7 && TokenUtilities.textEquals(s, "compile")) {  // NOI18N
  77.791 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.792 -                }
  77.793 -                if (length == 7 && TokenUtilities.textEquals(s, "complex")) {  // NOI18N
  77.794 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.795 -                }
  77.796 -                if (length == 8 && TokenUtilities.textEquals(s, "continue")) { // NOI18N
  77.797 -                    return PythonTokenId.ANY_KEYWORD;
  77.798 -                }
  77.799 -                break;
  77.800 -            }
  77.801 -            break;
  77.802 -        case 'd': // def, del
  77.803 -            switch (c2) {
  77.804 -                case 'e': // def, del, delattr
  77.805 -                    if (length == 3 && TokenUtilities.textEquals(s, "def")) {  // NOI18N
  77.806 -                        return PythonTokenId.DEF;
  77.807 -                    }
  77.808 -                    if (length == 3 && TokenUtilities.textEquals(s, "del")) {  // NOI18N
  77.809 -                        return PythonTokenId.ANY_KEYWORD;
  77.810 -                    }
  77.811 -                    if (length == 7 && TokenUtilities.textEquals(s, "delattr")) {  // NOI18N
  77.812 -                        return PythonTokenId.BUILTIN_FUNCTION;
  77.813 -                    }
  77.814 -                    break;
  77.815 -                case 'i': // dict, dir, divmod
  77.816 -                    if (length == 4 && TokenUtilities.textEquals(s, "dict")) {  // NOI18N
  77.817 -                        return PythonTokenId.BUILTIN_FUNCTION;
  77.818 -                    }
  77.819 -                    if (length == 3 && TokenUtilities.textEquals(s, "dir")) {  // NOI18N
  77.820 -                        return PythonTokenId.BUILTIN_FUNCTION;
  77.821 -                    }
  77.822 -                    if (length == 6 && TokenUtilities.textEquals(s, "divmod")) {  // NOI18N
  77.823 -                        return PythonTokenId.BUILTIN_FUNCTION;
  77.824 -                    }
  77.825 -                    break;
  77.826 -            }
  77.827 -            break;
  77.828 -        case 'e': // elif, else, enumerate, eval, except, exec, execfile
  77.829 -            switch (c2) {
  77.830 -            case 'l': // elif, else
  77.831 -                if (length == 4) {
  77.832 -                    if (TokenUtilities.textEquals(s, "elif")) { // NOI18N
  77.833 -                        return PythonTokenId.ELIF;
  77.834 -                    }
  77.835 -                    if (TokenUtilities.textEquals(s, "else")) { // NOI18N
  77.836 -                        return PythonTokenId.ELSE;
  77.837 -                    }
  77.838 -                }
  77.839 -                break;
  77.840 -            case 'n': // enumerate
  77.841 -                if (length == 9 && TokenUtilities.textEquals(s, "enumerate")) { // NOI18N
  77.842 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.843 -                }
  77.844 -                break;
  77.845 -            case 'v': // eval
  77.846 -                if (length == 4 && TokenUtilities.textEquals(s, "eval")) {  // NOI18N
  77.847 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.848 -                }
  77.849 -                break;
  77.850 -            case 'x': // except, exec, execfile
  77.851 -                if (length == 4 && TokenUtilities.textEquals(s, "exec")) { // NOI18N
  77.852 -                    return PythonTokenId.ANY_KEYWORD;
  77.853 -                }
  77.854 -                if (length == 8 && TokenUtilities.textEquals(s, "execfile")) { // NOI18N
  77.855 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.856 -                }
  77.857 -                if (length == 6 && TokenUtilities.textEquals(s, "except")) { // NOI18N
  77.858 -                    return PythonTokenId.EXCEPT;
  77.859 -                }
  77.860 -                break;
  77.861 -            }
  77.862 -            break;
  77.863 -        case 'f': // file, filter, finally, for, from
  77.864 -            switch (c2) {
  77.865 -            case 'i': // file, filter, finally
  77.866 -                if (length == 4 && TokenUtilities.textEquals(s, "file")) {  // NOI18N
  77.867 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.868 -                }
  77.869 -                if (length == 6 && TokenUtilities.textEquals(s, "filter")) {  // NOI18N
  77.870 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.871 -                }
  77.872 -                if (length == 7 && TokenUtilities.textEquals(s, "finally")) { // NOI18N
  77.873 -                    return PythonTokenId.FINALLY;
  77.874 -                }
  77.875 -                break;
  77.876 -            case 'o': // for, format
  77.877 -                if (length == 3 && TokenUtilities.textEquals(s, "for")) { // NOI18N
  77.878 -                    return PythonTokenId.ANY_KEYWORD;
  77.879 -                }
  77.880 -                if (length == 6 && TokenUtilities.textEquals(s, "format")) {  // NOI18N
  77.881 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.882 -                }
  77.883 -                break;
  77.884 -            case 'r': // from, frozenset
  77.885 -                if (length == 4 && TokenUtilities.textEquals(s, "from")) { // NOI18N
  77.886 -                    return PythonTokenId.FROM;
  77.887 -                }
  77.888 -                if (length == 9 && TokenUtilities.textEquals(s, "frozenset")) {  // NOI18N
  77.889 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.890 -                }
  77.891 -                break;
  77.892 -            case 'l':
  77.893 -                if (length == 5 && TokenUtilities.textEquals(s, "float")) {
  77.894 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.895 -                }
  77.896 -                break;
  77.897 -            }
  77.898 -            break;
  77.899 -        case 'g': // getattr, global, globals
  77.900 -            if (length == 7 && TokenUtilities.textEquals(s, "getattr")) {  // NOI18N
  77.901 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.902 -            }
  77.903 -            if (length == 6 && TokenUtilities.textEquals(s, "global")) { // NOI18N
  77.904 -                return PythonTokenId.ANY_KEYWORD;
  77.905 -            }
  77.906 -            if (length == 7 && TokenUtilities.textEquals(s, "globals")) { // NOI18N
  77.907 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.908 -            }
  77.909 -            break;
  77.910 -        case 'h': // hasattr, hash, help, hex
  77.911 -            if (length == 7 && TokenUtilities.textEquals(s, "hasattr")) {  // NOI18N
  77.912 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.913 -            }
  77.914 -            if (length == 4 && TokenUtilities.textEquals(s, "hash")) {  // NOI18N
  77.915 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.916 -            }
  77.917 -            if (length == 4 && TokenUtilities.textEquals(s, "help")) {  // NOI18N
  77.918 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.919 -            }
  77.920 -            if (length == 3 && TokenUtilities.textEquals(s, "hex")) {  // NOI18N
  77.921 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.922 -            }
  77.923 -            break;
  77.924 -        case 'i': // id, if, import, in, input, int, is, issubclass, iter
  77.925 -            if (length == 2) {
  77.926 -                switch (c2) {
  77.927 -                case 'd': // id
  77.928 -                    return PythonTokenId.BUILTIN_FUNCTION;
  77.929 -                case 'f': // if
  77.930 -                    return PythonTokenId.IF;
  77.931 -                case 'n': // in
  77.932 -                    if (length == 2 && TokenUtilities.textEquals(s, "in")) { //NOI18N
  77.933 -                        return PythonTokenId.ANY_KEYWORD;
  77.934 -                    }
  77.935 -                case 's': // is
  77.936 -                    return PythonTokenId.ANY_KEYWORD;
  77.937 -                }
  77.938 -            } else if (c2 == 'm' && length == 6 && TokenUtilities.textEquals(s, "import")) { // NOI18N
  77.939 -                return PythonTokenId.IMPORT;
  77.940 -            } else if (length == 5 && TokenUtilities.textEquals(s, "input")) {  // NOI18N
  77.941 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.942 -            } else if (length == 3 && TokenUtilities.textEquals(s, "int")) { // NOI18N
  77.943 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.944 -            } else if (length == 10 && TokenUtilities.textEquals(s, "isinstance")) { // NOI18N
  77.945 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.946 -            } else if (length == 10 && TokenUtilities.textEquals(s, "issubclass")) { // NOI18N
  77.947 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.948 -            } else if (length == 4 && TokenUtilities.textEquals(s, "iter")) { // NOI18N
  77.949 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.950 -            }
  77.951 -            break;
  77.952 -        case 'l': // lambda, len, list, locals, long
  77.953 -            if (length == 6 && TokenUtilities.textEquals(s, "lambda")) { // NOI18N
  77.954 -                return PythonTokenId.ANY_KEYWORD;
  77.955 -            } else if (length == 3 && TokenUtilities.textEquals(s, "len")) { // NOI18N
  77.956 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.957 -            } else if (length == 4 && TokenUtilities.textEquals(s, "list")) { // NOI18N
  77.958 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.959 -            } else if (length == 6 && TokenUtilities.textEquals(s, "locals")) { // NOI18N
  77.960 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.961 -            } else if (length == 4 && TokenUtilities.textEquals(s, "long")) { // NOI18N
  77.962 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.963 -            }
  77.964 -            break;
  77.965 -        case 'm': // map, max, memoryview, min
  77.966 -            if (length == 3 && TokenUtilities.textEquals(s, "map")) { // NOI18N
  77.967 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.968 -            }
  77.969 -            if (length == 3 && TokenUtilities.textEquals(s, "max")) { // NOI18N
  77.970 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.971 -            }
  77.972 -            if (length == 10 && TokenUtilities.textEquals(s, "memoryview")) { // NOI18N
  77.973 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.974 -            }
  77.975 -            if (length == 3 && TokenUtilities.textEquals(s, "min")) { // NOI18N
  77.976 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.977 -            }
  77.978 -            break;
  77.979 -        case 'n': // next, nonlocal, not
  77.980 -            if (length == 4 && TokenUtilities.textEquals(s, "next")) { // NOI18N
  77.981 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.982 -            }
  77.983 -            if (length == 8 && TokenUtilities.textEquals(s, "nonlocal")) { // NOI18N
  77.984 -                return PythonTokenId.ANY_KEYWORD;
  77.985 -            }
  77.986 -            if (length == 3 && TokenUtilities.textEquals(s, "not")) { // NOI18N
  77.987 -                return PythonTokenId.ANY_KEYWORD;
  77.988 -            }
  77.989 -            break;
  77.990 -        case 'o': // or, object, oct, open, ord
  77.991 -            if (length == 2 && TokenUtilities.textEquals(s, "or")) { // NOI18N
  77.992 -                return PythonTokenId.ANY_KEYWORD;
  77.993 -            }
  77.994 -            if (length == 6 && TokenUtilities.textEquals(s, "object")) { // NOI18N
  77.995 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.996 -            }
  77.997 -            if (length == 3 && TokenUtilities.textEquals(s, "oct")) { // NOI18N
  77.998 -                return PythonTokenId.BUILTIN_FUNCTION;
  77.999 -            }
 77.1000 -            if (length == 4 && TokenUtilities.textEquals(s, "open")) { // NOI18N
 77.1001 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1002 -            }
 77.1003 -            if (length == 3 && TokenUtilities.textEquals(s, "ord")) { // NOI18N
 77.1004 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1005 -            }
 77.1006 -            break;
 77.1007 -        case 'p': // pass, pow, print, property
 77.1008 -            if (c2 == 'a') { // pass
 77.1009 -                if (length == 4 && TokenUtilities.textEquals(s, "pass")) { // NOI18N
 77.1010 -                    return PythonTokenId.PASS;
 77.1011 -                }
 77.1012 -            }
 77.1013 -            if (length == 3 && TokenUtilities.textEquals(s, "pow")) { // NOI18N
 77.1014 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1015 -            }
 77.1016 -            if (c2 == 'r') { // print, property
 77.1017 -                if (length == 5 && TokenUtilities.textEquals(s, "print")) { // NOI18N
 77.1018 -                    return PythonTokenId.ANY_KEYWORD;
 77.1019 -                }
 77.1020 -                if (length == 8 && TokenUtilities.textEquals(s, "property")) { // NOI18N
 77.1021 -                    return PythonTokenId.BUILTIN_FUNCTION;
 77.1022 -                }
 77.1023 -            }
 77.1024 -            break;
 77.1025 -        case 'r': // raise, range, raise, raw_input, reduce, reload, repr, return, reversed, round
 77.1026 -            if (c2 == 'a') { // raise, range
 77.1027 -                if (length == 5 && TokenUtilities.textEquals(s, "range")) { // NOI18N
 77.1028 -                    return PythonTokenId.BUILTIN_FUNCTION;
 77.1029 -                }
 77.1030 -                if (length == 5 && TokenUtilities.textEquals(s, "raise")) { // NOI18N
 77.1031 -                    return PythonTokenId.RAISE;
 77.1032 -                }
 77.1033 -                if (length == 9 && TokenUtilities.textEquals(s, "raw_input")) { // NOI18N
 77.1034 -                    return PythonTokenId.BUILTIN_FUNCTION;
 77.1035 -                }
 77.1036 -            } else if (c2 == 'e') { // reduce, reload, repr, return, reversed
 77.1037 -                if (length == 6 && TokenUtilities.textEquals(s, "reduce")) { // NOI18N
 77.1038 -                    return PythonTokenId.BUILTIN_FUNCTION;
 77.1039 -                }
 77.1040 -                if (length == 6 && TokenUtilities.textEquals(s, "reload")) {  // NOI18N
 77.1041 -                    return PythonTokenId.BUILTIN_FUNCTION;
 77.1042 -                }
 77.1043 -                if (length == 4 && TokenUtilities.textEquals(s, "repr")) { // NOI18N
 77.1044 -                    return PythonTokenId.BUILTIN_FUNCTION;
 77.1045 -                }
 77.1046 -                if (length == 6 && TokenUtilities.textEquals(s, "return")) { // NOI18N
 77.1047 -                    return PythonTokenId.RETURN;
 77.1048 -                }
 77.1049 -                if (length == 8 && TokenUtilities.textEquals(s, "reversed")) { // NOI18N
 77.1050 -                    return PythonTokenId.BUILTIN_FUNCTION;
 77.1051 -                }
 77.1052 -            } else if (length == 5 && TokenUtilities.textEquals(s, "round")) { // NOI18N
 77.1053 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1054 -            }
 77.1055 -            break;
 77.1056 -        case 's': // self, set, setattr, slice, sorted, staticmethod, str, sum, super
 77.1057 -            if (length == 4 && TokenUtilities.textEquals(s, "self")) { // NOI18N
 77.1058 -                return PythonTokenId.ANY_KEYWORD;
 77.1059 -            }
 77.1060 -            if (length == 3 && TokenUtilities.textEquals(s, "set")) { // NOI18N
 77.1061 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1062 -            }
 77.1063 -            if (length == 7 && TokenUtilities.textEquals(s, "setattr")) { // NOI18N
 77.1064 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1065 -            }
 77.1066 -            if (length == 5 && TokenUtilities.textEquals(s, "slice")) { // NOI18N
 77.1067 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1068 -            }
 77.1069 -            if (length == 6 && TokenUtilities.textEquals(s, "sorted")) { // NOI18N
 77.1070 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1071 -            }
 77.1072 -            if (length == 12 && TokenUtilities.textEquals(s, "staticmethod")) { // NOI18N
 77.1073 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1074 -            }
 77.1075 -            if (length == 3 && TokenUtilities.textEquals(s, "str")) { // NOI18N
 77.1076 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1077 -            }
 77.1078 -            if (length == 3 && TokenUtilities.textEquals(s, "sum")) { // NOI18N
 77.1079 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1080 -            }
 77.1081 -            if (length == 5 && TokenUtilities.textEquals(s, "super")) { // NOI18N
 77.1082 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1083 -            }
 77.1084 -            break;
 77.1085 -        case 't': // try, tuple, type
 77.1086 -            if (length == 3 && TokenUtilities.textEquals(s, "try")) { // NOI18N
 77.1087 -                return PythonTokenId.TRY;
 77.1088 -            } else if (length == 5 && TokenUtilities.textEquals(s, "tuple")) { // NOI18N
 77.1089 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1090 -            } else if (length == 4 && TokenUtilities.textEquals(s, "type")) { // NOI18N
 77.1091 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1092 -            }
 77.1093 -            break;
 77.1094 -        case 'u': // unichr, unicode
 77.1095 -            if (length == 6 && TokenUtilities.textEquals(s, "unichr")) { // NOI18N
 77.1096 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1097 -            }
 77.1098 -            if (length == 7 && TokenUtilities.textEquals(s, "unicode")) { // NOI18N
 77.1099 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1100 -            }
 77.1101 -            break;
 77.1102 -        case 'v': // vars
 77.1103 -            if (length == 4 && TokenUtilities.textEquals(s, "vars")) { // NOI18N
 77.1104 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1105 -            }
 77.1106 -            break;
 77.1107 -        case 'w': // while,with
 77.1108 -            if (c2 == 'h') { // while
 77.1109 -                if (length == 5 && TokenUtilities.textEquals(s, "while")) { // NOI18N
 77.1110 -                    return PythonTokenId.ANY_KEYWORD;
 77.1111 -                }
 77.1112 -            } else if (c2 == 'i') { // with
 77.1113 -                if (length == 4 && TokenUtilities.textEquals(s, "with")) { // NOI18N
 77.1114 -                    return PythonTokenId.ANY_KEYWORD;
 77.1115 -                }
 77.1116 -            }
 77.1117 -            break;
 77.1118 -        case 'x': // xrange
 77.1119 -            if (length == 6 && TokenUtilities.textEquals(s, "xrange")) { // NOI18N
 77.1120 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1121 -            }
 77.1122 -            break;
 77.1123 -        case 'y': // yield
 77.1124 -            if (length == 5 && TokenUtilities.textEquals(s, "yield")) { // NOI18N
 77.1125 -                return PythonTokenId.ANY_KEYWORD;
 77.1126 -            }
 77.1127 -            break;
 77.1128 -        case 'z': // zip
 77.1129 -            if (length == 3 && TokenUtilities.textEquals(s, "zip")) { // NOI18N
 77.1130 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1131 -            }
 77.1132 -            break;
 77.1133 -        case 'F': // False
 77.1134 -            if (length == 5 && TokenUtilities.textEquals(s, "False")) { // NOI18N
 77.1135 -                return PythonTokenId.FALSE;
 77.1136 -            }
 77.1137 -            break;
 77.1138 -        case 'N': // None
 77.1139 -            if (length == 4 && TokenUtilities.textEquals(s, "None")) { // NOI18N
 77.1140 -                return PythonTokenId.NONE;
 77.1141 -            }
 77.1142 -            break;
 77.1143 -        case 'T': // True
 77.1144 -            if (length == 4 && TokenUtilities.textEquals(s, "True")) { // NOI18N
 77.1145 -                return PythonTokenId.TRUE;
 77.1146 -            }
 77.1147 -            break;
 77.1148 -        case '_': // Special symbols of python
 77.1149 -            if (length > 4 && TokenUtilities.startsWith(s, "__") && TokenUtilities.endsWith(s, "__")) { // NOI18N
 77.1150 -                return PythonTokenId.BUILTIN_FUNCTION;
 77.1151 -            }
 77.1152 -            break;
 77.1153 -        }
 77.1154 -
 77.1155 -        return null;
 77.1156 -    }
 77.1157 -
 77.1158 -    public static boolean isKeywordOrBuiltin(CharSequence name) {
 77.1159 -        return getKeywordToken(name) != null;
 77.1160 -    }
 77.1161 -}
    78.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/PythonLexerUtils.java	Fri Sep 18 16:20:24 2015 -0500
    78.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.3 @@ -1,562 +0,0 @@
    78.4 -/*
    78.5 - * To change this template, choose Tools | Templates
    78.6 - * and open the template in the editor.
    78.7 - */
    78.8 -package org.netbeans.modules.python.editor.lexer;
    78.9 -
   78.10 -import java.util.Arrays;
   78.11 -import java.util.List;
   78.12 -import java.util.regex.Matcher;
   78.13 -import java.util.regex.Pattern;
   78.14 -import javax.swing.text.BadLocationException;
   78.15 -import javax.swing.text.Document;
   78.16 -import org.netbeans.api.lexer.Token;
   78.17 -import org.netbeans.api.lexer.TokenHierarchy;
   78.18 -import org.netbeans.api.lexer.TokenId;
   78.19 -import org.netbeans.api.lexer.TokenSequence;
   78.20 -import org.netbeans.editor.BaseDocument;
   78.21 -import org.netbeans.editor.Utilities;
   78.22 -import org.netbeans.modules.csl.api.OffsetRange;
   78.23 -import org.netbeans.modules.python.editor.PythonParserResult;
   78.24 -import org.openide.filesystems.FileUtil;
   78.25 -import org.openide.loaders.DataObject;
   78.26 -import org.openide.util.Exceptions;
   78.27 -import org.python.antlr.PythonTree;
   78.28 -
   78.29 -/**
   78.30 - * Utility functions around the Python lexer
   78.31 - * 
   78.32 - * @author Tor Norbye
   78.33 - */
   78.34 -public class PythonLexerUtils {
   78.35 -    /**
   78.36 -     * Try to produce a more accurate location for the given name in the given import statement, located
   78.37 -     * at the lexRange provided
   78.38 -     */
   78.39 -    public static OffsetRange getImportNameOffset(BaseDocument doc, OffsetRange lexRange, PythonTree node, String name) {
   78.40 -        int docLength = doc.getLength();
   78.41 -        int start = Math.min(docLength, lexRange.getStart());
   78.42 -        int end = Math.min(docLength, lexRange.getEnd());
   78.43 -        try {
   78.44 -            String s = doc.getText(start, end - start);
   78.45 -
   78.46 -            Pattern p = Pattern.compile(".*import\\s+\\b(" + name + ")\\b.*");
   78.47 -            Matcher m = p.matcher(s);
   78.48 -            if (m.matches()) {
   78.49 -                int offset = start + m.start(1);
   78.50 -                return new OffsetRange(offset, offset + name.length());
   78.51 -            }
   78.52 -
   78.53 -            // Lame
   78.54 -            int searchIndex = s.indexOf("import ");
   78.55 -            if (searchIndex == -1) {
   78.56 -                searchIndex = 0;
   78.57 -            } else {
   78.58 -                searchIndex += 7;
   78.59 -            }
   78.60 -            int match = s.indexOf(name, searchIndex + 7);
   78.61 -            if (match != -1) {
   78.62 -                int offset = start + match;
   78.63 -                return new OffsetRange(offset, offset + name.length());
   78.64 -            }
   78.65 -
   78.66 -        // Give up - use the whole range
   78.67 -        } catch (BadLocationException ex) {
   78.68 -            Exceptions.printStackTrace(ex);
   78.69 -        }
   78.70 -
   78.71 -        return lexRange;
   78.72 -    }
   78.73 -
   78.74 -    /** For a possibly generated offset in an AST, return the corresponding lexing/true document offset */
   78.75 -    public static int getLexerOffset(PythonParserResult result, int astOffset) {
   78.76 -        return result.getSnapshot().getOriginalOffset(astOffset);
   78.77 -    }
   78.78 -
   78.79 -    public static OffsetRange getLexerOffsets(PythonParserResult result, OffsetRange astRange) {
   78.80 -        if (result != null) {
   78.81 -            int rangeStart = astRange.getStart();
   78.82 -            int start = result.getSnapshot().getOriginalOffset(rangeStart);
   78.83 -            if (start == rangeStart) {
   78.84 -                return astRange;
   78.85 -            } else if (start == -1) {
   78.86 -                return OffsetRange.NONE;
   78.87 -            } else {
   78.88 -                // Assumes the translated range maintains size
   78.89 -                return new OffsetRange(start, start + astRange.getLength());
   78.90 -            }
   78.91 -        }
   78.92 -
   78.93 -        return astRange;
   78.94 -    }
   78.95 -
   78.96 -    /**
   78.97 -     * Narrow a given lexical offset range to the closest AST-relevant offsets.
   78.98 -     * This means it will pass over things like comments and whitespace.
   78.99 -     * @param doc The document containing the range
  78.100 -     * @param range The start/end lexical range we want to narrow
  78.101 -     * @return An OffsetRange where the offsets begin and end at AST-relevant tokens
  78.102 -     */
  78.103 -    public static OffsetRange narrow(BaseDocument doc, OffsetRange range, boolean skipComments) {
  78.104 -        try {
  78.105 -            doc.readLock(); // For token hiearchy use
  78.106 -            // For token hiearchy use
  78.107 -            int start = range.getStart();
  78.108 -            TokenSequence<? extends PythonTokenId> ts = getPythonSequence(doc, start);
  78.109 -            if (ts != null) {
  78.110 -                int delta = ts.move(start);
  78.111 -                while (ts.moveNext()) {
  78.112 -                    Token<? extends PythonTokenId> token = ts.token();
  78.113 -                    PythonTokenId id = token.id();
  78.114 -                    if (id != PythonTokenId.NEWLINE && (!skipComments || id != PythonTokenId.COMMENT) && id != PythonTokenId.WHITESPACE) {
  78.115 -                        if (delta != 0) {
  78.116 -                            return OffsetRange.NONE;
  78.117 -                        }
  78.118 -                        start = ts.offset();
  78.119 -                        break;
  78.120 -                    } else {
  78.121 -                        delta = 0;
  78.122 -                    }
  78.123 -                }
  78.124 -            }
  78.125 -            int end = range.getEnd();
  78.126 -            ts = getPositionedSequence(doc, end);
  78.127 -            if (ts != null) {
  78.128 -                int delta = ts.move(end);
  78.129 -                while (delta > 0 ? ts.moveNext() : ts.movePrevious()) {
  78.130 -                    Token<? extends PythonTokenId> token = ts.token();
  78.131 -                    PythonTokenId id = token.id();
  78.132 -                    if (id != PythonTokenId.NEWLINE && (!skipComments || id != PythonTokenId.COMMENT) && id != PythonTokenId.WHITESPACE) {
  78.133 -                        if (delta != 0) {
  78.134 -                            return OffsetRange.NONE;
  78.135 -                        }
  78.136 -                        end = ts.offset() + token.length();
  78.137 -                        break;
  78.138 -                    } else {
  78.139 -                        delta = 0;
  78.140 -                    }
  78.141 -                }
  78.142 -            }
  78.143 -
  78.144 -            if (end < start) {
  78.145 -                return OffsetRange.NONE;
  78.146 -            }
  78.147 -
  78.148 -            return new OffsetRange(start, end);
  78.149 -        } finally {
  78.150 -            doc.readUnlock();
  78.151 -        }
  78.152 -    }
  78.153 -
  78.154 -    /** Find the ruby token sequence (in case it's embedded in something else at the top level */
  78.155 -    @SuppressWarnings("unchecked")
  78.156 -    public static TokenSequence<? extends PythonTokenId> getPythonSequence(BaseDocument doc, int offset) {
  78.157 -        TokenHierarchy<Document> th = TokenHierarchy.get((Document)doc);
  78.158 -        return getPythonSequence(th, offset);
  78.159 -    }
  78.160 -
  78.161 -    @SuppressWarnings("unchecked")
  78.162 -    public static TokenSequence<? extends PythonTokenId> getPythonSequence(TokenHierarchy<Document> th, int offset) {
  78.163 -        TokenSequence<? extends PythonTokenId> ts = th.tokenSequence(PythonTokenId.language());
  78.164 -
  78.165 -        if (ts == null) {
  78.166 -            // Possibly an embedding scenario such as an RHTML file
  78.167 -            // First try with backward bias true
  78.168 -            List<TokenSequence<?>> list = th.embeddedTokenSequences(offset, true);
  78.169 -
  78.170 -            for (TokenSequence t : list) {
  78.171 -                if (t.language() == PythonTokenId.language()) {
  78.172 -                    ts = t;
  78.173 -
  78.174 -                    break;
  78.175 -                }
  78.176 -            }
  78.177 -
  78.178 -            if (ts == null) {
  78.179 -                list = th.embeddedTokenSequences(offset, false);
  78.180 -
  78.181 -                for (TokenSequence t : list) {
  78.182 -                    if (t.language() == PythonTokenId.language()) {
  78.183 -                        ts = t;
  78.184 -
  78.185 -                        break;
  78.186 -                    }
  78.187 -                }
  78.188 -            }
  78.189 -        }
  78.190 -
  78.191 -        return ts;
  78.192 -    }
  78.193 -
  78.194 -    public static TokenSequence<? extends PythonTokenId> getPositionedSequence(BaseDocument doc, int offset) {
  78.195 -        return getPositionedSequence(doc, offset, true);
  78.196 -    }
  78.197 -
  78.198 -    public static TokenSequence<? extends PythonTokenId> getPositionedSequence(BaseDocument doc, int offset, boolean lookBack) {
  78.199 -        TokenSequence<? extends PythonTokenId> ts = getPythonSequence(doc, offset);
  78.200 -
  78.201 -        if (ts != null) {
  78.202 -            try {
  78.203 -                ts.move(offset);
  78.204 -            } catch (AssertionError e) {
  78.205 -                DataObject dobj = (DataObject)doc.getProperty(Document.StreamDescriptionProperty);
  78.206 -
  78.207 -                if (dobj != null) {
  78.208 -                    Exceptions.attachMessage(e, FileUtil.getFileDisplayName(dobj.getPrimaryFile()));
  78.209 -                }
  78.210 -
  78.211 -                throw e;
  78.212 -            }
  78.213 -
  78.214 -            if (!lookBack && !ts.moveNext()) {
  78.215 -                return null;
  78.216 -            } else if (lookBack && !ts.moveNext() && !ts.movePrevious()) {
  78.217 -                return null;
  78.218 -            }
  78.219 -
  78.220 -            /* TODO - allow Python inside strings
  78.221 -            if (ts.token().id() == PythonTokenId.STRING_LITERAL) {
  78.222 -            TokenSequence<? extends PythonStringTokenId> ets = ts.embedded(PythonStringTokenId.language());
  78.223 -            if (ets != null) {
  78.224 -            ets.move(offset);
  78.225 -            if ((!lookBack && ets.moveNext()) || (lookBack && ets.movePrevious())) {
  78.226 -            TokenSequence<?extends PythonTokenId> epts = ets.embedded(PythonTokenId.language());
  78.227 -            if (epts != null) {
  78.228 -            epts.move(offset);
  78.229 -            if (!lookBack && !epts.moveNext()) {
  78.230 -            return null;
  78.231 -            } else if (lookBack && !epts.moveNext() && !epts.movePrevious()) {
  78.232 -            return null;
  78.233 -            }
  78.234 -            return epts;
  78.235 -            }
  78.236 -            }
  78.237 -            }
  78.238 -            }
  78.239 -             */
  78.240 -
  78.241 -            return ts;
  78.242 -        }
  78.243 -
  78.244 -        return null;
  78.245 -    }
  78.246 -
  78.247 -    public static Token<? extends PythonTokenId> getToken(BaseDocument doc, int offset) {
  78.248 -        TokenSequence<? extends PythonTokenId> ts = getPositionedSequence(doc, offset);
  78.249 -
  78.250 -        if (ts != null) {
  78.251 -            return ts.token();
  78.252 -        }
  78.253 -
  78.254 -        return null;
  78.255 -    }
  78.256 -
  78.257 -    public static char getTokenChar(BaseDocument doc, int offset) {
  78.258 -        Token<? extends PythonTokenId> token = getToken(doc, offset);
  78.259 -
  78.260 -        if (token != null) {
  78.261 -            String text = token.text().toString();
  78.262 -
  78.263 -            if (text.length() > 0) { // Usually true, but I could have gotten EOF right?
  78.264 -
  78.265 -                return text.charAt(0);
  78.266 -            }
  78.267 -        }
  78.268 -
  78.269 -        return 0;
  78.270 -    }
  78.271 -
  78.272 -    public static Token<? extends PythonTokenId> findNextNonWsNonComment(TokenSequence<? extends PythonTokenId> ts) {
  78.273 -        return findNext(ts, Arrays.asList(PythonTokenId.WHITESPACE, PythonTokenId.NEWLINE, PythonTokenId.COMMENT));
  78.274 -    }
  78.275 -
  78.276 -    public static Token<? extends PythonTokenId> findPreviousNonWsNonComment(TokenSequence<? extends PythonTokenId> ts) {
  78.277 -        return findPrevious(ts, Arrays.asList(PythonTokenId.WHITESPACE, PythonTokenId.NEWLINE, PythonTokenId.COMMENT));
  78.278 -    }
  78.279 -
  78.280 -    public static Token<? extends PythonTokenId> findNext(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> ignores) {
  78.281 -        if (ignores.contains(ts.token().id())) {
  78.282 -            while (ts.moveNext() && ignores.contains(ts.token().id())) {
  78.283 -            }
  78.284 -        }
  78.285 -        return ts.token();
  78.286 -    }
  78.287 -
  78.288 -    public static Token<? extends PythonTokenId> findNextIncluding(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> includes) {
  78.289 -        while (ts.moveNext() && !includes.contains(ts.token().id())) {
  78.290 -        }
  78.291 -        return ts.token();
  78.292 -    }
  78.293 -
  78.294 -    public static Token<? extends PythonTokenId> findPreviousIncluding(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> includes) {
  78.295 -        while (ts.movePrevious() && !includes.contains(ts.token().id())) {
  78.296 -        }
  78.297 -        return ts.token();
  78.298 -    }
  78.299 -
  78.300 -    public static Token<? extends PythonTokenId> findPrevious(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> ignores) {
  78.301 -        if (ignores.contains(ts.token().id())) {
  78.302 -            while (ts.movePrevious() && ignores.contains(ts.token().id())) {
  78.303 -            }
  78.304 -        }
  78.305 -        return ts.token();
  78.306 -    }
  78.307 -
  78.308 -    static boolean skipParenthesis(TokenSequence<? extends PythonTokenId> ts) {
  78.309 -        return skipParenthesis(ts, false);
  78.310 -    }
  78.311 -
  78.312 -    /**
  78.313 -     * Tries to skip parenthesis
  78.314 -     */
  78.315 -    public static boolean skipParenthesis(TokenSequence<? extends PythonTokenId> ts, boolean back) {
  78.316 -        int balance = 0;
  78.317 -
  78.318 -        Token<? extends PythonTokenId> token = ts.token();
  78.319 -        if (token == null) {
  78.320 -            return false;
  78.321 -        }
  78.322 -
  78.323 -        TokenId id = token.id();
  78.324 -
  78.325 -        if (id == PythonTokenId.WHITESPACE || id == PythonTokenId.NEWLINE) {
  78.326 -            while ((back ? ts.movePrevious() : ts.moveNext()) && (ts.token().id() == PythonTokenId.WHITESPACE || ts.token().id() == PythonTokenId.NEWLINE)) {
  78.327 -            }
  78.328 -        }
  78.329 -
  78.330 -        // if current token is not left parenthesis
  78.331 -        if (ts.token().id() != (back ? PythonTokenId.RPAREN : PythonTokenId.LPAREN)) {
  78.332 -            return false;
  78.333 -        }
  78.334 -
  78.335 -        do {
  78.336 -            token = ts.token();
  78.337 -            id = token.id();
  78.338 -
  78.339 -            if (id == (back ? PythonTokenId.RPAREN : PythonTokenId.LPAREN)) {
  78.340 -                balance++;
  78.341 -            } else if (id == (back ? PythonTokenId.LPAREN : PythonTokenId.RPAREN)) {
  78.342 -                if (balance == 0) {
  78.343 -                    return false;
  78.344 -                } else if (balance == 1) {
  78.345 -                    //int length = ts.offset() + token.length();
  78.346 -                    if (back) {
  78.347 -                        ts.movePrevious();
  78.348 -                    } else {
  78.349 -                        ts.moveNext();
  78.350 -                    }
  78.351 -                    return true;
  78.352 -                }
  78.353 -
  78.354 -                balance--;
  78.355 -            }
  78.356 -        } while (back ? ts.movePrevious() : ts.moveNext());
  78.357 -
  78.358 -        return false;
  78.359 -    }
  78.360 -
  78.361 -    /** Search forwards in the token sequence until a token of type <code>down</code> is found */
  78.362 -    public static OffsetRange findFwd(BaseDocument doc, TokenSequence<? extends PythonTokenId> ts, TokenId up,
  78.363 -            TokenId down) {
  78.364 -        int balance = 0;
  78.365 -
  78.366 -        while (ts.moveNext()) {
  78.367 -            Token<? extends PythonTokenId> token = ts.token();
  78.368 -            TokenId id = token.id();
  78.369 -
  78.370 -            if (id == up) {
  78.371 -                balance++;
  78.372 -            } else if (id == down) {
  78.373 -                if (balance == 0) {
  78.374 -                    return new OffsetRange(ts.offset(), ts.offset() + token.length());
  78.375 -                }
  78.376 -
  78.377 -                balance--;
  78.378 -            }
  78.379 -        }
  78.380 -
  78.381 -        return OffsetRange.NONE;
  78.382 -    }
  78.383 -
  78.384 -    /** Search backwards in the token sequence until a token of type <code>up</code> is found */
  78.385 -    public static OffsetRange findBwd(BaseDocument doc, TokenSequence<? extends PythonTokenId> ts, TokenId up,
  78.386 -            TokenId down) {
  78.387 -        int balance = 0;
  78.388 -
  78.389 -        while (ts.movePrevious()) {
  78.390 -            Token<? extends PythonTokenId> token = ts.token();
  78.391 -            TokenId id = token.id();
  78.392 -
  78.393 -            if (id == up) {
  78.394 -                if (balance == 0) {
  78.395 -                    return new OffsetRange(ts.offset(), ts.offset() + token.length());
  78.396 -                }
  78.397 -
  78.398 -                balance++;
  78.399 -            } else if (id == down) {
  78.400 -                balance--;
  78.401 -            }
  78.402 -        }
  78.403 -
  78.404 -        return OffsetRange.NONE;
  78.405 -    }
  78.406 -
  78.407 -    /** Compute the balance of begin/end tokens on the line */
  78.408 -    public static int getLineBalance(BaseDocument doc, int offset, TokenId up, TokenId down) {
  78.409 -        try {
  78.410 -            int begin = Utilities.getRowStart(doc, offset);
  78.411 -            int end = Utilities.getRowEnd(doc, offset);
  78.412 -
  78.413 -            TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(doc, begin);
  78.414 -            if (ts == null) {
  78.415 -                return 0;
  78.416 -            }
  78.417 -
  78.418 -            ts.move(begin);
  78.419 -
  78.420 -            if (!ts.moveNext()) {
  78.421 -                return 0;
  78.422 -            }
  78.423 -
  78.424 -            int balance = 0;
  78.425 -
  78.426 -            do {
  78.427 -                Token<? extends PythonTokenId> token = ts.token();
  78.428 -                TokenId id = token.id();
  78.429 -
  78.430 -                if (id == up) {
  78.431 -                    balance++;
  78.432 -                } else if (id == down) {
  78.433 -                    balance--;
  78.434 -                }
  78.435 -            } while (ts.moveNext() && (ts.offset() <= end));
  78.436 -
  78.437 -            return balance;
  78.438 -        } catch (BadLocationException ble) {
  78.439 -            Exceptions.printStackTrace(ble);
  78.440 -
  78.441 -            return 0;
  78.442 -        }
  78.443 -    }
  78.444 -
  78.445 -    /**
  78.446 -     * The same as braceBalance but generalized to any pair of matching
  78.447 -     * tokens.
  78.448 -     * @param open the token that increses the count
  78.449 -     * @param close the token that decreses the count
  78.450 -     */
  78.451 -    public static int getTokenBalance(BaseDocument doc, TokenId open, TokenId close, int offset)
  78.452 -            throws BadLocationException {
  78.453 -        TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(doc, 0);
  78.454 -        if (ts == null) {
  78.455 -            return 0;
  78.456 -        }
  78.457 -
  78.458 -        // XXX Why 0? Why not offset?
  78.459 -        ts.moveIndex(0);
  78.460 -
  78.461 -        if (!ts.moveNext()) {
  78.462 -            return 0;
  78.463 -        }
  78.464 -
  78.465 -        int balance = 0;
  78.466 -
  78.467 -        do {
  78.468 -            Token t = ts.token();
  78.469 -
  78.470 -            if (t.id() == open) {
  78.471 -                balance++;
  78.472 -            } else if (t.id() == close) {
  78.473 -                balance--;
  78.474 -            }
  78.475 -        } while (ts.moveNext());
  78.476 -
  78.477 -        return balance;
  78.478 -    }
  78.479 -
  78.480 -    /**
  78.481 -     * Return true iff the line for the given offset is a JavaScript comment line.
  78.482 -     * This will return false for lines that contain comments (even when the
  78.483 -     * offset is within the comment portion) but also contain code.
  78.484 -     */
  78.485 -    public static boolean isCommentOnlyLine(BaseDocument doc, int offset)
  78.486 -            throws BadLocationException {
  78.487 -        int begin = Utilities.getRowFirstNonWhite(doc, offset);
  78.488 -
  78.489 -        if (begin == -1) {
  78.490 -            return false; // whitespace only
  78.491 -        }
  78.492 -
  78.493 -        Token<? extends PythonTokenId> token = PythonLexerUtils.getToken(doc, begin);
  78.494 -        if (token != null) {
  78.495 -            return token.id() == PythonTokenId.COMMENT;
  78.496 -        }
  78.497 -
  78.498 -        return false;
  78.499 -    }
  78.500 -
  78.501 -    /**
  78.502 -     * Back up to the first space character prior to the given offset - as long as
  78.503 -     * it's on the same line!  If there's only leading whitespace on the line up
  78.504 -     * to the lex offset, return the offset itself
  78.505 -     * @todo Rewrite this now that I have a separate newline token, EOL, that I can
  78.506 -     *   break on - no need to call Utilities.getRowStart.
  78.507 -     */
  78.508 -    public static int findSpaceBegin(BaseDocument doc, int lexOffset) {
  78.509 -        TokenSequence ts = getPythonSequence(doc, lexOffset);
  78.510 -        if (ts == null) {
  78.511 -            return lexOffset;
  78.512 -        }
  78.513 -        boolean allowPrevLine = false;
  78.514 -        int lineStart;
  78.515 -        try {
  78.516 -            lineStart = Utilities.getRowStart(doc, Math.min(lexOffset, doc.getLength()));
  78.517 -            int prevLast = lineStart - 1;
  78.518 -            if (lineStart > 0) {
  78.519 -                prevLast = Utilities.getRowLastNonWhite(doc, lineStart - 1);
  78.520 -                if (prevLast != -1) {
  78.521 -                    char c = doc.getText(prevLast, 1).charAt(0);
  78.522 -                    if (c == ',') {
  78.523 -                        // Arglist continuation? // TODO : check lexing
  78.524 -                        allowPrevLine = true;
  78.525 -                    }
  78.526 -                }
  78.527 -            }
  78.528 -            if (!allowPrevLine) {
  78.529 -                int firstNonWhite = Utilities.getRowFirstNonWhite(doc, lineStart);
  78.530 -                if (lexOffset <= firstNonWhite || firstNonWhite == -1) {
  78.531 -                    return lexOffset;
  78.532 -                }
  78.533 -            } else {
  78.534 -                // Make lineStart so small that Math.max won't cause any problems
  78.535 -                int firstNonWhite = Utilities.getRowFirstNonWhite(doc, lineStart);
  78.536 -                if (prevLast >= 0 && (lexOffset <= firstNonWhite || firstNonWhite == -1)) {
  78.537 -                    return prevLast + 1;
  78.538 -                }
  78.539 -                lineStart = 0;
  78.540 -            }
  78.541 -        } catch (BadLocationException ble) {
  78.542 -            Exceptions.printStackTrace(ble);
  78.543 -            return lexOffset;
  78.544 -        }
  78.545 -        ts.move(lexOffset);
  78.546 -        if (ts.moveNext()) {
  78.547 -            if (lexOffset > ts.offset()) {
  78.548 -                // We're in the middle of a token
  78.549 -                return Math.max((ts.token().id() == PythonTokenId.WHITESPACE) ? ts.offset() : lexOffset, lineStart);
  78.550 -            }
  78.551 -            while (ts.movePrevious()) {
  78.552 -                Token token = ts.token();
  78.553 -                if (token.id() != PythonTokenId.WHITESPACE) {
  78.554 -                    return Math.max(ts.offset() + token.length(), lineStart);
  78.555 -                }
  78.556 -            }
  78.557 -        }
  78.558 -
  78.559 -        return lexOffset;
  78.560 -    }
  78.561 -
  78.562 -     public static boolean isKeywordOrBuiltin(CharSequence name) {
  78.563 -        return PythonLexer.isKeywordOrBuiltin(name);
  78.564 -    }
  78.565 -}
    79.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/PythonStringLexer.java	Fri Sep 18 16:20:24 2015 -0500
    79.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.3 @@ -1,292 +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 org.netbeans.api.lexer.Token;
   79.50 -import org.netbeans.spi.lexer.Lexer;
   79.51 -import org.netbeans.spi.lexer.LexerInput;
   79.52 -import org.netbeans.spi.lexer.LexerRestartInfo;
   79.53 -import org.netbeans.spi.lexer.TokenFactory;
   79.54 -
   79.55 -/**
   79.56 - * A lexer for python strings. Highlights escape sequences, and recognizes
   79.57 - * doctest sections and highlights these as well.
   79.58 - *   http://docs.python.org/lib/module-doctest.html
   79.59 - *
   79.60 - * @todo Track whether strings are raw or not, and don't do escape sequence
   79.61 - *  highlighting in raw strings
   79.62 - *
   79.63 - * @author Tor Norbye
   79.64 - */
   79.65 -public class PythonStringLexer implements Lexer<PythonStringTokenId> {
   79.66 -    private static final int EOF = LexerInput.EOF;
   79.67 -    private final LexerInput input;
   79.68 -    private final TokenFactory<PythonStringTokenId> tokenFactory;
   79.69 -    private final boolean substituting;
   79.70 -
   79.71 -    /**
   79.72 -     * A Lexer for Python strings
   79.73 -     * @param substituting If true, handle substitution rules for double quoted strings, otherwise
   79.74 -     *    single quoted strings.
   79.75 -     */
   79.76 -    public PythonStringLexer(LexerRestartInfo<PythonStringTokenId> info, boolean substituting) {
   79.77 -        this.input = info.input();
   79.78 -        this.tokenFactory = info.tokenFactory();
   79.79 -        this.substituting = substituting;
   79.80 -        assert (info.state() == null); // passed argument always null
   79.81 -    }
   79.82 -
   79.83 -    @Override
   79.84 -    public Object state() {
   79.85 -        return null;
   79.86 -    }
   79.87 -
   79.88 -    @Override
   79.89 -    public Token<PythonStringTokenId> nextToken() {
   79.90 -        boolean inWord = false;
   79.91 -        while (true) {
   79.92 -            int ch = input.read();
   79.93 -
   79.94 -            switch (ch) {
   79.95 -            case EOF:
   79.96 -
   79.97 -                if (input.readLength() > 0) {
   79.98 -                    return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
   79.99 -                            input.readLength());
  79.100 -                } else {
  79.101 -                    return null;
  79.102 -                }
  79.103 -
  79.104 -            case '>':
  79.105 -                // Look for doctest:  \n, whitespace, >>>{embedded python}\n
  79.106 -                int initialReadLength = input.readLength();
  79.107 -                input.read();
  79.108 -                if (ch == '>') {
  79.109 -                    ch = input.read();
  79.110 -                    if (ch == '>') {
  79.111 -                        if (input.readLength() > 3) {
  79.112 -                            input.backup(3);
  79.113 -                            // Finish this token such that we can do a dedicated token for the ">>>" line.
  79.114 -                            return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
  79.115 -                                    input.readLength());
  79.116 -                        }
  79.117 -                        // Find end...
  79.118 -                        boolean nonempty = false;
  79.119 -                        while (true) {
  79.120 -                            ch = input.read();
  79.121 -                            if (ch == EOF) {
  79.122 -                                break;
  79.123 -                            } else if (ch == '\n') {
  79.124 -                                if (nonempty) {
  79.125 -                                    input.backup(1); // Don't include the \n
  79.126 -                                    return tokenFactory.createToken(PythonStringTokenId.EMBEDDED_PYTHON,
  79.127 -                                            input.readLength());
  79.128 -
  79.129 -                                }
  79.130 -                                break;
  79.131 -                            } else if (!Character.isWhitespace(ch)) {
  79.132 -                                nonempty = true;
  79.133 -                            }
  79.134 -                        }
  79.135 -                    }
  79.136 -                }
  79.137 -                if (input.readLength() > initialReadLength) {
  79.138 -                    input.backup(input.readLength() - initialReadLength);
  79.139 -                } else {
  79.140 -                    return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
  79.141 -                            input.readLength());
  79.142 -                }
  79.143 -                break;
  79.144 -
  79.145 -            case '\\':
  79.146 -
  79.147 -                if (input.readLength() > 1) { // already read some text
  79.148 -                    input.backup(1);
  79.149 -
  79.150 -                    return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
  79.151 -                            input.readLength());
  79.152 -                }
  79.153 -
  79.154 -                ch = input.read();
  79.155 -                if (ch == EOF) {
  79.156 -                    return tokenFactory.createToken(PythonStringTokenId.STRING_INVALID,
  79.157 -                            input.readLength());
  79.158 -                } else {
  79.159 -                    return tokenFactory.createToken(PythonStringTokenId.STRING_ESCAPE,
  79.160 -                            input.readLength());
  79.161 -                }
  79.162 -
  79.163 -            case 'f': // ftp:
  79.164 -            case 'm': // mailto:
  79.165 -            case 'w': // www.
  79.166 -            case 'h': { // http links. TODO: link:, ftp:, mailto:, and www.
  79.167 -
  79.168 -                if (inWord) {
  79.169 -                    break;
  79.170 -                }
  79.171 -
  79.172 -                int originalLength = input.readLength();
  79.173 -                boolean foundLinkBegin = false;
  79.174 -
  79.175 -                if (ch == 'h') { // http:
  79.176 -
  79.177 -                    if (input.read() == 't') {
  79.178 -                        if (input.read() == 't') {
  79.179 -                            if (input.read() == 'p') {
  79.180 -                                int r = input.read();
  79.181 -                                if (r == ':') {
  79.182 -                                    foundLinkBegin = true;
  79.183 -                                } else if (r == 's') {
  79.184 -                                    if (input.read() == ':') {
  79.185 -                                        foundLinkBegin = true;
  79.186 -                                    } else {
  79.187 -                                        input.backup(5);
  79.188 -                                    }
  79.189 -                                } else {
  79.190 -                                    input.backup(4);
  79.191 -                                }
  79.192 -                            } else {
  79.193 -                                input.backup(3);
  79.194 -                            }
  79.195 -                        } else {
  79.196 -                            input.backup(2);
  79.197 -                        }
  79.198 -                    } else {
  79.199 -                        input.backup(1);
  79.200 -                    }
  79.201 -                } else if (ch == 'f') { // ftp:
  79.202 -
  79.203 -                    if (input.read() == 't') {
  79.204 -                        if (input.read() == 'p') {
  79.205 -                            if (input.read() == ':') {
  79.206 -                                foundLinkBegin = true;
  79.207 -                            } else {
  79.208 -                                input.backup(3);
  79.209 -                            }
  79.210 -                        } else {
  79.211 -                            input.backup(2);
  79.212 -                        }
  79.213 -                    } else {
  79.214 -                        input.backup(1);
  79.215 -                    }
  79.216 -                } else if (ch == 'm') { // mailto:
  79.217 -
  79.218 -                    if (input.read() == 'a') {
  79.219 -                        if (input.read() == 'i') {
  79.220 -                            if (input.read() == 'l') {
  79.221 -                                if (input.read() == 't') {
  79.222 -                                    if (input.read() == 'o') {
  79.223 -                                        if (input.read() == ':') {
  79.224 -                                            foundLinkBegin = true;
  79.225 -                                        } else {
  79.226 -                                            input.backup(6);
  79.227 -                                        }
  79.228 -                                    } else {
  79.229 -                                        input.backup(5);
  79.230 -                                    }
  79.231 -                                } else {
  79.232 -                                    input.backup(4);
  79.233 -                                }
  79.234 -                            } else {
  79.235 -                                input.backup(3);
  79.236 -                            }
  79.237 -                        } else {
  79.238 -                            input.backup(2);
  79.239 -                        }
  79.240 -                    } else {
  79.241 -                        input.backup(1);
  79.242 -                    }
  79.243 -                } else if (ch == 'w') { // www.
  79.244 -
  79.245 -                    if (input.read() == 'w') {
  79.246 -                        if (input.read() == 'w') {
  79.247 -                            if (input.read() == '.') {
  79.248 -                                foundLinkBegin = true;
  79.249 -                            } else {
  79.250 -                                input.backup(3);
  79.251 -                            }
  79.252 -                        } else {
  79.253 -                            input.backup(2);
  79.254 -                        }
  79.255 -                    } else {
  79.256 -                        input.backup(1);
  79.257 -                    }
  79.258 -                }
  79.259 -
  79.260 -                if (foundLinkBegin) {
  79.261 -                    while (ch != EOF) {
  79.262 -                        ch = input.read();
  79.263 -
  79.264 -                        if ((ch == ']') || (ch == ')') || Character.isWhitespace(ch) ||
  79.265 -                                (ch == '\'') || (ch == '"')) {
  79.266 -                            input.backup(1);
  79.267 -
  79.268 -                            break;
  79.269 -                        }
  79.270 -                    }
  79.271 -
  79.272 -                    if (originalLength > 1) {
  79.273 -                        input.backup(input.readLengthEOF() - originalLength + 1);
  79.274 -
  79.275 -                        return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
  79.276 -                                input.readLength());
  79.277 -                    }
  79.278 -
  79.279 -                    if (input.readLength() > 2) {
  79.280 -                        return tokenFactory.createToken(PythonStringTokenId.URL,
  79.281 -                                input.readLength());
  79.282 -                    }
  79.283 -                }
  79.284 -                break;
  79.285 -            }
  79.286 -            }
  79.287 -
  79.288 -            inWord = Character.isJavaIdentifierPart(ch);
  79.289 -        }
  79.290 -    }
  79.291 -
  79.292 -    @Override
  79.293 -    public void release() {
  79.294 -    }
  79.295 -}
    80.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/PythonStringTokenId.java	Fri Sep 18 16:20:24 2015 -0500
    80.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.3 @@ -1,125 +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.Map;
   80.52 -
   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.api.lexer.TokenUtilities;
   80.59 -import org.netbeans.spi.lexer.LanguageEmbedding;
   80.60 -import org.netbeans.spi.lexer.LanguageHierarchy;
   80.61 -import org.netbeans.spi.lexer.Lexer;
   80.62 -import org.netbeans.spi.lexer.LexerRestartInfo;
   80.63 -
   80.64 -/**
   80.65 - *
   80.66 - * @author Tor Norbye
   80.67 - */
   80.68 -public enum PythonStringTokenId implements TokenId {
   80.69 -    STRING_TEXT("string"),
   80.70 -    STRING_ESCAPE("string-escape"),
   80.71 -    STRING_INVALID("string-escape-invalid"),
   80.72 -    URL("url"),
   80.73 -    EMBEDDED_PYTHON("string");
   80.74 -    private final String primaryCategory;
   80.75 -
   80.76 -    PythonStringTokenId() {
   80.77 -        this(null);
   80.78 -    }
   80.79 -
   80.80 -    PythonStringTokenId(String primaryCategory) {
   80.81 -        this.primaryCategory = primaryCategory;
   80.82 -    }
   80.83 -
   80.84 -    @Override
   80.85 -    public String primaryCategory() {
   80.86 -        return primaryCategory;
   80.87 -    }
   80.88 -    public static final Language<PythonStringTokenId> language =
   80.89 -            new LanguageHierarchy<PythonStringTokenId>() {
   80.90 -                @Override
   80.91 -                protected Collection<PythonStringTokenId> createTokenIds() {
   80.92 -                    return EnumSet.allOf(PythonStringTokenId.class);
   80.93 -                }
   80.94 -
   80.95 -                @Override
   80.96 -                protected Map<String, Collection<PythonStringTokenId>> createTokenCategories() {
   80.97 -                    return null; // no extra categories
   80.98 -                }
   80.99 -
  80.100 -                @Override
  80.101 -                protected Lexer<PythonStringTokenId> createLexer(
  80.102 -                        LexerRestartInfo<PythonStringTokenId> info) {
  80.103 -                    return new PythonStringLexer(info, true);
  80.104 -                }
  80.105 -
  80.106 -                @Override
  80.107 -                protected LanguageEmbedding<?> embedding(
  80.108 -                        Token<PythonStringTokenId> token, LanguagePath languagePath,
  80.109 -                        InputAttributes inputAttributes) {
  80.110 -                    PythonStringTokenId id = token.id();
  80.111 -
  80.112 -                    if (id == EMBEDDED_PYTHON && token.text() != null) {
  80.113 -                        return LanguageEmbedding.create(PythonTokenId.language(), 3, 0); // 3: Exlude ">>>" prefix
  80.114 -                    }
  80.115 -
  80.116 -                    return null; // No embedding
  80.117 -                }
  80.118 -
  80.119 -                @Override
  80.120 -                public String mimeType() {
  80.121 -                    return "text/x-python-string"; // NOI18N
  80.122 -                }
  80.123 -            }.language();
  80.124 -
  80.125 -    public static Language<PythonStringTokenId> language() {
  80.126 -        return language;
  80.127 -    }
  80.128 -}
    81.1 --- a/python.editor/src/org/netbeans/modules/python/editor/lexer/PythonTokenId.java	Fri Sep 18 16:20:24 2015 -0500
    81.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.3 @@ -1,206 +0,0 @@
    81.4 -/*
    81.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    81.6 - *
    81.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    81.8 - *
    81.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   81.10 - * Other names may be trademarks of their respective owners.
   81.11 - *
   81.12 - * The contents of this file are subject to the terms of either the GNU
   81.13 - * General Public License Version 2 only ("GPL") or the Common
   81.14 - * Development and Distribution License("CDDL") (collectively, the
   81.15 - * "License"). You may not use this file except in compliance with the
   81.16 - * License. You can obtain a copy of the License at
   81.17 - * http://www.netbeans.org/cddl-gplv2.html
   81.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   81.19 - * specific language governing permissions and limitations under the
   81.20 - * License.  When distributing the software, include this License Header
   81.21 - * Notice in each file and include the License file at
   81.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   81.23 - * particular file as subject to the "Classpath" exception as provided
   81.24 - * by Oracle in the GPL Version 2 section of the License file that
   81.25 - * accompanied this code. If applicable, add the following below the
   81.26 - * License Header, with the fields enclosed by brackets [] replaced by
   81.27 - * your own identifying information:
   81.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   81.29 - *
   81.30 - * Contributor(s):
   81.31 - *
   81.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   81.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   81.34 - * Microsystems, Inc. All Rights Reserved.
   81.35 - *
   81.36 - * If you wish your version of this file to be governed by only the CDDL
   81.37 - * or only the GPL Version 2, indicate your decision by adding
   81.38 - * "[Contributor] elects to include this software in this distribution
   81.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   81.40 - * single choice of license, a recipient has the option to distribute
   81.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   81.42 - * to extend the choice of license to its licensees as provided above.
   81.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   81.44 - * Version 2 license, then the option applies only if the new code is
   81.45 - * made subject to such option by the copyright holder.
   81.46 - */
   81.47 -package org.netbeans.modules.python.editor.lexer;
   81.48 -
   81.49 -import java.util.Collection;
   81.50 -import java.util.EnumSet;
   81.51 -import java.util.HashMap;
   81.52 -import java.util.Map;
   81.53 -import org.netbeans.api.lexer.InputAttributes;
   81.54 -import org.netbeans.api.lexer.Language;
   81.55 -import org.netbeans.api.lexer.LanguagePath;
   81.56 -import org.netbeans.api.lexer.Token;
   81.57 -import org.netbeans.api.lexer.TokenId;
   81.58 -import org.netbeans.modules.python.api.PythonMIMEResolver;
   81.59 -import org.netbeans.modules.python.editor.PythonUtils;
   81.60 -import org.netbeans.spi.lexer.LanguageEmbedding;
   81.61 -import org.netbeans.spi.lexer.LanguageHierarchy;
   81.62 -import org.netbeans.spi.lexer.Lexer;
   81.63 -import org.netbeans.spi.lexer.LexerInput;
   81.64 -import org.netbeans.spi.lexer.LexerRestartInfo;
   81.65 -
   81.66 -import org.netbeans.spi.lexer.TokenFactory;
   81.67 -import org.openide.filesystems.FileObject;
   81.68 -import static org.netbeans.modules.python.editor.lexer.PythonLexer.*;
   81.69 -
   81.70 -/**
   81.71 - * @todo add the rest of the tokens
   81.72 - *
   81.73 - * @author Martin Adamek
   81.74 - * @author alley
   81.75 - */
   81.76 -public enum PythonTokenId implements TokenId {
   81.77 -    ERROR(null, ERROR_CAT),
   81.78 -    IDENTIFIER(null, IDENTIFIER_CAT),
   81.79 -    INT_LITERAL(null, NUMBER_CAT),
   81.80 -    FLOAT_LITERAL(null, NUMBER_CAT),
   81.81 -    STRING_LITERAL(null, STRING_CAT),
   81.82 -    WHITESPACE(null, WHITESPACE_CAT),
   81.83 -    NEWLINE(null, WHITESPACE_CAT),
   81.84 -    DECORATOR(null, OPERATOR_CAT), // NOI18N
   81.85 -    //    CONTINUED_LINE(null, WHITESPACE_CAT), // NOI18N
   81.86 -    COMMENT(null, COMMENT_CAT),
   81.87 -    BUILTIN_FUNCTION(null, KEYWORD_CAT), // NOI18N
   81.88 -    LPAREN("(", SEPARATOR_CAT), // NOI18N
   81.89 -    RPAREN(")", SEPARATOR_CAT), // NOI18N
   81.90 -    LBRACE("{", SEPARATOR_CAT), // NOI18N
   81.91 -    RBRACE("}", SEPARATOR_CAT), // NOI18N
   81.92 -    LBRACKET("[", SEPARATOR_CAT), // NOI18N
   81.93 -    RBRACKET("]", SEPARATOR_CAT), // NOI18N
   81.94 -    STRING_BEGIN(null, STRING_CAT),
   81.95 -    STRING_END(null, STRING_CAT),
   81.96 -    // Cheating: out of laziness just map all keywords returning from Jython
   81.97 -    // into a single KEYWORD token; eventually we will have separate tokens
   81.98 -    // for each here such that the various helper methods for formatting,
   81.99 -    // smart indent, brace matching etc. can refer to specific keywords
  81.100 -    ANY_KEYWORD(null, KEYWORD_CAT),
  81.101 -    ANY_OPERATOR(null, OPERATOR_CAT),
  81.102 -    DEF("def", KEYWORD_CAT), // NOI18N
  81.103 -    CLASS("class", KEYWORD_CAT), // NOI18N
  81.104 -    IF("if", KEYWORD_CAT), // NOI18N
  81.105 -    ELSE("else", KEYWORD_CAT), // NOI18N
  81.106 -    ELIF("elif", KEYWORD_CAT), // NOI18N
  81.107 -    RAISE("raise", KEYWORD_CAT), // NOI18N
  81.108 -    PASS("pass", KEYWORD_CAT), // NOI18N
  81.109 -    RETURN("return", KEYWORD_CAT), // NOI18N
  81.110 -    EXCEPT("except", KEYWORD_CAT), // NOI18N
  81.111 -    FINALLY("finally", KEYWORD_CAT), // NOI18N
  81.112 -    IMPORT("import", KEYWORD_CAT), // NOI18N
  81.113 -    FROM("from", KEYWORD_CAT), // NOI18N
  81.114 -    TRUE("True", KEYWORD_CAT), // NOI18N
  81.115 -    FALSE("False", KEYWORD_CAT), // NOI18N
  81.116 -    NONE("None", KEYWORD_CAT), // NOI18N
  81.117 -    TRY("try", KEYWORD_CAT), // NOI18N
  81.118 -    DOT(".", OPERATOR_CAT), // NOI18N
  81.119 -    COMMA(",", OPERATOR_CAT), // NOI18N
  81.120 -    COLON(":", OPERATOR_CAT), // NOI18N
  81.121 -    ESC("\\", OPERATOR_CAT), // NOI18N
  81.122 -
  81.123 -    // Non-unary operators which indicate a line continuation if used at the end of a line
  81.124 -    NONUNARY_OP(null, OPERATOR_CAT);
  81.125 -    private final String fixedText;
  81.126 -    private final String primaryCategory;
  81.127 -
  81.128 -    PythonTokenId(String fixedText, String primaryCategory) {
  81.129 -        this.fixedText = fixedText;
  81.130 -        this.primaryCategory = primaryCategory;
  81.131 -    }
  81.132 -
  81.133 -    @Override
  81.134 -    public String primaryCategory() {
  81.135 -        return primaryCategory;
  81.136 -    }
  81.137 -
  81.138 -    public String fixedText() {
  81.139 -        return fixedText;
  81.140 -    }
  81.141 -    private static final Language<PythonTokenId> language =
  81.142 -            new LanguageHierarchy<PythonTokenId>() {
  81.143 -                @Override
  81.144 -                protected String mimeType() {
  81.145 -                    return PythonMIMEResolver.PYTHON_MIME_TYPE;
  81.146 -                }
  81.147 -
  81.148 -                @Override
  81.149 -                protected Collection<PythonTokenId> createTokenIds() {
  81.150 -                    return EnumSet.allOf(PythonTokenId.class);
  81.151 -                }
  81.152 -
  81.153 -                @Override
  81.154 -                protected Map<String, Collection<PythonTokenId>> createTokenCategories() {
  81.155 -                    Map<String, Collection<PythonTokenId>> cats =
  81.156 -                            new HashMap<>();
  81.157 -                    return cats;
  81.158 -                }
  81.159 -
  81.160 -                @Override
  81.161 -                protected Lexer<PythonTokenId> createLexer(LexerRestartInfo<PythonTokenId> info) {
  81.162 -                    FileObject fileObject = (FileObject)info.getAttributeValue(FileObject.class);
  81.163 -                    final TokenFactory<PythonTokenId> tokenFactory = info.tokenFactory();
  81.164 -                    final LexerInput input = info.input();
  81.165 -                    // Lex .rst files just as literal strings
  81.166 -                    if (fileObject != null && PythonUtils.isRstFile(fileObject)) {
  81.167 -                        return new Lexer<PythonTokenId>() {
  81.168 -                            @Override
  81.169 -                            public Token<PythonTokenId> nextToken() {
  81.170 -                                if (input.read() == LexerInput.EOF) {
  81.171 -                                    return null;
  81.172 -                                }
  81.173 -                                while (input.read() != LexerInput.EOF) {
  81.174 -                                    ;
  81.175 -                                }
  81.176 -                                return tokenFactory.createToken(PythonTokenId.STRING_LITERAL, input.readLength());
  81.177 -                            }
  81.178 -
  81.179 -                            @Override
  81.180 -                            public Object state() {
  81.181 -                                return null;
  81.182 -                            }
  81.183 -
  81.184 -                            @Override
  81.185 -                            public void release() {
  81.186 -                            }
  81.187 -                        };
  81.188 -                    }
  81.189 -                    return new PythonLexer(info);
  81.190 -                }
  81.191 -
  81.192 -                @Override
  81.193 -                protected LanguageEmbedding<?> embedding(Token<PythonTokenId> token,
  81.194 -                        LanguagePath languagePath, InputAttributes inputAttributes) {
  81.195 -                    PythonTokenId id = token.id();
  81.196 -                    if (id == STRING_LITERAL) {
  81.197 -                        return LanguageEmbedding.create(PythonStringTokenId.language, 0, 0);
  81.198 -                    } else if (id == COMMENT) {
  81.199 -                        return LanguageEmbedding.create(PythonCommentTokenId.language(), 1, 0);
  81.200 -                    }
  81.201 -
  81.202 -                    return null; // No embedding
  81.203 -                }
  81.204 -            }.language();
  81.205 -
  81.206 -    public static Language<PythonTokenId> language() {
  81.207 -        return language;
  81.208 -    }
  81.209 -}
    82.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/Bundle.properties	Fri Sep 18 16:20:24 2015 -0500
    82.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.3 @@ -1,284 +0,0 @@
    82.4 -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    82.5 -#
    82.6 -# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    82.7 -#
    82.8 -# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    82.9 -# Other names may be trademarks of their respective owners.
   82.10 -#
   82.11 -# The contents of this file are subject to the terms of either the GNU
   82.12 -# General Public License Version 2 only ("GPL") or the Common
   82.13 -# Development and Distribution License("CDDL") (collectively, the
   82.14 -# "License"). You may not use this file except in compliance with the
   82.15 -# License. You can obtain a copy of the License at
   82.16 -# http://www.netbeans.org/cddl-gplv2.html
   82.17 -# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   82.18 -# specific language governing permissions and limitations under the
   82.19 -# License.  When distributing the software, include this License Header
   82.20 -# Notice in each file and include the License file at
   82.21 -# nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   82.22 -# particular file as subject to the "Classpath" exception as provided
   82.23 -# by Oracle in the GPL Version 2 section of the License file that
   82.24 -# accompanied this code. If applicable, add the following below the
   82.25 -# License Header, with the fields enclosed by brackets [] replaced by
   82.26 -# your own identifying information:
   82.27 -# "Portions Copyrighted [year] [name of copyright owner]"
   82.28 -#
   82.29 -# Contributor(s):
   82.30 -#
   82.31 -# The Original Software is NetBeans. The Initial Developer of the Original
   82.32 -# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   82.33 -# Microsystems, Inc. All Rights Reserved.
   82.34 -#
   82.35 -# If you wish your version of this file to be governed by only the CDDL
   82.36 -# or only the GPL Version 2, indicate your decision by adding
   82.37 -# "[Contributor] elects to include this software in this distribution
   82.38 -# under the [CDDL or GPL Version 2] license." If you do not indicate a
   82.39 -# single choice of license, a recipient has the option to distribute
   82.40 -# your version of this file under either the CDDL, the GPL Version 2 or
   82.41 -# to extend the choice of license to its licensees as provided above.
   82.42 -# However, if you add GPL Version 2 code and therefore, elected the GPL
   82.43 -# Version 2 license, then the option applies only if the new code is
   82.44 -# made subject to such option by the copyright holder.
   82.45 -
   82.46 -# Formating options
   82.47 -
   82.48 -LBL_TabsAndIndents=Tabs and Indents
   82.49 -LBL_CodeGeneration=Code Generation
   82.50 -LBL_Alignment=Alignment
   82.51 -LBL_Wrapping=Wrapping
   82.52 -LBL_BlankLines=Blank Lines
   82.53 -LBL_Spaces=Spaces
   82.54 -LBL_Imports=Imports
   82.55 -
   82.56 -LBL_bp_SAME_LINE=Same Line
   82.57 -LBL_bp_NEW_LINE=New Line
   82.58 -LBL_bp_NEW_LINE_HALF_INDENTED=New Line Half Indented
   82.59 -LBL_bp_NEW_LINE_INDENTED= New Line Indented
   82.60 -    
   82.61 -LBL_bg_GENERATE=Generate
   82.62 -LBL_bg_LEAVE_ALONE=Leave Alone
   82.63 -LBL_bg_ELIMINATE=Eliminate
   82.64 -       
   82.65 -LBL_wrp_WRAP_ALWAYS=Always
   82.66 -LBL_wrp_WRAP_IF_LONG=If Long
   82.67 -LBL_wrp_WRAP_NEVER=Never
   82.68 -
   82.69 -LBL_imp_COMMENT_OUT=Comment Out
   82.70 -LBL_imp_LEAVE_ALONE=Leave Alone
   82.71 -LBL_imp_DELETE=Delete
   82.72 -
   82.73 -LBL_ExpandTabToSpaces=&Expand Tab to Spaces
   82.74 -LBL_TabSize=&Tab Size:
   82.75 -LBL_IndentSize=&Indentation Size:
   82.76 -LBL_ContinuationIndentSize=&Continuation Indentation Size:
   82.77 -LBL_LabelIndent=&Label Indentation\:
   82.78 -LBL_AbsoluteLabelIndent=&Absolute Label Indentation
   82.79 -LBL_IndentTopLevelClassMemberts=Indent Top Level Class &Members
   82.80 -LBL_AddLeadingStarInComment=Add Leading Star In Comment
   82.81 -LBL_RightMargin=&Right Margin:
   82.82 -
   82.83 -LBL_Naming=Naming\:
   82.84 -LBL_PreferLongerNames=Prefer Longer Names
   82.85 -LBL_Prefix=Prefix
   82.86 -LBL_Suffix=Suffix
   82.87 -LBL_Field=Field\:
   82.88 -LBL_StaticField=Static Field\:
   82.89 -LBL_Parameter=Parameter\:
   82.90 -LBL_LocalVariable=Local Variable\:
   82.91 -LBL_Misc=Misc\:
   82.92 -LBL_QualifyFieldAccess=Qualify Field Access
   82.93 -LBL_UseIsForBooleanGetters=Use Is For Boolean Getters
   82.94 -LBL_AddOverrideAnnotation=Add Override Annotation
   82.95 -LBL_FinalMofier=Final Modifier\:
   82.96 -LBL_ParametersFinal=Make Generated Parameters Final
   82.97 -LBL_LocalVariablesFinal=Make Generated Local variables Final
   82.98 -LBL_ImportOredering=Import Ordering\:
   82.99 -LBL_ImportUp=Move Up
  82.100 -LBL_ImportDown=Move Down
  82.101 -LBL_blBeforePackage=Before &Package\:
  82.102 -LBL_blAfterPackage=After P&ackage\:
  82.103 -LBL_blBeforeImports=Before &Imports\:
  82.104 -LBL_blAfterImports=After I&mports\:
  82.105 -LBL_blBeforeClass=Before &Class\:
  82.106 -LBL_blAfterClass=After C&lass\:
  82.107 -LBL_blAfterClassHeader=After Class &Header\:
  82.108 -LBL_blBeforeFields=Before &Field\:
  82.109 -LBL_blAfterFields=After Fi&eld\:
  82.110 -LBL_blBeforeMethods=Before &Method\:
  82.111 -LBL_blAfterMethods=After Me&thod\:
  82.112 -
  82.113 -LBL_BeforeKeywords=Before Keywords
  82.114 -LBL_spaceBeforeWhile="while"
  82.115 -LBL_spaceBeforeElse="else"
  82.116 -LBL_spaceBeforeCatch="catch"
  82.117 -LBL_spaceBeforeFinally="finally"
  82.118 -
  82.119 -LBL_BeforeParentheses=Before Parentheses
  82.120 -LBL_spaceBeforeMethodDeclParen=Method Declaration
  82.121 -LBL_spaceBeforeMethodCallParen=Method Call
  82.122 -LBL_spaceBeforeIfParen="if"
  82.123 -LBL_spaceBeforeForParen="for"
  82.124 -LBL_spaceBeforeWhileParen="while"
  82.125 -LBL_spaceBeforeCatchParen="catch"
  82.126 -LBL_spaceBeforeSwitchParen="switch"
  82.127 -LBL_spaceBeforeSynchronizedParen="synchronized"
  82.128 -LBL_spaceBeforeAnnotationParen=Annotation Parameters
  82.129 -
  82.130 -LBL_AroundOperators=Around Operators
  82.131 -LBL_spaceAroundUnaryOps=Unary Operators
  82.132 -LBL_spaceAroundBinaryOps=Binary Operators
  82.133 -LBL_spaceAroundTernaryOps=Ternary Operators
  82.134 -LBL_spaceAroundAssignOps=Assignment Operators
  82.135 -
  82.136 -LBL_BeforeLeftBraces=Before Left Braces
  82.137 -LBL_spaceBeforeClassDeclLeftBrace=Class Declaration
  82.138 -LBL_spaceBeforeMethodDeclLeftBrace=Method Declaration
  82.139 -LBL_spaceBeforeIfLeftBrace="if"
  82.140 -LBL_spaceBeforeElseLeftBrace="else"
  82.141 -LBL_spaceBeforeWhileLeftBrace="while"
  82.142 -LBL_spaceBeforeForLeftBrace="for"
  82.143 -LBL_spaceBeforeDoLeftBrace="do"
  82.144 -LBL_spaceBeforeSwitchLeftBrace="switch"
  82.145 -LBL_spaceBeforeTryLeftBrace="try"
  82.146 -LBL_spaceBeforeCatchLeftBrace="catch"
  82.147 -LBL_spaceBeforeFinallyLeftBrace="finally"
  82.148 -LBL_spaceBeforeSynchronizedLeftBrace="synchronized"
  82.149 -LBL_spaceBeforeStaticInitLeftBrace=Static Initializer
  82.150 -LBL_spaceBeforeArrayInitLeftBrace=Array Initializer
  82.151 -
  82.152 -LBL_WithinParentheses=Within Parentheses
  82.153 -LBL_spaceWithinParens=Parentheses
  82.154 -LBL_spaceWithinMethodDeclParens=Method Declaration
  82.155 -LBL_spaceWithinMethodCallParens=Method Call
  82.156 -LBL_spaceWithinIfParens="if"
  82.157 -LBL_spaceWithinForParens="for"
  82.158 -LBL_spaceWithinWhileParens="while"
  82.159 -LBL_spaceWithinSwitchParens="switch"
  82.160 -LBL_spaceWithinCatchParens="catch"
  82.161 -LBL_spaceWithinSynchronizedParens="synchronized"
  82.162 -LBL_spaceWithinTypeCastParens=Type Cast
  82.163 -LBL_spaceWithinAnnotationParens=Annotation
  82.164 -LBL_spaceWithinBraces=Braces
  82.165 -LBL_spaceWithinArrayInitBrackets=Array Initializer Brackets
  82.166 -
  82.167 -LBL_Other=Other
  82.168 -LBL_spaceBeforeComma=Before Comma
  82.169 -LBL_spaceAfterComma=After Comma
  82.170 -LBL_spaceBeforeSemi=Before Semicolon
  82.171 -LBL_spaceAfterSemi=After Semicolon
  82.172 -LBL_spaceBeforeColon=Before Colon
  82.173 -LBL_spaceAfterColon=After Colon
  82.174 -LBL_spaceAfterTypeCast=After Type Cast
  82.175 -LBL_wrp_extendsImplementsKeyword=&Extends/Implements Keyword\: 
  82.176 -LBL_wrp_extendsImplementsList=E&xtends/Implements List\:
  82.177 -LBL_wrp_methodParameters=Method &Parameters\:
  82.178 -LBL_wrp_throwsKeyword=&Throws Keyword\:
  82.179 -LBL_wrp_throwsList=Th&rows List\:
  82.180 -LBL_wrp_methodCallArgs=Method Call &Arguments\:
  82.181 -LBL_wrp_annotationArgs=Annotation Arg&uments\:
  82.182 -LBL_wrp_chainedMethodCalls=C&hained Method Calls\:
  82.183 -LBL_wrp_arrayInit=Array Initiali&zer\:
  82.184 -LBL_wrp_for=&For\:
  82.185 -LBL_wrp_forStatement=F&or Statement\:
  82.186 -LBL_wrp_ifStatement=&If Statement\:
  82.187 -LBL_wrp_whileStatement=&While Statement\:
  82.188 -LBL_wrp_doWhileStatement=&Do ... While Statement
  82.189 -LBL_wrp_assert=&Assert\:
  82.190 -LBL_wrp_enumConstants=Enum &Constants\:
  82.191 -LBL_wrp_annotations=A&nnotations\:
  82.192 -LBL_wrp_binaryOps=&Binary Operators\:
  82.193 -LBL_wrp_ternaryOps=Ternar&y Operators\:
  82.194 -LBL_wrp_assignOps=Assi&gnment Operators\:
  82.195 -
  82.196 -LBL_br_bracesPlacement=Braces Placement
  82.197 -LBL_br_bracesGeneration=Braces Generation
  82.198 -LBL_al_newLines=New Lines
  82.199 -LBL_al_multilineAlignment=Multiline Alignment
  82.200 -LBL_nl_Else="&else"
  82.201 -LBL_nl_While="w&hile"
  82.202 -LBL_nl_Catch="c&atch"
  82.203 -LBL_nl_Finally="finall&y"
  82.204 -LBL_nl_Modifiers=after modifie&rs
  82.205 -LBL_am_MethodParams=Method &Parameters
  82.206 -LBL_am_CallArgs=Method Call Arg&uments
  82.207 -LBL_am_AnnotationArgs=&Annotation Arguments
  82.208 -LBL_an_Implements=I&mplements List
  82.209 -LBL_am_Throws=&Throws List
  82.210 -LBL_am_Paren=Parenthesize&d
  82.211 -LBL_am_BinaryOp=&Binary Operators
  82.212 -LBL_am_TernaryOp=Ter&nary Operators
  82.213 -LBL_am_Assign=Assi&gnment
  82.214 -LBL_am_For=&For
  82.215 -LBL_am_ArrayInit=Array Initiali&zer
  82.216 -
  82.217 -LBL_IndentCasesFromSwitch=Indent Case Statements In &Switch
  82.218 -
  82.219 -# Following entries (marked) as samples are used as examples in the formating
  82.220 -# options. It is highly discourage to localize them unless absolutely necessary.
  82.221 -
  82.222 -SAMPLE_Default=public class ClassA extends Object implements InterfaceA, InterfaceB, InterfaceC
  82.223 -SAMPLE_TabsIndents=public class ClassA extends Object implements InterfaceA, InterfaceB, InterfaceC {
  82.224 -SAMPLE_AlignBraces=@Anno(paramA="a Value", paramB="bValue")\n
  82.225 -SAMPLE_Wrapping=@Anno(paramA="a Value", paramB="bValue")
  82.226 -SAMPLE_BlankLines=package org.netbeans.samples;
  82.227 -
  82.228 -SAMPLE_Imports=\
  82.229 -# Copyright 2008\n\
  82.230 -"""My Module"""\n\
  82.231 -\n\
  82.232 -import sys\n\
  82.233 -import wsgiref.handlers\n\
  82.234 -from google.appengine.ext.webapp.util import run_wsgi_app\n\
  82.235 -from google.appengine.ext import webapp\n\
  82.236 -from google.appengine.ext import db\n\
  82.237 -import os\n\
  82.238 -\n\
  82.239 -\n\
  82.240 -from google.appengine.api import users\n\
  82.241 -import google.appengine.api.test\n\
  82.242 -from google.appengine.api import users\n\
  82.243 -\n\
  82.244 -from google.appengine.api import users\n\
  82.245 -from google.appengine.api import users\n\
  82.246 -import string\n\
  82.247 -from google.appengine.ext.webapp import template as FooBar\n\
  82.248 -from google.appengine.ext.webapp.util import login_required\n\
  82.249 -import random\n\
  82.250 -import datetime\n
  82.251 -
  82.252 -#\n\
  82.253 -#new_str = swapcase("foo")
  82.254 -
  82.255 -
  82.256 -# Newlines on the following line since space prefixes are ignored by the .properties loader
  82.257 -SAMPLE_Spaces=\
  82.258 -def func( arg1 ,arg2 ,\
  82.259 -\n  arg3 = 3,  arg  =  4):\
  82.260 -\n\
  82.261 -\n  if pos!=-1 and optval[ pos-1 ].isspace():\
  82.262 -\n      x=5+2\
  82.263 -\n\
  82.264 -\nmodeDict = { 'r':'rb','w':'wb', \\\
  82.265 -\n   'a' : 'r+b' }\
  82.266 -\nx = 2; y=3 ; z    =      5\n
  82.267 -
  82.268 -
  82.269 -nlFinallyCheckBox1.text="finall&y"
  82.270 -
  82.271 -
  82.272 -AN_Preview=Preview
  82.273 -AD_Preview=Preview
  82.274 -FmtImports.formatImportsCb.text=Organize Imports during formatting
  82.275 -FmtImports.removeDuplicateCb.text=Remove Duplicate Imports
  82.276 -FmtImports.systemLibsCb.text=Separate out system libraries
  82.277 -FmtImports.onePerLineCb.text=Prefer one import per line
  82.278 -FmtImports.cleanupLabel.text=Unused imports:
  82.279 -FmtImports.preferSymbols.text=Prefer symbol imports
  82.280 -FmtImports.sortImportsCb.text=Sort Alphabetically
  82.281 -FmtSpaces.addAroundOp.text=Add spaces around operators
  82.282 -FmtSpaces.removeInParam.text=But remove in parameter assignments
  82.283 -FmtSpaces.removeInParen.text=Remove spaces inside ( ), { }, and [ ]
  82.284 -FmtSpaces.addAfterComma.text=Add spaces after commas
  82.285 -FmtSpaces.removeBeforeSep.text=Remove spaces before separators ( : , ; )
  82.286 -FmtSpaces.collapseSpacesCb.text=Collapse multiple spaces
  82.287 -FmtImports.sepFromImpCb.text=Separate "from" and "import" statements
    83.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/CodeStyle.java	Fri Sep 18 16:20:24 2015 -0500
    83.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.3 @@ -1,737 +0,0 @@
    83.4 -/*
    83.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    83.6 - *
    83.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    83.8 - *
    83.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   83.10 - * Other names may be trademarks of their respective owners.
   83.11 - *
   83.12 - * The contents of this file are subject to the terms of either the GNU
   83.13 - * General Public License Version 2 only ("GPL") or the Common
   83.14 - * Development and Distribution License("CDDL") (collectively, the
   83.15 - * "License"). You may not use this file except in compliance with the
   83.16 - * License. You can obtain a copy of the License at
   83.17 - * http://www.netbeans.org/cddl-gplv2.html
   83.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   83.19 - * specific language governing permissions and limitations under the
   83.20 - * License.  When distributing the software, include this License Header
   83.21 - * Notice in each file and include the License file at
   83.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   83.23 - * particular file as subject to the "Classpath" exception as provided
   83.24 - * by Oracle in the GPL Version 2 section of the License file that
   83.25 - * accompanied this code. If applicable, add the following below the
   83.26 - * License Header, with the fields enclosed by brackets [] replaced by
   83.27 - * your own identifying information:
   83.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   83.29 - *
   83.30 - * Contributor(s):
   83.31 - *
   83.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   83.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   83.34 - * Microsystems, Inc. All Rights Reserved.
   83.35 - *
   83.36 - * If you wish your version of this file to be governed by only the CDDL
   83.37 - * or only the GPL Version 2, indicate your decision by adding
   83.38 - * "[Contributor] elects to include this software in this distribution
   83.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   83.40 - * single choice of license, a recipient has the option to distribute
   83.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   83.42 - * to extend the choice of license to its licensees as provided above.
   83.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   83.44 - * Version 2 license, then the option applies only if the new code is
   83.45 - * made subject to such option by the copyright holder.
   83.46 - */
   83.47 -package org.netbeans.modules.python.editor.options;
   83.48 -
   83.49 -import java.util.prefs.Preferences;
   83.50 -import javax.swing.text.Document;
   83.51 -import org.netbeans.modules.editor.indent.spi.CodeStylePreferences;
   83.52 -
   83.53 -import org.openide.filesystems.FileObject;
   83.54 -import static org.netbeans.modules.python.editor.options.FmtOptions.*;
   83.55 -
   83.56 -/** 
   83.57 - *  XXX make sure the getters get the defaults from somewhere
   83.58 - *  XXX add support for profiles
   83.59 - *  XXX get the preferences node from somewhere else in odrer to be able not to
   83.60 - *      use the getters and to be able to write to it.
   83.61 - * 
   83.62 - * @author Dusan Balek
   83.63 - */
   83.64 -public final class CodeStyle {
   83.65 -    static {
   83.66 -        FmtOptions.codeStyleProducer = new Producer();
   83.67 -    }
   83.68 -    private Preferences preferences;
   83.69 -
   83.70 -    private CodeStyle(Preferences preferences) {
   83.71 -        this.preferences = preferences;
   83.72 -    }
   83.73 -
   83.74 -//    /**
   83.75 -//     * Gets <code>CodeStyle</code> for files in the given project.
   83.76 -//     *
   83.77 -//     * <p>Please see the other two <code>getDefault</code> methods as they are
   83.78 -//     * the preferred way of getting <code>CodeStyle</code>.
   83.79 -//     *
   83.80 -//     * @param project The project to get the <code>CodeStyle</code> for.
   83.81 -//     * @return The current code style that would be used by documents opened
   83.82 -//     *   from files belonging to the <code>project</code>.
   83.83 -//     *
   83.84 -//     * @deprecated Please use {@link #getDefault(javax.swing.text.Document)}
   83.85 -//     *   or {@link #getDefault(org.openide.filesystems.FileObject)} respectively.
   83.86 -//     */
   83.87 -//    @Deprecated
   83.88 -//    public static CodeStyle getDefault(Project project) {
   83.89 -//        return getDefault(project.getProjectDirectory());
   83.90 -//    }
   83.91 -    /**
   83.92 -     * Gets <code>CodeStyle</code> for the given file. If you have a document
   83.93 -     * instance you should use the {@link #getDefault(javax.swing.text.Document)}
   83.94 -     * method.
   83.95 -     * 
   83.96 -     * @param file The file to get the <code>CodeStyle</code> for.
   83.97 -     * @return The current code style that would be used by a document if the
   83.98 -     *   <code>file</code> were opened in the editor.
   83.99 -     *
  83.100 -     * @since 0.39
  83.101 -     */
  83.102 -    public synchronized static CodeStyle getDefault(FileObject file) {
  83.103 -        Preferences prefs = CodeStylePreferences.get(file).getPreferences();
  83.104 -        return FmtOptions.codeStyleProducer.create(prefs);
  83.105 -    }
  83.106 -
  83.107 -    /**
  83.108 -     * Gets <code>CodeStyle</code> for the given document. This is the preferred
  83.109 -     * method of getting <code>CodeStyle</code>. If you don't have a document
  83.110 -     * you can use {@link #getDefault(org.openide.filesystems.FileObject)} method instead.
  83.111 -     *
  83.112 -     * @param doc The document to get the <code>CodeStyle</code> for.
  83.113 -     * @return The current code style used by a document. This is the code style that
  83.114 -     *   will be used when formatting the document or generating new code.
  83.115 -     * 
  83.116 -     * @since 0.39
  83.117 -     */
  83.118 -    public synchronized static CodeStyle getDefault(Document doc) {
  83.119 -        Preferences prefs = CodeStylePreferences.get(doc).getPreferences();
  83.120 -        return FmtOptions.codeStyleProducer.create(prefs);
  83.121 -    }
  83.122 -
  83.123 -    // General tabs and indents ------------------------------------------------
  83.124 -    public boolean expandTabToSpaces() {
  83.125 -//        System.out.println("~~~ expand-tabs=" + preferences.get(SimpleValueNames.EXPAND_TABS, null));
  83.126 -        return preferences.getBoolean(expandTabToSpaces, getDefaultAsBoolean(expandTabToSpaces));
  83.127 -    }
  83.128 -
  83.129 -    public int getTabSize() {
  83.130 -//        System.out.println("~~~ tab-size=" + preferences.get(SimpleValueNames.TAB_SIZE, null));
  83.131 -        return preferences.getInt(tabSize, getDefaultAsInt(tabSize));
  83.132 -    }
  83.133 -
  83.134 -    public int getIndentSize() {
  83.135 -//        System.out.println("~~~ indent-shift-width=" + preferences.get(SimpleValueNames.INDENT_SHIFT_WIDTH, null));
  83.136 -        int indentLevel = preferences.getInt(indentSize, getDefaultAsInt(indentSize));
  83.137 -
  83.138 -        if (indentLevel <= 0) {
  83.139 -//            System.out.println("~~~ expand-tabs=" + preferences.get(SimpleValueNames.EXPAND_TABS, null));
  83.140 -            boolean expandTabs = preferences.getBoolean(expandTabToSpaces, getDefaultAsBoolean(expandTabToSpaces));
  83.141 -            if (expandTabs) {
  83.142 -//                System.out.println("~~~ spaces-per-tab=" + preferences.get(SimpleValueNames.SPACES_PER_TAB, null));
  83.143 -                indentLevel = preferences.getInt(spacesPerTab, getDefaultAsInt(spacesPerTab));
  83.144 -            } else {
  83.145 -//                System.out.println("~~~ tab-size=" + preferences.get(SimpleValueNames.TAB_SIZE, null));
  83.146 -                indentLevel = preferences.getInt(tabSize, getDefaultAsInt(tabSize));
  83.147 -            }
  83.148 -        }
  83.149 -
  83.150 -        return indentLevel;
  83.151 -    }
  83.152 -
  83.153 -    public int getContinuationIndentSize() {
  83.154 -        return preferences.getInt(continuationIndentSize, getDefaultAsInt(continuationIndentSize));
  83.155 -    }
  83.156 -
  83.157 -    public int getLabelIndent() {
  83.158 -        return preferences.getInt(labelIndent, getDefaultAsInt(labelIndent));
  83.159 -    }
  83.160 -
  83.161 -    public boolean absoluteLabelIndent() {
  83.162 -        return preferences.getBoolean(absoluteLabelIndent, getDefaultAsBoolean(absoluteLabelIndent));
  83.163 -    }
  83.164 -
  83.165 -    public boolean indentTopLevelClassMembers() {
  83.166 -        return preferences.getBoolean(indentTopLevelClassMembers, getDefaultAsBoolean(indentTopLevelClassMembers));
  83.167 -    }
  83.168 -
  83.169 -    public boolean indentCasesFromSwitch() {
  83.170 -        return preferences.getBoolean(indentCasesFromSwitch, getDefaultAsBoolean(indentCasesFromSwitch));
  83.171 -    }
  83.172 -
  83.173 -    public int getRightMargin() {
  83.174 -        return preferences.getInt(rightMargin, getDefaultAsInt(rightMargin));
  83.175 -    }
  83.176 -
  83.177 -    /*
  83.178 -    public boolean addLeadingStarInComment() {
  83.179 -    return preferences.getBoolean(addLeadingStarInComment, getDefaultAsBoolean(addLeadingStarInComment));
  83.180 -    }
  83.181 -
  83.182 -    // Code generation ---------------------------------------------------------
  83.183 -    
  83.184 -    public boolean preferLongerNames() {
  83.185 -    return preferences.getBoolean(preferLongerNames, getDefaultAsBoolean(preferLongerNames));
  83.186 -    }
  83.187 -
  83.188 -    public String getFieldNamePrefix() {
  83.189 -    return preferences.get(fieldNamePrefix, getDefaultAsString(fieldNamePrefix));
  83.190 -    }
  83.191 -
  83.192 -    public String getFieldNameSuffix() {
  83.193 -    return preferences.get(fieldNameSuffix, getDefaultAsString(fieldNameSuffix));
  83.194 -    }
  83.195 -
  83.196 -    public String getStaticFieldNamePrefix() {
  83.197 -    return preferences.get(staticFieldNamePrefix, getDefaultAsString(staticFieldNamePrefix));
  83.198 -    }
  83.199 -
  83.200 -    public String getStaticFieldNameSuffix() {
  83.201 -    return preferences.get(staticFieldNameSuffix, getDefaultAsString(staticFieldNameSuffix));
  83.202 -    }
  83.203 -
  83.204 -    public String getParameterNamePrefix() {
  83.205 -    return preferences.get(parameterNamePrefix, getDefaultAsString(parameterNamePrefix));
  83.206 -    }
  83.207 -
  83.208 -    public String getParameterNameSuffix() {
  83.209 -    return preferences.get(parameterNameSuffix, getDefaultAsString(parameterNameSuffix));
  83.210 -    }
  83.211 -
  83.212 -    public String getLocalVarNamePrefix() {
  83.213 -    return preferences.get(localVarNamePrefix, getDefaultAsString(localVarNamePrefix));
  83.214 -    }
  83.215 -
  83.216 -    public String getLocalVarNameSuffix() {
  83.217 -    return preferences.get(localVarNameSuffix, getDefaultAsString(localVarNameSuffix));
  83.218 -    }
  83.219 -
  83.220 -    public boolean qualifyFieldAccess() {
  83.221 -    return preferences.getBoolean(qualifyFieldAccess, getDefaultAsBoolean(qualifyFieldAccess));
  83.222 -    }
  83.223 -
  83.224 -    public boolean useIsForBooleanGetters() {
  83.225 -    return preferences.getBoolean(useIsForBooleanGetters, getDefaultAsBoolean(useIsForBooleanGetters));
  83.226 -    }
  83.227 -
  83.228 -    public boolean addOverrideAnnotation() {
  83.229 -    return preferences.getBoolean(addOverrideAnnotation, getDefaultAsBoolean(addOverrideAnnotation));
  83.230 -    }
  83.231 -
  83.232 -    public boolean makeLocalVarsFinal() {
  83.233 -    return preferences.getBoolean(makeLocalVarsFinal, getDefaultAsBoolean(makeLocalVarsFinal));
  83.234 -    }
  83.235 -
  83.236 -    // Alignment ----------------------------------------------------
  83.237 -    
  83.238 -    public boolean alignMultilineMethodParams() {
  83.239 -    return preferences.getBoolean(alignMultilineMethodParams, getDefaultAsBoolean(alignMultilineMethodParams));
  83.240 -    }
  83.241 -
  83.242 -    public boolean alignMultilineCallArgs() {
  83.243 -    return preferences.getBoolean(alignMultilineCallArgs, getDefaultAsBoolean(alignMultilineCallArgs));
  83.244 -    }
  83.245 -
  83.246 -    public boolean alignMultilineAnnotationArgs() {
  83.247 -    return preferences.getBoolean(alignMultilineAnnotationArgs, getDefaultAsBoolean(alignMultilineAnnotationArgs));
  83.248 -    }
  83.249 -
  83.250 -    public boolean alignMultilineImplements() {
  83.251 -    return preferences.getBoolean(alignMultilineImplements, getDefaultAsBoolean(alignMultilineImplements));
  83.252 -    }
  83.253 -
  83.254 -    public boolean alignMultilineThrows() {
  83.255 -    return preferences.getBoolean(alignMultilineThrows, getDefaultAsBoolean(alignMultilineThrows));
  83.256 -    }
  83.257 -
  83.258 -    public boolean alignMultilineParenthesized() {
  83.259 -    return preferences.getBoolean(alignMultilineParenthesized, getDefaultAsBoolean(alignMultilineParenthesized));
  83.260 -    }
  83.261 -
  83.262 -    public boolean alignMultilineBinaryOp() {
  83.263 -    return preferences.getBoolean(alignMultilineBinaryOp, getDefaultAsBoolean(alignMultilineBinaryOp));
  83.264 -    }
  83.265 -
  83.266 -    public boolean alignMultilineTernaryOp() {
  83.267 -    return preferences.getBoolean(alignMultilineTernaryOp, getDefaultAsBoolean(alignMultilineTernaryOp));
  83.268 -    }
  83.269 -
  83.270 -    public boolean alignMultilineAssignment() {
  83.271 -    return preferences.getBoolean(alignMultilineAssignment, getDefaultAsBoolean(alignMultilineAssignment));
  83.272 -    }
  83.273 -
  83.274 -    public boolean alignMultilineFor() {
  83.275 -    return preferences.getBoolean(alignMultilineFor, getDefaultAsBoolean(alignMultilineFor));
  83.276 -    }
  83.277 -
  83.278 -    public boolean alignMultilineArrayInit() {
  83.279 -    return preferences.getBoolean(alignMultilineArrayInit, getDefaultAsBoolean(alignMultilineArrayInit));
  83.280 -    }
  83.281 -
  83.282 -    public boolean placeElseOnNewLine() {
  83.283 -    return preferences.getBoolean(placeElseOnNewLine, getDefaultAsBoolean(placeElseOnNewLine));
  83.284 -    }
  83.285 -
  83.286 -    public boolean placeWhileOnNewLine() {
  83.287 -    return preferences.getBoolean(placeWhileOnNewLine, getDefaultAsBoolean(placeWhileOnNewLine));
  83.288 -    }
  83.289 -
  83.290 -    public boolean placeCatchOnNewLine() {
  83.291 -    return preferences.getBoolean(placeCatchOnNewLine, getDefaultAsBoolean(placeCatchOnNewLine));
  83.292 -    }
  83.293 -
  83.294 -    public boolean placeFinallyOnNewLine() {
  83.295 -    return preferences.getBoolean(placeFinallyOnNewLine, getDefaultAsBoolean(placeFinallyOnNewLine));
  83.296 -    }
  83.297 -    
  83.298 -    public boolean placeNewLineAfterModifiers() {
  83.299 -    return preferences.getBoolean(placeNewLineAfterModifiers, getDefaultAsBoolean(placeNewLineAfterModifiers));
  83.300 -    }
  83.301 -
  83.302 -    // Wrapping ----------------------------------------------------------------
  83.303 -    
  83.304 -    public WrapStyle wrapExtendsImplementsKeyword() {
  83.305 -    String wrap = preferences.get(wrapExtendsImplementsKeyword, getDefaultAsString(wrapExtendsImplementsKeyword));
  83.306 -    return WrapStyle.valueOf(wrap);
  83.307 -    }
  83.308 -
  83.309 -    public WrapStyle wrapExtendsImplementsList() {
  83.310 -    String wrap = preferences.get(wrapExtendsImplementsList, getDefaultAsString(wrapExtendsImplementsList));
  83.311 -    return WrapStyle.valueOf(wrap);
  83.312 -    }
  83.313 -
  83.314 -    public WrapStyle wrapMethodParams() {
  83.315 -    String wrap = preferences.get(wrapMethodParams, getDefaultAsString(wrapMethodParams));
  83.316 -    return WrapStyle.valueOf(wrap);
  83.317 -    }
  83.318 -
  83.319 -    public WrapStyle wrapThrowsKeyword() {
  83.320 -    String wrap = preferences.get(wrapThrowsKeyword, getDefaultAsString(wrapThrowsKeyword));
  83.321 -    return WrapStyle.valueOf(wrap);
  83.322 -    }
  83.323 -
  83.324 -    public WrapStyle wrapThrowsList() {
  83.325 -    String wrap = preferences.get(wrapThrowsList, getDefaultAsString(wrapThrowsList));
  83.326 -    return WrapStyle.valueOf(wrap);
  83.327 -    }
  83.328 -
  83.329 -    public WrapStyle wrapMethodCallArgs() {
  83.330 -    String wrap = preferences.get(wrapMethodCallArgs, getDefaultAsString(wrapMethodCallArgs));
  83.331 -    return WrapStyle.valueOf(wrap);
  83.332 -    }
  83.333 -
  83.334 -    public WrapStyle wrapAnnotationArgs() {
  83.335 -    String wrap = preferences.get(wrapAnnotationArgs, getDefaultAsString(wrapAnnotationArgs));
  83.336 -    return WrapStyle.valueOf(wrap);
  83.337 -    }
  83.338 -
  83.339 -    public WrapStyle wrapChainedMethodCalls() {
  83.340 -    String wrap = preferences.get(wrapChainedMethodCalls, getDefaultAsString(wrapChainedMethodCalls));
  83.341 -    return WrapStyle.valueOf(wrap);
  83.342 -    }
  83.343 -
  83.344 -    public WrapStyle wrapArrayInit() {
  83.345 -    String wrap = preferences.get(wrapArrayInit, getDefaultAsString(wrapArrayInit));
  83.346 -    return WrapStyle.valueOf(wrap);
  83.347 -    }
  83.348 -
  83.349 -    public WrapStyle wrapFor() {
  83.350 -    String wrap = preferences.get(wrapFor, getDefaultAsString(wrapFor));
  83.351 -    return WrapStyle.valueOf(wrap);
  83.352 -    }
  83.353 -
  83.354 -    public WrapStyle wrapForStatement() {
  83.355 -    String wrap = preferences.get(wrapForStatement, getDefaultAsString(wrapForStatement));
  83.356 -    return WrapStyle.valueOf(wrap);
  83.357 -    }
  83.358 -
  83.359 -    public WrapStyle wrapIfStatement() {
  83.360 -    String wrap = preferences.get(wrapIfStatement, getDefaultAsString(wrapIfStatement));
  83.361 -    return WrapStyle.valueOf(wrap);
  83.362 -    }
  83.363 -
  83.364 -    public WrapStyle wrapWhileStatement() {
  83.365 -    String wrap = preferences.get(wrapWhileStatement, getDefaultAsString(wrapWhileStatement));
  83.366 -    return WrapStyle.valueOf(wrap);
  83.367 -    }
  83.368 -
  83.369 -    public WrapStyle wrapDoWhileStatement() {
  83.370 -    String wrap = preferences.get(wrapDoWhileStatement, getDefaultAsString(wrapDoWhileStatement));
  83.371 -    return WrapStyle.valueOf(wrap);
  83.372 -    }
  83.373 -
  83.374 -    public WrapStyle wrapAssert() {
  83.375 -    String wrap = preferences.get(wrapAssert, getDefaultAsString(wrapAssert));
  83.376 -    return WrapStyle.valueOf(wrap);
  83.377 -    }
  83.378 -
  83.379 -    public WrapStyle wrapEnumConstants() {
  83.380 -    String wrap = preferences.get(wrapEnumConstants, getDefaultAsString(wrapEnumConstants));
  83.381 -    return WrapStyle.valueOf(wrap);
  83.382 -    }
  83.383 -
  83.384 -    public WrapStyle wrapAnnotations() {
  83.385 -    String wrap = preferences.get(wrapAnnotations, getDefaultAsString(wrapAnnotations));
  83.386 -    return WrapStyle.valueOf(wrap);
  83.387 -    }
  83.388 -
  83.389 -    public WrapStyle wrapBinaryOps() {
  83.390 -    String wrap = preferences.get(wrapBinaryOps, getDefaultAsString(wrapBinaryOps));
  83.391 -    return WrapStyle.valueOf(wrap);
  83.392 -    }
  83.393 -
  83.394 -    public WrapStyle wrapTernaryOps() {
  83.395 -    String wrap = preferences.get(wrapTernaryOps, getDefaultAsString(wrapTernaryOps));
  83.396 -    return WrapStyle.valueOf(wrap);
  83.397 -    }
  83.398 -
  83.399 -    public WrapStyle wrapAssignOps() {
  83.400 -    String wrap = preferences.get(wrapAssignOps, getDefaultAsString(wrapAssignOps));
  83.401 -    return WrapStyle.valueOf(wrap);
  83.402 -    }
  83.403 -
  83.404 -    // Blank lines -------------------------------------------------------------
  83.405 -    
  83.406 -    public int getBlankLinesBeforePackage() {
  83.407 -    return preferences.getInt(blankLinesBeforePackage, getDefaultAsInt(blankLinesBeforePackage));
  83.408 -    }
  83.409 -
  83.410 -    public int getBlankLinesAfterPackage() {
  83.411 -    return preferences.getInt(blankLinesAfterPackage, getDefaultAsInt(blankLinesAfterPackage));
  83.412 -    }
  83.413 -
  83.414 -    public int getBlankLinesBeforeImports() {
  83.415 -    return preferences.getInt(blankLinesBeforeImports, getDefaultAsInt(blankLinesBeforeImports));
  83.416 -    }
  83.417 -
  83.418 -    public int getBlankLinesAfterImports() {
  83.419 -    return preferences.getInt(blankLinesAfterImports, getDefaultAsInt(blankLinesAfterImports));
  83.420 -    }
  83.421 -
  83.422 -    public int getBlankLinesBeforeClass() {
  83.423 -    return preferences.getInt(blankLinesBeforeClass, getDefaultAsInt(blankLinesBeforeClass));
  83.424 -    }
  83.425 -
  83.426 -    public int getBlankLinesAfterClass() {
  83.427 -    return preferences.getInt(blankLinesAfterClass, getDefaultAsInt(blankLinesAfterClass));
  83.428 -    }
  83.429 -
  83.430 -    public int getBlankLinesAfterClassHeader() {
  83.431 -    return preferences.getInt(blankLinesAfterClassHeader, getDefaultAsInt(blankLinesAfterClassHeader));
  83.432 -    }
  83.433 -
  83.434 -    public int getBlankLinesBeforeFields() {
  83.435 -    return preferences.getInt(blankLinesBeforeFields, getDefaultAsInt(blankLinesBeforeFields));
  83.436 -    }
  83.437 -
  83.438 -    public int getBlankLinesAfterFields() {
  83.439 -    return preferences.getInt(blankLinesAfterFields, getDefaultAsInt(blankLinesAfterFields));
  83.440 -    }
  83.441 -
  83.442 -    public int getBlankLinesBeforeMethods() {
  83.443 -    return preferences.getInt(blankLinesBeforeMethods, getDefaultAsInt(blankLinesBeforeMethods));
  83.444 -    }
  83.445 -
  83.446 -    public int getBlankLinesAfterMethods() {
  83.447 -    return preferences.getInt(blankLinesAfterMethods, getDefaultAsInt(blankLinesAfterMethods));
  83.448 -    }
  83.449 -
  83.450 -    // Spaces ------------------------------------------------------------------
  83.451 -    
  83.452 -    public boolean spaceBeforeWhile() {
  83.453 -    return preferences.getBoolean(spaceBeforeWhile, getDefaultAsBoolean(spaceBeforeWhile));
  83.454 -    }
  83.455 -
  83.456 -    public boolean spaceBeforeElse() {
  83.457 -    return preferences.getBoolean(spaceBeforeElse, getDefaultAsBoolean(spaceBeforeElse));
  83.458 -    }
  83.459 -
  83.460 -    public boolean spaceBeforeCatch() {
  83.461 -    return preferences.getBoolean(spaceBeforeCatch, getDefaultAsBoolean(spaceBeforeCatch));
  83.462 -    }
  83.463 -
  83.464 -    public boolean spaceBeforeFinally() {
  83.465 -    return preferences.getBoolean(spaceBeforeFinally, getDefaultAsBoolean(spaceBeforeFinally));
  83.466 -    }
  83.467 -
  83.468 -    public boolean spaceBeforeMethodDeclParen() {
  83.469 -    return preferences.getBoolean(spaceBeforeMethodDeclParen, getDefaultAsBoolean(spaceBeforeMethodDeclParen));
  83.470 -    }
  83.471 -
  83.472 -    public boolean spaceBeforeMethodCallParen() {
  83.473 -    return preferences.getBoolean(spaceBeforeMethodCallParen, getDefaultAsBoolean(spaceBeforeMethodCallParen));
  83.474 -    }
  83.475 -
  83.476 -    public boolean spaceBeforeIfParen() {
  83.477 -    return preferences.getBoolean(spaceBeforeIfParen, getDefaultAsBoolean(spaceBeforeIfParen));
  83.478 -    }
  83.479 -
  83.480 -    public boolean spaceBeforeForParen() {
  83.481 -    return preferences.getBoolean(spaceBeforeForParen, getDefaultAsBoolean(spaceBeforeForParen));
  83.482 -    }
  83.483 -
  83.484 -    public boolean spaceBeforeWhileParen() {
  83.485 -    return preferences.getBoolean(spaceBeforeWhileParen, getDefaultAsBoolean(spaceBeforeWhileParen));
  83.486 -    }
  83.487 -
  83.488 -    public boolean spaceBeforeCatchParen() {
  83.489 -    return preferences.getBoolean(spaceBeforeCatchParen, getDefaultAsBoolean(spaceBeforeCatchParen));
  83.490 -    }
  83.491 -
  83.492 -    public boolean spaceBeforeSwitchParen() {
  83.493 -    return preferences.getBoolean(spaceBeforeSwitchParen, getDefaultAsBoolean(spaceBeforeSwitchParen));
  83.494 -    }
  83.495 -
  83.496 -    public boolean spaceBeforeSynchronizedParen() {
  83.497 -    return preferences.getBoolean(spaceBeforeSynchronizedParen, getDefaultAsBoolean(spaceBeforeSynchronizedParen));
  83.498 -    }
  83.499 -
  83.500 -    public boolean spaceBeforeAnnotationParen() {
  83.501 -    return preferences.getBoolean(spaceBeforeAnnotationParen, getDefaultAsBoolean(spaceBeforeAnnotationParen));
  83.502 -    }
  83.503 -
  83.504 -    public boolean spaceAroundUnaryOps() {
  83.505 -    return preferences.getBoolean(spaceAroundUnaryOps, getDefaultAsBoolean(spaceAroundUnaryOps));
  83.506 -    }
  83.507 -
  83.508 -    public boolean spaceAroundBinaryOps() {
  83.509 -    return preferences.getBoolean(spaceAroundBinaryOps, getDefaultAsBoolean(spaceAroundBinaryOps));
  83.510 -    }
  83.511 -
  83.512 -    public boolean spaceAroundTernaryOps() {
  83.513 -    return preferences.getBoolean(spaceAroundTernaryOps, getDefaultAsBoolean(spaceAroundTernaryOps));
  83.514 -    }
  83.515 -
  83.516 -    public boolean spaceAroundAssignOps() {
  83.517 -    return preferences.getBoolean(spaceAroundAssignOps, getDefaultAsBoolean(spaceAroundAssignOps));
  83.518 -    }
  83.519 -
  83.520 -    public boolean spaceBeforeClassDeclLeftBrace() {
  83.521 -    return preferences.getBoolean(spaceBeforeClassDeclLeftBrace, getDefaultAsBoolean(spaceBeforeClassDeclLeftBrace));
  83.522 -    }
  83.523 -
  83.524 -    public boolean spaceBeforeMethodDeclLeftBrace() {
  83.525 -    return preferences.getBoolean(spaceBeforeMethodDeclLeftBrace, getDefaultAsBoolean(spaceBeforeMethodDeclLeftBrace));
  83.526 -    }
  83.527 -
  83.528 -    public boolean spaceBeforeIfLeftBrace() {
  83.529 -    return preferences.getBoolean(spaceBeforeIfLeftBrace, getDefaultAsBoolean(spaceBeforeIfLeftBrace));
  83.530 -    }
  83.531 -
  83.532 -    public boolean spaceBeforeElseLeftBrace() {
  83.533 -    return preferences.getBoolean(spaceBeforeElseLeftBrace, getDefaultAsBoolean(spaceBeforeElseLeftBrace));
  83.534 -    }
  83.535 -
  83.536 -    public boolean spaceBeforeWhileLeftBrace() {
  83.537 -    return preferences.getBoolean(spaceBeforeWhileLeftBrace, getDefaultAsBoolean(spaceBeforeWhileLeftBrace));
  83.538 -    }
  83.539 -
  83.540 -    public boolean spaceBeforeForLeftBrace() {
  83.541 -    return preferences.getBoolean(spaceBeforeForLeftBrace, getDefaultAsBoolean(spaceBeforeForLeftBrace));
  83.542 -    }
  83.543 -
  83.544 -    public boolean spaceBeforeDoLeftBrace() {
  83.545 -    return preferences.getBoolean(spaceBeforeDoLeftBrace, getDefaultAsBoolean(spaceBeforeDoLeftBrace));
  83.546 -    }
  83.547 -
  83.548 -    public boolean spaceBeforeSwitchLeftBrace() {
  83.549 -    return preferences.getBoolean(spaceBeforeSwitchLeftBrace, getDefaultAsBoolean(spaceBeforeSwitchLeftBrace));
  83.550 -    }
  83.551 -
  83.552 -    public boolean spaceBeforeTryLeftBrace() {
  83.553 -    return preferences.getBoolean(spaceBeforeTryLeftBrace, getDefaultAsBoolean(spaceBeforeTryLeftBrace));
  83.554 -    }
  83.555 -
  83.556 -    public boolean spaceBeforeCatchLeftBrace() {
  83.557 -    return preferences.getBoolean(spaceBeforeCatchLeftBrace, getDefaultAsBoolean(spaceBeforeCatchLeftBrace));
  83.558 -    }
  83.559 -
  83.560 -    public boolean spaceBeforeFinallyLeftBrace() {
  83.561 -    return preferences.getBoolean(spaceBeforeFinallyLeftBrace, getDefaultAsBoolean(spaceBeforeFinallyLeftBrace));
  83.562 -    }
  83.563 -
  83.564 -    public boolean spaceBeforeSynchronizedLeftBrace() {
  83.565 -    return preferences.getBoolean(spaceBeforeSynchronizedLeftBrace, getDefaultAsBoolean(spaceBeforeSynchronizedLeftBrace));
  83.566 -    }
  83.567 -
  83.568 -    public boolean spaceBeforeStaticInitLeftBrace() {
  83.569 -    return preferences.getBoolean(spaceBeforeStaticInitLeftBrace, getDefaultAsBoolean(spaceBeforeStaticInitLeftBrace));
  83.570 -    }
  83.571 -
  83.572 -    public boolean spaceBeforeArrayInitLeftBrace() {
  83.573 -    return preferences.getBoolean(spaceBeforeArrayInitLeftBrace, getDefaultAsBoolean(spaceBeforeArrayInitLeftBrace));
  83.574 -    }
  83.575 -
  83.576 -    public boolean spaceWithinParens() {
  83.577 -    return preferences.getBoolean(spaceWithinParens, getDefaultAsBoolean(spaceWithinParens));
  83.578 -    }
  83.579 -
  83.580 -    public boolean spaceWithinMethodDeclParens() {
  83.581 -    return preferences.getBoolean(spaceWithinMethodDeclParens, getDefaultAsBoolean(spaceWithinMethodDeclParens));
  83.582 -    }
  83.583 -
  83.584 -    public boolean spaceWithinMethodCallParens() {
  83.585 -    return preferences.getBoolean(spaceWithinMethodCallParens, getDefaultAsBoolean(spaceWithinMethodCallParens));
  83.586 -    }
  83.587 -
  83.588 -    public boolean spaceWithinIfParens() {
  83.589 -    return preferences.getBoolean(spaceWithinIfParens, getDefaultAsBoolean(spaceWithinIfParens));
  83.590 -    }
  83.591 -
  83.592 -    public boolean spaceWithinForParens() {
  83.593 -    return preferences.getBoolean(spaceWithinForParens, getDefaultAsBoolean(spaceWithinForParens));
  83.594 -    }
  83.595 -
  83.596 -    public boolean spaceWithinWhileParens() {
  83.597 -    return preferences.getBoolean(spaceWithinWhileParens, getDefaultAsBoolean(spaceWithinWhileParens));
  83.598 -    }
  83.599 -
  83.600 -    public boolean spaceWithinSwitchParens() {
  83.601 -    return preferences.getBoolean(spaceWithinSwitchParens, getDefaultAsBoolean(spaceWithinSwitchParens));
  83.602 -    }
  83.603 -
  83.604 -    public boolean spaceWithinCatchParens() {
  83.605 -    return preferences.getBoolean(spaceWithinCatchParens, getDefaultAsBoolean(spaceWithinCatchParens));
  83.606 -    }
  83.607 -
  83.608 -    public boolean spaceWithinSynchronizedParens() {
  83.609 -    return preferences.getBoolean(spaceWithinSynchronizedParens, getDefaultAsBoolean(spaceWithinSynchronizedParens));
  83.610 -    }
  83.611 -
  83.612 -    public boolean spaceWithinTypeCastParens() {
  83.613 -    return preferences.getBoolean(spaceWithinTypeCastParens, getDefaultAsBoolean(spaceWithinTypeCastParens));
  83.614 -    }
  83.615 -
  83.616 -    public boolean spaceWithinAnnotationParens() {
  83.617 -    return preferences.getBoolean(spaceWithinAnnotationParens, getDefaultAsBoolean(spaceWithinAnnotationParens));
  83.618 -    }
  83.619 -
  83.620 -    public boolean spaceWithinBraces() {
  83.621 -    return preferences.getBoolean(spaceWithinBraces, getDefaultAsBoolean(spaceWithinBraces));
  83.622 -    }
  83.623 -
  83.624 -    public boolean spaceWithinArrayInitBrackets() {
  83.625 -    return preferences.getBoolean(spaceWithinArrayInitBrackets, getDefaultAsBoolean(spaceWithinArrayInitBrackets));
  83.626 -    }
  83.627 -
  83.628 -    public boolean spaceBeforeComma() {
  83.629 -    return preferences.getBoolean(spaceBeforeComma, getDefaultAsBoolean(spaceBeforeComma));
  83.630 -    }
  83.631 -
  83.632 -    public boolean spaceAfterComma() {
  83.633 -    return preferences.getBoolean(spaceAfterComma, getDefaultAsBoolean(spaceAfterComma));
  83.634 -    }
  83.635 -
  83.636 -    public boolean spaceBeforeSemi() {
  83.637 -    return preferences.getBoolean(spaceBeforeSemi, getDefaultAsBoolean(spaceBeforeSemi));
  83.638 -    }
  83.639 -
  83.640 -    public boolean spaceAfterSemi() {
  83.641 -    return preferences.getBoolean(spaceAfterSemi, getDefaultAsBoolean(spaceAfterSemi));
  83.642 -    }
  83.643 -
  83.644 -    public boolean spaceBeforeColon() {
  83.645 -    return preferences.getBoolean(spaceBeforeColon, getDefaultAsBoolean(spaceBeforeColon));
  83.646 -    }
  83.647 -
  83.648 -    public boolean spaceAfterColon() {
  83.649 -    return preferences.getBoolean(spaceAfterColon, getDefaultAsBoolean(spaceAfterColon));
  83.650 -    }
  83.651 -
  83.652 -    public boolean spaceAfterTypeCast() {
  83.653 -    return preferences.getBoolean(spaceAfterTypeCast, getDefaultAsBoolean(spaceAfterTypeCast));
  83.654 -    }
  83.655 -
  83.656 -     */
  83.657 -    // Spaces -----------------------------------------------------------------
  83.658 -    public boolean addSpaceAroundOperators() {
  83.659 -        return preferences.getBoolean(addSpaceAroundOperators, getDefaultAsBoolean(addSpaceAroundOperators));
  83.660 -    }
  83.661 -
  83.662 -    public boolean removeSpaceInsideParens() {
  83.663 -        return preferences.getBoolean(removeSpaceInParens, getDefaultAsBoolean(removeSpaceInParens));
  83.664 -    }
  83.665 -
  83.666 -    public boolean addSpaceAfterComma() {
  83.667 -        return preferences.getBoolean(addSpaceAfterComma, getDefaultAsBoolean(addSpaceAfterComma));
  83.668 -    }
  83.669 -
  83.670 -    public boolean removeSpaceBeforeSep() {
  83.671 -        return preferences.getBoolean(removeSpaceBeforeSep, getDefaultAsBoolean(removeSpaceBeforeSep));
  83.672 -    }
  83.673 -
  83.674 -    public boolean removeSpaceInParamAssign() {
  83.675 -        return preferences.getBoolean(removeSpaceInParamAssign, getDefaultAsBoolean(removeSpaceInParamAssign));
  83.676 -    }
  83.677 -
  83.678 -    public boolean collapseSpaces() {
  83.679 -        return preferences.getBoolean(collapseSpaces, getDefaultAsBoolean(collapseSpaces));
  83.680 -    }
  83.681 -
  83.682 -    // Imports -----------------------------------------------------------------
  83.683 -    public boolean formatImports() {
  83.684 -        return preferences.getBoolean(formatImports, getDefaultAsBoolean(formatImports));
  83.685 -    }
  83.686 -
  83.687 -    public boolean oneImportPerLine() {
  83.688 -        return preferences.getBoolean(oneImportPerLine, getDefaultAsBoolean(oneImportPerLine));
  83.689 -    }
  83.690 -
  83.691 -    public boolean removeDuplicates() {
  83.692 -        return preferences.getBoolean(removeDuplicates, getDefaultAsBoolean(removeDuplicates));
  83.693 -    }
  83.694 -
  83.695 -    public boolean systemLibsFirst() {
  83.696 -        return preferences.getBoolean(systemLibsFirst, getDefaultAsBoolean(systemLibsFirst));
  83.697 -    }
  83.698 -
  83.699 -    public boolean preferSymbolImports() {
  83.700 -        return preferences.getBoolean(preferSymbolImports, getDefaultAsBoolean(preferSymbolImports));
  83.701 -    }
  83.702 -
  83.703 -    public boolean sortImports() {
  83.704 -        return preferences.getBoolean(sortImports, getDefaultAsBoolean(sortImports));
  83.705 -    }
  83.706 -
  83.707 -    public boolean separateFromImps() {
  83.708 -        return preferences.getBoolean(separateFromImps, getDefaultAsBoolean(separateFromImps));
  83.709 -    }
  83.710 -
  83.711 -    public ImportCleanupStyle cleanupImports() {
  83.712 -        String cleanup = preferences.get(cleanupUnusedImports, getDefaultAsString(cleanupUnusedImports));
  83.713 -        return ImportCleanupStyle.valueOf(cleanup);
  83.714 -    }
  83.715 -
  83.716 -    public String[] getPackagesForStarImport() {
  83.717 -        return null;
  83.718 -    }
  83.719 -
  83.720 -    // Nested classes ----------------------------------------------------------
  83.721 -    public enum WrapStyle {
  83.722 -        WRAP_ALWAYS,
  83.723 -        WRAP_IF_LONG,
  83.724 -        WRAP_NEVER
  83.725 -    }
  83.726 -
  83.727 -    public enum ImportCleanupStyle {
  83.728 -        LEAVE_ALONE,
  83.729 -        COMMENT_OUT,
  83.730 -        DELETE
  83.731 -    }
  83.732 -
  83.733 -    // Communication with non public packages ----------------------------------
  83.734 -    private static class Producer implements FmtOptions.CodeStyleProducer {
  83.735 -        @Override
  83.736 -        public CodeStyle create(Preferences preferences) {
  83.737 -            return new CodeStyle(preferences);
  83.738 -        }
  83.739 -    }
  83.740 -}
    84.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtAlignment.form	Fri Sep 18 16:20:24 2015 -0500
    84.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.3 @@ -1,350 +0,0 @@
    84.4 -<?xml version="1.0" encoding="UTF-8" ?>
    84.5 -
    84.6 -<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    84.7 -  <Properties>
    84.8 -    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    84.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;)"/>
   84.10 -    </Property>
   84.11 -    <Property name="opaque" type="boolean" value="false"/>
   84.12 -  </Properties>
   84.13 -  <AuxValues>
   84.14 -    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   84.15 -    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   84.16 -    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   84.17 -    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
   84.18 -    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   84.19 -    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
   84.20 -    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
   84.21 -    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   84.22 -    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   84.23 -  </AuxValues>
   84.24 -
   84.25 -  <Layout>
   84.26 -    <DimensionLayout dim="0">
   84.27 -      <Group type="103" groupAlignment="0" attributes="0">
   84.28 -          <Group type="102" attributes="0">
   84.29 -              <Group type="103" groupAlignment="0" attributes="0">
   84.30 -                  <Group type="102" alignment="0" attributes="0">
   84.31 -                      <EmptySpace min="-2" max="-2" attributes="0"/>
   84.32 -                      <Component id="amParenthesizedCheckBox1" min="-2" max="-2" attributes="0"/>
   84.33 -                  </Group>
   84.34 -                  <Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
   84.35 -                      <Group type="102" alignment="0" attributes="1">
   84.36 -                          <Component id="newLinesLabel" min="-2" max="-2" attributes="0"/>
   84.37 -                          <EmptySpace max="-2" attributes="0"/>
   84.38 -                          <Component id="jSeparator1" max="32767" attributes="0"/>
   84.39 -                      </Group>
   84.40 -                      <Group type="102" alignment="0" attributes="1">
   84.41 -                          <Component id="multilineAlignmentLabel" min="-2" max="-2" attributes="0"/>
   84.42 -                          <EmptySpace max="-2" attributes="0"/>
   84.43 -                          <Component id="jSeparator2" max="32767" attributes="1"/>
   84.44 -                      </Group>
   84.45 -                      <Group type="102" alignment="0" attributes="0">
   84.46 -                          <EmptySpace max="-2" attributes="0"/>
   84.47 -                          <Group type="103" groupAlignment="0" attributes="0">
   84.48 -                              <Component id="amThrowsCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/>
   84.49 -                              <Component id="amBinaryOpCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/>
   84.50 -                              <Component id="amAssignCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/>
   84.51 -                              <Component id="amAnnotationArgsCheckBox" alignment="0" min="-2" max="-2" attributes="1"/>
   84.52 -                              <Component id="nlElseCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
   84.53 -                              <Component id="nlWhileCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
   84.54 -                              <Component id="nlCatchCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
   84.55 -                              <Component id="amMethodParamsCheckBox" alignment="0" min="-2" max="-2" attributes="1"/>
   84.56 -                          </Group>
   84.57 -                          <EmptySpace min="-2" max="-2" attributes="0"/>
   84.58 -                          <Group type="103" groupAlignment="0" attributes="0">
   84.59 -                              <Component id="amCallArgsCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
   84.60 -                              <Component id="nlModifiersCheckBox" min="-2" max="-2" attributes="0"/>
   84.61 -                              <Component id="nlFinallyCheckBox" min="-2" max="-2" attributes="0"/>
   84.62 -                              <Component id="amImplementsCheckBox1" min="-2" max="-2" attributes="0"/>
   84.63 -                              <Component id="amArrayInitCheckBox1" min="-2" max="-2" attributes="0"/>
   84.64 -                              <Component id="amTernaryOpCheckBox1" min="-2" max="-2" attributes="0"/>
   84.65 -                              <Component id="amForCheckBox1" min="-2" max="-2" attributes="0"/>
   84.66 -                          </Group>
   84.67 -                      </Group>
   84.68 -                  </Group>
   84.69 -              </Group>
   84.70 -              <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
   84.71 -          </Group>
   84.72 -      </Group>
   84.73 -    </DimensionLayout>
   84.74 -    <DimensionLayout dim="1">
   84.75 -      <Group type="103" groupAlignment="0" attributes="0">
   84.76 -          <Group type="102" alignment="0" attributes="0">
   84.77 -              <Group type="103" groupAlignment="0" attributes="0">
   84.78 -                  <Group type="102" attributes="0">
   84.79 -                      <EmptySpace max="-2" attributes="0"/>
   84.80 -                      <Component id="newLinesLabel" min="-2" max="-2" attributes="1"/>
   84.81 -                  </Group>
   84.82 -                  <Group type="102" attributes="0">
   84.83 -                      <EmptySpace min="-2" pref="17" max="-2" attributes="0"/>
   84.84 -                      <Component id="jSeparator1" min="-2" pref="10" max="-2" attributes="0"/>
   84.85 -                  </Group>
   84.86 -              </Group>
   84.87 -              <EmptySpace max="-2" attributes="0"/>
   84.88 -              <Group type="103" groupAlignment="3" attributes="0">
   84.89 -                  <Component id="nlElseCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
   84.90 -                  <Component id="nlFinallyCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
   84.91 -              </Group>
   84.92 -              <EmptySpace max="-2" attributes="0"/>
   84.93 -              <Group type="103" groupAlignment="3" attributes="0">
   84.94 -                  <Component id="nlWhileCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
   84.95 -                  <Component id="nlModifiersCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
   84.96 -              </Group>
   84.97 -              <Group type="103" groupAlignment="0" attributes="0">
   84.98 -                  <Group type="102" attributes="0">
   84.99 -                      <EmptySpace max="-2" attributes="0"/>
  84.100 -                      <Component id="nlCatchCheckBox" min="-2" max="-2" attributes="0"/>
  84.101 -                      <EmptySpace type="separate" max="-2" attributes="0"/>
  84.102 -                      <Component id="multilineAlignmentLabel" min="-2" max="-2" attributes="0"/>
  84.103 -                  </Group>
  84.104 -                  <Group type="102" attributes="0">
  84.105 -                      <EmptySpace min="-2" pref="44" max="-2" attributes="0"/>
  84.106 -                      <Component id="jSeparator2" min="-2" pref="10" max="-2" attributes="0"/>
  84.107 -                  </Group>
  84.108 -              </Group>
  84.109 -              <EmptySpace min="-2" max="-2" attributes="0"/>
  84.110 -              <Group type="103" groupAlignment="3" attributes="0">
  84.111 -                  <Component id="amMethodParamsCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
  84.112 -                  <Component id="amCallArgsCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
  84.113 -              </Group>
  84.114 -              <EmptySpace min="-2" max="-2" attributes="0"/>
  84.115 -              <Group type="103" groupAlignment="3" attributes="0">
  84.116 -                  <Component id="amAnnotationArgsCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
  84.117 -                  <Component id="amImplementsCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
  84.118 -              </Group>
  84.119 -              <EmptySpace max="-2" attributes="0"/>
  84.120 -              <Group type="103" groupAlignment="3" attributes="0">
  84.121 -                  <Component id="amThrowsCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
  84.122 -                  <Component id="amArrayInitCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
  84.123 -              </Group>
  84.124 -              <EmptySpace max="-2" attributes="0"/>
  84.125 -              <Group type="103" groupAlignment="3" attributes="0">
  84.126 -                  <Component id="amBinaryOpCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
  84.127 -                  <Component id="amTernaryOpCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
  84.128 -              </Group>
  84.129 -              <EmptySpace max="-2" attributes="0"/>
  84.130 -              <Group type="103" groupAlignment="3" attributes="0">
  84.131 -                  <Component id="amAssignCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
  84.132 -                  <Component id="amForCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
  84.133 -              </Group>
  84.134 -              <EmptySpace min="-2" max="-2" attributes="0"/>
  84.135 -              <Component id="amParenthesizedCheckBox1" min="-2" max="-2" attributes="0"/>
  84.136 -              <EmptySpace max="32767" attributes="0"/>
  84.137 -          </Group>
  84.138 -      </Group>
  84.139 -    </DimensionLayout>
  84.140 -  </Layout>
  84.141 -  <SubComponents>
  84.142 -    <Component class="javax.swing.JLabel" name="newLinesLabel">
  84.143 -      <Properties>
  84.144 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.146 -        </Property>
  84.147 -      </Properties>
  84.148 -    </Component>
  84.149 -    <Component class="javax.swing.JCheckBox" name="nlElseCheckBox">
  84.150 -      <Properties>
  84.151 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.153 -        </Property>
  84.154 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.155 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.156 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.157 -          </Border>
  84.158 -        </Property>
  84.159 -      </Properties>
  84.160 -    </Component>
  84.161 -    <Component class="javax.swing.JCheckBox" name="nlWhileCheckBox">
  84.162 -      <Properties>
  84.163 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.165 -        </Property>
  84.166 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.167 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.168 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.169 -          </Border>
  84.170 -        </Property>
  84.171 -      </Properties>
  84.172 -    </Component>
  84.173 -    <Component class="javax.swing.JCheckBox" name="nlCatchCheckBox">
  84.174 -      <Properties>
  84.175 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.177 -        </Property>
  84.178 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.179 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.180 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.181 -          </Border>
  84.182 -        </Property>
  84.183 -      </Properties>
  84.184 -    </Component>
  84.185 -    <Component class="javax.swing.JCheckBox" name="nlFinallyCheckBox">
  84.186 -      <Properties>
  84.187 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.189 -        </Property>
  84.190 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.191 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.192 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.193 -          </Border>
  84.194 -        </Property>
  84.195 -      </Properties>
  84.196 -    </Component>
  84.197 -    <Component class="javax.swing.JCheckBox" name="nlModifiersCheckBox">
  84.198 -      <Properties>
  84.199 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.201 -        </Property>
  84.202 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.203 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.204 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.205 -          </Border>
  84.206 -        </Property>
  84.207 -      </Properties>
  84.208 -    </Component>
  84.209 -    <Component class="javax.swing.JLabel" name="multilineAlignmentLabel">
  84.210 -      <Properties>
  84.211 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.213 -        </Property>
  84.214 -      </Properties>
  84.215 -    </Component>
  84.216 -    <Component class="javax.swing.JCheckBox" name="amMethodParamsCheckBox">
  84.217 -      <Properties>
  84.218 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.220 -        </Property>
  84.221 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.222 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.223 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.224 -          </Border>
  84.225 -        </Property>
  84.226 -      </Properties>
  84.227 -    </Component>
  84.228 -    <Component class="javax.swing.JCheckBox" name="amCallArgsCheckBox">
  84.229 -      <Properties>
  84.230 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.232 -        </Property>
  84.233 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.234 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.235 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.236 -          </Border>
  84.237 -        </Property>
  84.238 -      </Properties>
  84.239 -    </Component>
  84.240 -    <Component class="javax.swing.JCheckBox" name="amAnnotationArgsCheckBox">
  84.241 -      <Properties>
  84.242 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.244 -        </Property>
  84.245 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.246 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.247 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.248 -          </Border>
  84.249 -        </Property>
  84.250 -      </Properties>
  84.251 -    </Component>
  84.252 -    <Component class="javax.swing.JCheckBox" name="amImplementsCheckBox1">
  84.253 -      <Properties>
  84.254 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.256 -        </Property>
  84.257 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.258 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.259 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.260 -          </Border>
  84.261 -        </Property>
  84.262 -      </Properties>
  84.263 -    </Component>
  84.264 -    <Component class="javax.swing.JCheckBox" name="amThrowsCheckBox1">
  84.265 -      <Properties>
  84.266 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.268 -        </Property>
  84.269 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.270 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.271 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.272 -          </Border>
  84.273 -        </Property>
  84.274 -      </Properties>
  84.275 -    </Component>
  84.276 -    <Component class="javax.swing.JCheckBox" name="amArrayInitCheckBox1">
  84.277 -      <Properties>
  84.278 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.280 -        </Property>
  84.281 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.282 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.283 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.284 -          </Border>
  84.285 -        </Property>
  84.286 -      </Properties>
  84.287 -    </Component>
  84.288 -    <Component class="javax.swing.JCheckBox" name="amBinaryOpCheckBox1">
  84.289 -      <Properties>
  84.290 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.292 -        </Property>
  84.293 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.294 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.295 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.296 -          </Border>
  84.297 -        </Property>
  84.298 -      </Properties>
  84.299 -    </Component>
  84.300 -    <Component class="javax.swing.JCheckBox" name="amTernaryOpCheckBox1">
  84.301 -      <Properties>
  84.302 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.304 -        </Property>
  84.305 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.306 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.307 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.308 -          </Border>
  84.309 -        </Property>
  84.310 -      </Properties>
  84.311 -    </Component>
  84.312 -    <Component class="javax.swing.JCheckBox" name="amAssignCheckBox1">
  84.313 -      <Properties>
  84.314 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.316 -        </Property>
  84.317 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.318 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.319 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.320 -          </Border>
  84.321 -        </Property>
  84.322 -      </Properties>
  84.323 -    </Component>
  84.324 -    <Component class="javax.swing.JCheckBox" name="amForCheckBox1">
  84.325 -      <Properties>
  84.326 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.328 -        </Property>
  84.329 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.330 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.331 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.332 -          </Border>
  84.333 -        </Property>
  84.334 -      </Properties>
  84.335 -    </Component>
  84.336 -    <Component class="javax.swing.JCheckBox" name="amParenthesizedCheckBox1">
  84.337 -      <Properties>
  84.338 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  84.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;)"/>
  84.340 -        </Property>
  84.341 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  84.342 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  84.343 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  84.344 -          </Border>
  84.345 -        </Property>
  84.346 -      </Properties>
  84.347 -    </Component>
  84.348 -    <Component class="javax.swing.JSeparator" name="jSeparator1">
  84.349 -    </Component>
  84.350 -    <Component class="javax.swing.JSeparator" name="jSeparator2">
  84.351 -    </Component>
  84.352 -  </SubComponents>
  84.353 -</Form>
    85.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtAlignment.java	Fri Sep 18 16:20:24 2015 -0500
    85.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.3 @@ -1,309 +0,0 @@
    85.4 -/*
    85.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    85.6 - *
    85.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    85.8 - *
    85.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   85.10 - * Other names may be trademarks of their respective owners.
   85.11 - *
   85.12 - * The contents of this file are subject to the terms of either the GNU
   85.13 - * General Public License Version 2 only ("GPL") or the Common
   85.14 - * Development and Distribution License("CDDL") (collectively, the
   85.15 - * "License"). You may not use this file except in compliance with the
   85.16 - * License. You can obtain a copy of the License at
   85.17 - * http://www.netbeans.org/cddl-gplv2.html
   85.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   85.19 - * specific language governing permissions and limitations under the
   85.20 - * License.  When distributing the software, include this License Header
   85.21 - * Notice in each file and include the License file at
   85.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   85.23 - * particular file as subject to the "Classpath" exception as provided
   85.24 - * by Oracle in the GPL Version 2 section of the License file that
   85.25 - * accompanied this code. If applicable, add the following below the
   85.26 - * License Header, with the fields enclosed by brackets [] replaced by
   85.27 - * your own identifying information:
   85.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   85.29 - *
   85.30 - * Contributor(s):
   85.31 - *
   85.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   85.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   85.34 - * Microsystems, Inc. All Rights Reserved.
   85.35 - *
   85.36 - * If you wish your version of this file to be governed by only the CDDL
   85.37 - * or only the GPL Version 2, indicate your decision by adding
   85.38 - * "[Contributor] elects to include this software in this distribution
   85.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   85.40 - * single choice of license, a recipient has the option to distribute
   85.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   85.42 - * to extend the choice of license to its licensees as provided above.
   85.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   85.44 - * Version 2 license, then the option applies only if the new code is
   85.45 - * made subject to such option by the copyright holder.
   85.46 - */
   85.47 -
   85.48 -package org.netbeans.modules.python.editor.options;
   85.49 -
   85.50 -import org.netbeans.modules.python.editor.options.CodeStyle.WrapStyle;
   85.51 -import static org.netbeans.modules.python.editor.options.FmtOptions.*;
   85.52 -import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
   85.53 -import org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport;
   85.54 -import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
   85.55 -
   85.56 -
   85.57 -/**
   85.58 - *
   85.59 - * @author  phrebejk
   85.60 - */
   85.61 -public class FmtAlignment extends javax.swing.JPanel {
   85.62 -    
   85.63 -    /** Creates new form FmtAlignment */
   85.64 -    public FmtAlignment() {
   85.65 -        initComponents();
   85.66 -/*
   85.67 -        nlElseCheckBox.putClientProperty(OPTION_ID, placeElseOnNewLine);
   85.68 -        nlWhileCheckBox.putClientProperty(OPTION_ID, placeWhileOnNewLine);
   85.69 -        nlCatchCheckBox.putClientProperty(OPTION_ID, placeCatchOnNewLine);
   85.70 -        nlFinallyCheckBox.putClientProperty(OPTION_ID, placeFinallyOnNewLine);
   85.71 -        nlModifiersCheckBox.putClientProperty(OPTION_ID, placeNewLineAfterModifiers);
   85.72 -        amMethodParamsCheckBox.putClientProperty(OPTION_ID, alignMultilineMethodParams);
   85.73 -        amCallArgsCheckBox.putClientProperty(OPTION_ID, alignMultilineCallArgs);
   85.74 -        amAnnotationArgsCheckBox.putClientProperty(OPTION_ID, alignMultilineAnnotationArgs);
   85.75 -        amArrayInitCheckBox1.putClientProperty(OPTION_ID, alignMultilineArrayInit);
   85.76 -        amAssignCheckBox1.putClientProperty(OPTION_ID, alignMultilineAssignment);
   85.77 -        amBinaryOpCheckBox1.putClientProperty(OPTION_ID, alignMultilineBinaryOp);
   85.78 -        amForCheckBox1.putClientProperty(OPTION_ID, alignMultilineFor);
   85.79 -        amImplementsCheckBox1.putClientProperty(OPTION_ID, alignMultilineImplements);
   85.80 -        amParenthesizedCheckBox1.putClientProperty(OPTION_ID, alignMultilineParenthesized);
   85.81 -        amTernaryOpCheckBox1.putClientProperty(OPTION_ID, alignMultilineTernaryOp);
   85.82 -        amThrowsCheckBox1.putClientProperty(OPTION_ID, alignMultilineThrows);
   85.83 -    }
   85.84 -    
   85.85 -    public static PreferencesCustomizer.Factory getController() {
   85.86 -        return new CategorySupport.Factory("alignment", FmtAlignment.class, //NOI18N
   85.87 -                org.openide.util.NbBundle.getMessage(FmtAlignment.class, "SAMPLE_AlignBraces"), // NOI18N
   85.88 -                new String[] { FmtOptions.wrapAnnotations, WrapStyle.WRAP_ALWAYS.name() },
   85.89 -                new String[] { FmtOptions.wrapArrayInit, WrapStyle.WRAP_ALWAYS.name() },
   85.90 -                new String[] { FmtOptions.wrapAssert, WrapStyle.WRAP_ALWAYS.name() },
   85.91 -                new String[] { FmtOptions.wrapAssignOps, WrapStyle.WRAP_ALWAYS.name() },
   85.92 -                new String[] { FmtOptions.wrapBinaryOps, WrapStyle.WRAP_ALWAYS.name() },
   85.93 -                new String[] { FmtOptions.wrapChainedMethodCalls, WrapStyle.WRAP_ALWAYS.name() },
   85.94 -                new String[] { FmtOptions.wrapDoWhileStatement, WrapStyle.WRAP_ALWAYS.name() },
   85.95 -                new String[] { FmtOptions.wrapEnumConstants, WrapStyle.WRAP_ALWAYS.name() },
   85.96 -                new String[] { FmtOptions.wrapExtendsImplementsKeyword, WrapStyle.WRAP_ALWAYS.name() },
   85.97 -                new String[] { FmtOptions.wrapExtendsImplementsList, WrapStyle.WRAP_ALWAYS.name() },
   85.98 -                new String[] { FmtOptions.wrapFor, WrapStyle.WRAP_ALWAYS.name() },
   85.99 -                new String[] { FmtOptions.wrapForStatement, WrapStyle.WRAP_ALWAYS.name() },
  85.100 -                new String[] { FmtOptions.wrapIfStatement, WrapStyle.WRAP_ALWAYS.name() },
  85.101 -                new String[] { FmtOptions.wrapMethodCallArgs, WrapStyle.WRAP_ALWAYS.name() },
  85.102 -                new String[] { FmtOptions.wrapAnnotationArgs, WrapStyle.WRAP_ALWAYS.name() },
  85.103 -                new String[] { FmtOptions.wrapMethodParams, WrapStyle.WRAP_ALWAYS.name() },
  85.104 -                new String[] { FmtOptions.wrapTernaryOps, WrapStyle.WRAP_ALWAYS.name() },
  85.105 -                new String[] { FmtOptions.wrapThrowsKeyword, WrapStyle.WRAP_ALWAYS.name() },
  85.106 -                new String[] { FmtOptions.wrapThrowsList, WrapStyle.WRAP_ALWAYS.name() },
  85.107 -                new String[] { FmtOptions.wrapWhileStatement, WrapStyle.WRAP_ALWAYS.name() }  );
  85.108 - */
  85.109 -    }
  85.110 -    
  85.111 -    /** This method is called from within the constructor to
  85.112 -     * initialize the form.
  85.113 -     * WARNING: Do NOT modify this code. The content of this method is
  85.114 -     * always regenerated by the Form Editor.
  85.115 -     */
  85.116 -    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  85.117 -    private void initComponents() {
  85.118 -
  85.119 -        newLinesLabel = new javax.swing.JLabel();
  85.120 -        nlElseCheckBox = new javax.swing.JCheckBox();
  85.121 -        nlWhileCheckBox = new javax.swing.JCheckBox();
  85.122 -        nlCatchCheckBox = new javax.swing.JCheckBox();
  85.123 -        nlFinallyCheckBox = new javax.swing.JCheckBox();
  85.124 -        nlModifiersCheckBox = new javax.swing.JCheckBox();
  85.125 -        multilineAlignmentLabel = new javax.swing.JLabel();
  85.126 -        amMethodParamsCheckBox = new javax.swing.JCheckBox();
  85.127 -        amCallArgsCheckBox = new javax.swing.JCheckBox();
  85.128 -        amAnnotationArgsCheckBox = new javax.swing.JCheckBox();
  85.129 -        amImplementsCheckBox1 = new javax.swing.JCheckBox();
  85.130 -        amThrowsCheckBox1 = new javax.swing.JCheckBox();
  85.131 -        amArrayInitCheckBox1 = new javax.swing.JCheckBox();
  85.132 -        amBinaryOpCheckBox1 = new javax.swing.JCheckBox();
  85.133 -        amTernaryOpCheckBox1 = new javax.swing.JCheckBox();
  85.134 -        amAssignCheckBox1 = new javax.swing.JCheckBox();
  85.135 -        amForCheckBox1 = new javax.swing.JCheckBox();
  85.136 -        amParenthesizedCheckBox1 = new javax.swing.JCheckBox();
  85.137 -        jSeparator1 = new javax.swing.JSeparator();
  85.138 -        jSeparator2 = new javax.swing.JSeparator();
  85.139 -
  85.140 -        setName(org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_Alignment")); // NOI18N
  85.141 -        setOpaque(false);
  85.142 -
  85.143 -        org.openide.awt.Mnemonics.setLocalizedText(newLinesLabel, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_al_newLines")); // NOI18N
  85.144 -
  85.145 -        org.openide.awt.Mnemonics.setLocalizedText(nlElseCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Else")); // NOI18N
  85.146 -        nlElseCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.147 -
  85.148 -        org.openide.awt.Mnemonics.setLocalizedText(nlWhileCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_While")); // NOI18N
  85.149 -        nlWhileCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.150 -
  85.151 -        org.openide.awt.Mnemonics.setLocalizedText(nlCatchCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Catch")); // NOI18N
  85.152 -        nlCatchCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.153 -
  85.154 -        org.openide.awt.Mnemonics.setLocalizedText(nlFinallyCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Finally")); // NOI18N
  85.155 -        nlFinallyCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.156 -
  85.157 -        org.openide.awt.Mnemonics.setLocalizedText(nlModifiersCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Modifiers")); // NOI18N
  85.158 -        nlModifiersCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.159 -
  85.160 -        org.openide.awt.Mnemonics.setLocalizedText(multilineAlignmentLabel, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_al_multilineAlignment")); // NOI18N
  85.161 -
  85.162 -        org.openide.awt.Mnemonics.setLocalizedText(amMethodParamsCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_MethodParams")); // NOI18N
  85.163 -        amMethodParamsCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.164 -
  85.165 -        org.openide.awt.Mnemonics.setLocalizedText(amCallArgsCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_CallArgs")); // NOI18N
  85.166 -        amCallArgsCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.167 -
  85.168 -        org.openide.awt.Mnemonics.setLocalizedText(amAnnotationArgsCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_AnnotationArgs")); // NOI18N
  85.169 -        amAnnotationArgsCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.170 -
  85.171 -        org.openide.awt.Mnemonics.setLocalizedText(amImplementsCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_an_Implements")); // NOI18N
  85.172 -        amImplementsCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.173 -
  85.174 -        org.openide.awt.Mnemonics.setLocalizedText(amThrowsCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_Throws")); // NOI18N
  85.175 -        amThrowsCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.176 -
  85.177 -        org.openide.awt.Mnemonics.setLocalizedText(amArrayInitCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_ArrayInit")); // NOI18N
  85.178 -        amArrayInitCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.179 -
  85.180 -        org.openide.awt.Mnemonics.setLocalizedText(amBinaryOpCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_BinaryOp")); // NOI18N
  85.181 -        amBinaryOpCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.182 -
  85.183 -        org.openide.awt.Mnemonics.setLocalizedText(amTernaryOpCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_TernaryOp")); // NOI18N
  85.184 -        amTernaryOpCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.185 -
  85.186 -        org.openide.awt.Mnemonics.setLocalizedText(amAssignCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_Assign")); // NOI18N
  85.187 -        amAssignCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.188 -
  85.189 -        org.openide.awt.Mnemonics.setLocalizedText(amForCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_For")); // NOI18N
  85.190 -        amForCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.191 -
  85.192 -        org.openide.awt.Mnemonics.setLocalizedText(amParenthesizedCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_Paren")); // NOI18N
  85.193 -        amParenthesizedCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  85.194 -
  85.195 -        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
  85.196 -        this.setLayout(layout);
  85.197 -        layout.setHorizontalGroup(
  85.198 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  85.199 -            .addGroup(layout.createSequentialGroup()
  85.200 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  85.201 -                    .addGroup(layout.createSequentialGroup()
  85.202 -                        .addContainerGap()
  85.203 -                        .addComponent(amParenthesizedCheckBox1))
  85.204 -                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
  85.205 -                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
  85.206 -                            .addComponent(newLinesLabel)
  85.207 -                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  85.208 -                            .addComponent(jSeparator1))
  85.209 -                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
  85.210 -                            .addComponent(multilineAlignmentLabel)
  85.211 -                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  85.212 -                            .addComponent(jSeparator2))
  85.213 -                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
  85.214 -                            .addContainerGap()
  85.215 -                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  85.216 -                                .addComponent(amThrowsCheckBox1)
  85.217 -                                .addComponent(amBinaryOpCheckBox1)
  85.218 -                                .addComponent(amAssignCheckBox1)
  85.219 -                                .addComponent(amAnnotationArgsCheckBox)
  85.220 -                                .addComponent(nlElseCheckBox)
  85.221 -                                .addComponent(nlWhileCheckBox)
  85.222 -                                .addComponent(nlCatchCheckBox)
  85.223 -                                .addComponent(amMethodParamsCheckBox))
  85.224 -                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  85.225 -                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  85.226 -                                .addComponent(amCallArgsCheckBox)
  85.227 -                                .addComponent(nlModifiersCheckBox)
  85.228 -                                .addComponent(nlFinallyCheckBox)
  85.229 -                                .addComponent(amImplementsCheckBox1)
  85.230 -                                .addComponent(amArrayInitCheckBox1)
  85.231 -                                .addComponent(amTernaryOpCheckBox1)
  85.232 -                                .addComponent(amForCheckBox1)))))
  85.233 -                .addGap(0, 0, 0))
  85.234 -        );
  85.235 -        layout.setVerticalGroup(
  85.236 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  85.237 -            .addGroup(layout.createSequentialGroup()
  85.238 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  85.239 -                    .addGroup(layout.createSequentialGroup()
  85.240 -                        .addContainerGap()
  85.241 -                        .addComponent(newLinesLabel))
  85.242 -                    .addGroup(layout.createSequentialGroup()
  85.243 -                        .addGap(17, 17, 17)
  85.244 -                        .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)))
  85.245 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  85.246 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  85.247 -                    .addComponent(nlElseCheckBox)
  85.248 -                    .addComponent(nlFinallyCheckBox))
  85.249 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  85.250 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  85.251 -                    .addComponent(nlWhileCheckBox)
  85.252 -                    .addComponent(nlModifiersCheckBox))
  85.253 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  85.254 -                    .addGroup(layout.createSequentialGroup()
  85.255 -                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  85.256 -                        .addComponent(nlCatchCheckBox)
  85.257 -                        .addGap(18, 18, 18)
  85.258 -                        .addComponent(multilineAlignmentLabel))
  85.259 -                    .addGroup(layout.createSequentialGroup()
  85.260 -                        .addGap(44, 44, 44)
  85.261 -                        .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)))
  85.262 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  85.263 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  85.264 -                    .addComponent(amMethodParamsCheckBox)
  85.265 -                    .addComponent(amCallArgsCheckBox))
  85.266 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  85.267 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  85.268 -                    .addComponent(amAnnotationArgsCheckBox)
  85.269 -                    .addComponent(amImplementsCheckBox1))
  85.270 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  85.271 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  85.272 -                    .addComponent(amThrowsCheckBox1)
  85.273 -                    .addComponent(amArrayInitCheckBox1))
  85.274 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  85.275 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  85.276 -                    .addComponent(amBinaryOpCheckBox1)
  85.277 -                    .addComponent(amTernaryOpCheckBox1))
  85.278 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  85.279 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  85.280 -                    .addComponent(amAssignCheckBox1)
  85.281 -                    .addComponent(amForCheckBox1))
  85.282 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  85.283 -                .addComponent(amParenthesizedCheckBox1)
  85.284 -                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  85.285 -        );
  85.286 -    }// </editor-fold>//GEN-END:initComponents
  85.287 -    
  85.288 -    
  85.289 -    // Variables declaration - do not modify//GEN-BEGIN:variables
  85.290 -    private javax.swing.JCheckBox amAnnotationArgsCheckBox;
  85.291 -    private javax.swing.JCheckBox amArrayInitCheckBox1;
  85.292 -    private javax.swing.JCheckBox amAssignCheckBox1;
  85.293 -    private javax.swing.JCheckBox amBinaryOpCheckBox1;
  85.294 -    private javax.swing.JCheckBox amCallArgsCheckBox;
  85.295 -    private javax.swing.JCheckBox amForCheckBox1;
  85.296 -    private javax.swing.JCheckBox amImplementsCheckBox1;
  85.297 -    private javax.swing.JCheckBox amMethodParamsCheckBox;
  85.298 -    private javax.swing.JCheckBox amParenthesizedCheckBox1;
  85.299 -    private javax.swing.JCheckBox amTernaryOpCheckBox1;
  85.300 -    private javax.swing.JCheckBox amThrowsCheckBox1;
  85.301 -    private javax.swing.JSeparator jSeparator1;
  85.302 -    private javax.swing.JSeparator jSeparator2;
  85.303 -    private javax.swing.JLabel multilineAlignmentLabel;
  85.304 -    private javax.swing.JLabel newLinesLabel;
  85.305 -    private javax.swing.JCheckBox nlCatchCheckBox;
  85.306 -    private javax.swing.JCheckBox nlElseCheckBox;
  85.307 -    private javax.swing.JCheckBox nlFinallyCheckBox;
  85.308 -    private javax.swing.JCheckBox nlModifiersCheckBox;
  85.309 -    private javax.swing.JCheckBox nlWhileCheckBox;
  85.310 -    // End of variables declaration//GEN-END:variables
  85.311 -    
  85.312 -}
    86.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtBlankLines.form	Fri Sep 18 16:20:24 2015 -0500
    86.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.3 @@ -1,284 +0,0 @@
    86.4 -<?xml version="1.0" encoding="UTF-8" ?>
    86.5 -
    86.6 -<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    86.7 -  <Properties>
    86.8 -    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    86.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;)"/>
   86.10 -    </Property>
   86.11 -    <Property name="opaque" type="boolean" value="false"/>
   86.12 -  </Properties>
   86.13 -  <AuxValues>
   86.14 -    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   86.15 -    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   86.16 -    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   86.17 -    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
   86.18 -    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   86.19 -    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
   86.20 -    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
   86.21 -    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   86.22 -    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   86.23 -  </AuxValues>
   86.24 -
   86.25 -  <Layout>
   86.26 -    <DimensionLayout dim="0">
   86.27 -      <Group type="103" groupAlignment="0" attributes="0">
   86.28 -          <Group type="102" attributes="0">
   86.29 -              <Group type="103" groupAlignment="0" attributes="0">
   86.30 -                  <Component id="bPackageLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   86.31 -                  <Component id="aPackageLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   86.32 -                  <Component id="bImportsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   86.33 -                  <Component id="aImports" alignment="0" min="-2" max="-2" attributes="0"/>
   86.34 -                  <Component id="bClassLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   86.35 -                  <Component id="aClassLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   86.36 -                  <Component id="aClassHeaderLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   86.37 -                  <Component id="bFieldsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   86.38 -                  <Component id="aFieldsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   86.39 -                  <Component id="bMethodsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   86.40 -                  <Component id="aMethodsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
   86.41 -              </Group>
   86.42 -              <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
   86.43 -              <Group type="103" groupAlignment="0" attributes="0">
   86.44 -                  <Component id="aMethodsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   86.45 -                  <Component id="bMethodsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   86.46 -                  <Component id="aFieldsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   86.47 -                  <Component id="bFieldsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   86.48 -                  <Component id="aClassHeaderField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   86.49 -                  <Component id="aClassField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   86.50 -                  <Component id="bClassField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   86.51 -                  <Component id="aImportsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   86.52 -                  <Component id="bImportsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   86.53 -                  <Component id="aPackageField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   86.54 -                  <Component id="bPackageField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
   86.55 -              </Group>
   86.56 -          </Group>
   86.57 -      </Group>
   86.58 -    </DimensionLayout>
   86.59 -    <DimensionLayout dim="1">
   86.60 -      <Group type="103" groupAlignment="0" attributes="0">
   86.61 -          <Group type="102" attributes="0">
   86.62 -              <Group type="103" groupAlignment="3" attributes="0">
   86.63 -                  <Component id="bPackageField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   86.64 -                  <Component id="bPackageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   86.65 -              </Group>
   86.66 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
   86.67 -              <Group type="103" groupAlignment="3" attributes="0">
   86.68 -                  <Component id="aPackageField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   86.69 -                  <Component id="aPackageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   86.70 -              </Group>
   86.71 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
   86.72 -              <Group type="103" groupAlignment="3" attributes="0">
   86.73 -                  <Component id="bImportsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   86.74 -                  <Component id="bImportsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   86.75 -              </Group>
   86.76 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
   86.77 -              <Group type="103" groupAlignment="3" attributes="0">
   86.78 -                  <Component id="aImportsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   86.79 -                  <Component id="aImports" alignment="3" min="-2" max="-2" attributes="0"/>
   86.80 -              </Group>
   86.81 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
   86.82 -              <Group type="103" groupAlignment="3" attributes="0">
   86.83 -                  <Component id="bClassField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   86.84 -                  <Component id="bClassLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   86.85 -              </Group>
   86.86 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
   86.87 -              <Group type="103" groupAlignment="3" attributes="0">
   86.88 -                  <Component id="aClassField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   86.89 -                  <Component id="aClassLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   86.90 -              </Group>
   86.91 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
   86.92 -              <Group type="103" groupAlignment="3" attributes="0">
   86.93 -                  <Component id="aClassHeaderField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   86.94 -                  <Component id="aClassHeaderLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   86.95 -              </Group>
   86.96 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
   86.97 -              <Group type="103" groupAlignment="3" attributes="0">
   86.98 -                  <Component id="bFieldsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
   86.99 -                  <Component id="bFieldsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  86.100 -              </Group>
  86.101 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  86.102 -              <Group type="103" groupAlignment="3" attributes="0">
  86.103 -                  <Component id="aFieldsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  86.104 -                  <Component id="aFieldsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  86.105 -              </Group>
  86.106 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  86.107 -              <Group type="103" groupAlignment="3" attributes="0">
  86.108 -                  <Component id="bMethodsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  86.109 -                  <Component id="bMethodsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  86.110 -              </Group>
  86.111 -              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  86.112 -              <Group type="103" groupAlignment="3" attributes="0">
  86.113 -                  <Component id="aMethodsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  86.114 -                  <Component id="aMethodsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  86.115 -              </Group>
  86.116 -          </Group>
  86.117 -      </Group>
  86.118 -    </DimensionLayout>
  86.119 -  </Layout>
  86.120 -  <SubComponents>
  86.121 -    <Component class="javax.swing.JLabel" name="bPackageLabel">
  86.122 -      <Properties>
  86.123 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  86.124 -          <ComponentRef name="bPackageField"/>
  86.125 -        </Property>
  86.126 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  86.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;)"/>
  86.128 -        </Property>
  86.129 -      </Properties>
  86.130 -    </Component>
  86.131 -    <Component class="javax.swing.JTextField" name="bPackageField">
  86.132 -      <Properties>
  86.133 -        <Property name="columns" type="int" value="5"/>
  86.134 -      </Properties>
  86.135 -    </Component>
  86.136 -    <Component class="javax.swing.JLabel" name="aPackageLabel">
  86.137 -      <Properties>
  86.138 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  86.139 -          <ComponentRef name="aPackageField"/>
  86.140 -        </Property>
  86.141 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  86.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;)"/>
  86.143 -        </Property>
  86.144 -      </Properties>
  86.145 -    </Component>
  86.146 -    <Component class="javax.swing.JTextField" name="aPackageField">
  86.147 -      <Properties>
  86.148 -        <Property name="columns" type="int" value="5"/>
  86.149 -      </Properties>
  86.150 -    </Component>
  86.151 -    <Component class="javax.swing.JLabel" name="bImportsLabel">
  86.152 -      <Properties>
  86.153 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  86.154 -          <ComponentRef name="bImportsField"/>
  86.155 -        </Property>
  86.156 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  86.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;)"/>
  86.158 -        </Property>
  86.159 -      </Properties>
  86.160 -    </Component>
  86.161 -    <Component class="javax.swing.JTextField" name="bImportsField">
  86.162 -      <Properties>
  86.163 -        <Property name="columns" type="int" value="5"/>
  86.164 -      </Properties>
  86.165 -    </Component>
  86.166 -    <Component class="javax.swing.JLabel" name="aImports">
  86.167 -      <Properties>
  86.168 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  86.169 -          <ComponentRef name="aImportsField"/>
  86.170 -        </Property>
  86.171 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  86.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;)"/>
  86.173 -        </Property>
  86.174 -      </Properties>
  86.175 -    </Component>
  86.176 -    <Component class="javax.swing.JTextField" name="aImportsField">
  86.177 -      <Properties>
  86.178 -        <Property name="columns" type="int" value="5"/>
  86.179 -      </Properties>
  86.180 -    </Component>
  86.181 -    <Component class="javax.swing.JLabel" name="bClassLabel">
  86.182 -      <Properties>
  86.183 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  86.184 -          <ComponentRef name="bClassField"/>
  86.185 -        </Property>
  86.186 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  86.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;)"/>
  86.188 -        </Property>
  86.189 -      </Properties>
  86.190 -    </Component>
  86.191 -    <Component class="javax.swing.JTextField" name="bClassField">
  86.192 -      <Properties>
  86.193 -        <Property name="columns" type="int" value="5"/>
  86.194 -      </Properties>
  86.195 -    </Component>
  86.196 -    <Component class="javax.swing.JLabel" name="aClassLabel">
  86.197 -      <Properties>
  86.198 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  86.199 -          <ComponentRef name="aClassField"/>
  86.200 -        </Property>
  86.201 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  86.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;)"/>
  86.203 -        </Property>
  86.204 -      </Properties>
  86.205 -    </Component>
  86.206 -    <Component class="javax.swing.JTextField" name="aClassField">
  86.207 -      <Properties>
  86.208 -        <Property name="columns" type="int" value="5"/>
  86.209 -      </Properties>
  86.210 -    </Component>
  86.211 -    <Component class="javax.swing.JLabel" name="aClassHeaderLabel">
  86.212 -      <Properties>
  86.213 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  86.214 -          <ComponentRef name="aClassHeaderField"/>
  86.215 -        </Property>
  86.216 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  86.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;)"/>
  86.218 -        </Property>
  86.219 -      </Properties>
  86.220 -    </Component>
  86.221 -    <Component class="javax.swing.JTextField" name="aClassHeaderField">
  86.222 -      <Properties>
  86.223 -        <Property name="columns" type="int" value="5"/>
  86.224 -      </Properties>
  86.225 -    </Component>
  86.226 -    <Component class="javax.swing.JLabel" name="bFieldsLabel">
  86.227 -      <Properties>
  86.228 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  86.229 -          <ComponentRef name="bFieldsField"/>
  86.230 -        </Property>
  86.231 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  86.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;)"/>
  86.233 -        </Property>
  86.234 -      </Properties>
  86.235 -    </Component>
  86.236 -    <Component class="javax.swing.JTextField" name="bFieldsField">
  86.237 -      <Properties>
  86.238 -        <Property name="columns" type="int" value="5"/>
  86.239 -      </Properties>
  86.240 -    </Component>
  86.241 -    <Component class="javax.swing.JLabel" name="aFieldsLabel">
  86.242 -      <Properties>
  86.243 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  86.244 -          <ComponentRef name="aFieldsField"/>
  86.245 -        </Property>
  86.246 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  86.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;)"/>
  86.248 -        </Property>
  86.249 -      </Properties>
  86.250 -    </Component>
  86.251 -    <Component class="javax.swing.JTextField" name="aFieldsField">
  86.252 -      <Properties>
  86.253 -        <Property name="columns" type="int" value="5"/>
  86.254 -      </Properties>
  86.255 -    </Component>
  86.256 -    <Component class="javax.swing.JLabel" name="bMethodsLabel">
  86.257 -      <Properties>
  86.258 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  86.259 -          <ComponentRef name="bMethodsField"/>
  86.260 -        </Property>
  86.261 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  86.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;)"/>
  86.263 -        </Property>
  86.264 -      </Properties>
  86.265 -    </Component>
  86.266 -    <Component class="javax.swing.JTextField" name="bMethodsField">
  86.267 -      <Properties>
  86.268 -        <Property name="columns" type="int" value="5"/>
  86.269 -      </Properties>
  86.270 -    </Component>
  86.271 -    <Component class="javax.swing.JLabel" name="aMethodsLabel">
  86.272 -      <Properties>
  86.273 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  86.274 -          <ComponentRef name="aMethodsField"/>
  86.275 -        </Property>
  86.276 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  86.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;)"/>
  86.278 -        </Property>
  86.279 -      </Properties>
  86.280 -    </Component>
  86.281 -    <Component class="javax.swing.JTextField" name="aMethodsField">
  86.282 -      <Properties>
  86.283 -        <Property name="columns" type="int" value="5"/>
  86.284 -      </Properties>
  86.285 -    </Component>
  86.286 -  </SubComponents>
  86.287 -</Form>
    87.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtBlankLines.java	Fri Sep 18 16:20:24 2015 -0500
    87.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.3 @@ -1,295 +0,0 @@
    87.4 -/*
    87.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    87.6 - *
    87.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    87.8 - *
    87.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   87.10 - * Other names may be trademarks of their respective owners.
   87.11 - *
   87.12 - * The contents of this file are subject to the terms of either the GNU
   87.13 - * General Public License Version 2 only ("GPL") or the Common
   87.14 - * Development and Distribution License("CDDL") (collectively, the
   87.15 - * "License"). You may not use this file except in compliance with the
   87.16 - * License. You can obtain a copy of the License at
   87.17 - * http://www.netbeans.org/cddl-gplv2.html
   87.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   87.19 - * specific language governing permissions and limitations under the
   87.20 - * License.  When distributing the software, include this License Header
   87.21 - * Notice in each file and include the License file at
   87.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   87.23 - * particular file as subject to the "Classpath" exception as provided
   87.24 - * by Oracle in the GPL Version 2 section of the License file that
   87.25 - * accompanied this code. If applicable, add the following below the
   87.26 - * License Header, with the fields enclosed by brackets [] replaced by
   87.27 - * your own identifying information:
   87.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   87.29 - *
   87.30 - * Contributor(s):
   87.31 - *
   87.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   87.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   87.34 - * Microsystems, Inc. All Rights Reserved.
   87.35 - *
   87.36 - * If you wish your version of this file to be governed by only the CDDL
   87.37 - * or only the GPL Version 2, indicate your decision by adding
   87.38 - * "[Contributor] elects to include this software in this distribution
   87.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   87.40 - * single choice of license, a recipient has the option to distribute
   87.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   87.42 - * to extend the choice of license to its licensees as provided above.
   87.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   87.44 - * Version 2 license, then the option applies only if the new code is
   87.45 - * made subject to such option by the copyright holder.
   87.46 - */
   87.47 -
   87.48 -package org.netbeans.modules.python.editor.options;
   87.49 -
   87.50 -import static org.netbeans.modules.python.editor.options.FmtOptions.*;
   87.51 -import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
   87.52 -import org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport;
   87.53 -import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
   87.54 -
   87.55 -/**
   87.56 - *
   87.57 - * @author  phrebejk
   87.58 - */
   87.59 -public class FmtBlankLines extends javax.swing.JPanel {
   87.60 -    
   87.61 -    /** Creates new form FmtBlankLines */
   87.62 -    public FmtBlankLines() {
   87.63 -        initComponents();
   87.64 -/*
   87.65 -        bPackageField.putClientProperty(OPTION_ID, blankLinesBeforePackage );
   87.66 -        aPackageField.putClientProperty(OPTION_ID, blankLinesAfterPackage);
   87.67 -        bImportsField.putClientProperty(OPTION_ID, blankLinesBeforeImports);
   87.68 -        aImportsField.putClientProperty(OPTION_ID, blankLinesAfterImports);
   87.69 -        bClassField.putClientProperty(OPTION_ID, blankLinesBeforeClass);
   87.70 -        aClassField.putClientProperty(OPTION_ID, blankLinesAfterClass);
   87.71 -        aClassHeaderField.putClientProperty(OPTION_ID, blankLinesAfterClassHeader);
   87.72 -        bFieldsField.putClientProperty(OPTION_ID, blankLinesBeforeFields);
   87.73 -        aFieldsField.putClientProperty(OPTION_ID, blankLinesAfterFields);
   87.74 -        bMethodsField.putClientProperty(OPTION_ID, blankLinesBeforeMethods );
   87.75 -        aMethodsField.putClientProperty(OPTION_ID, blankLinesAfterMethods);
   87.76 -        
   87.77 -        bPackageField.addKeyListener(new NumericKeyListener());
   87.78 -        aPackageField.addKeyListener(new NumericKeyListener());
   87.79 -        bImportsField.addKeyListener(new NumericKeyListener());
   87.80 -        aImportsField.addKeyListener(new NumericKeyListener());
   87.81 -        bClassField.addKeyListener(new NumericKeyListener());
   87.82 -        aClassField.addKeyListener(new NumericKeyListener());
   87.83 -        aClassHeaderField.addKeyListener(new NumericKeyListener());
   87.84 -        bFieldsField.addKeyListener(new NumericKeyListener());
   87.85 -        aFieldsField.addKeyListener(new NumericKeyListener());
   87.86 -        bMethodsField.addKeyListener(new NumericKeyListener());
   87.87 -        aMethodsField.addKeyListener(new NumericKeyListener());
   87.88 -        
   87.89 -    }
   87.90 -    
   87.91 -    public static PreferencesCustomizer.Factory getController() {
   87.92 -        return new CategorySupport.Factory("blank-lines", FmtBlankLines.class, //NOI18N
   87.93 -                 org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "SAMPLE_BlankLines")); // NOI18N
   87.94 - */
   87.95 -    }
   87.96 -    
   87.97 -    /** This method is called from within the constructor to
   87.98 -     * initialize the form.
   87.99 -     * WARNING: Do NOT modify this code. The content of this method is
  87.100 -     * always regenerated by the Form Editor.
  87.101 -     */
  87.102 -    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  87.103 -    private void initComponents() {
  87.104 -
  87.105 -        bPackageLabel = new javax.swing.JLabel();
  87.106 -        bPackageField = new javax.swing.JTextField();
  87.107 -        aPackageLabel = new javax.swing.JLabel();
  87.108 -        aPackageField = new javax.swing.JTextField();
  87.109 -        bImportsLabel = new javax.swing.JLabel();
  87.110 -        bImportsField = new javax.swing.JTextField();
  87.111 -        aImports = new javax.swing.JLabel();
  87.112 -        aImportsField = new javax.swing.JTextField();
  87.113 -        bClassLabel = new javax.swing.JLabel();
  87.114 -        bClassField = new javax.swing.JTextField();
  87.115 -        aClassLabel = new javax.swing.JLabel();
  87.116 -        aClassField = new javax.swing.JTextField();
  87.117 -        aClassHeaderLabel = new javax.swing.JLabel();
  87.118 -        aClassHeaderField = new javax.swing.JTextField();
  87.119 -        bFieldsLabel = new javax.swing.JLabel();
  87.120 -        bFieldsField = new javax.swing.JTextField();
  87.121 -        aFieldsLabel = new javax.swing.JLabel();
  87.122 -        aFieldsField = new javax.swing.JTextField();
  87.123 -        bMethodsLabel = new javax.swing.JLabel();
  87.124 -        bMethodsField = new javax.swing.JTextField();
  87.125 -        aMethodsLabel = new javax.swing.JLabel();
  87.126 -        aMethodsField = new javax.swing.JTextField();
  87.127 -
  87.128 -        setName(org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_BlankLines")); // NOI18N
  87.129 -        setOpaque(false);
  87.130 -
  87.131 -        bPackageLabel.setLabelFor(bPackageField);
  87.132 -        org.openide.awt.Mnemonics.setLocalizedText(bPackageLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforePackage")); // NOI18N
  87.133 -
  87.134 -        bPackageField.setColumns(5);
  87.135 -
  87.136 -        aPackageLabel.setLabelFor(aPackageField);
  87.137 -        org.openide.awt.Mnemonics.setLocalizedText(aPackageLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterPackage")); // NOI18N
  87.138 -
  87.139 -        aPackageField.setColumns(5);
  87.140 -
  87.141 -        bImportsLabel.setLabelFor(bImportsField);
  87.142 -        org.openide.awt.Mnemonics.setLocalizedText(bImportsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeImports")); // NOI18N
  87.143 -
  87.144 -        bImportsField.setColumns(5);
  87.145 -
  87.146 -        aImports.setLabelFor(aImportsField);
  87.147 -        org.openide.awt.Mnemonics.setLocalizedText(aImports, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterImports")); // NOI18N
  87.148 -
  87.149 -        aImportsField.setColumns(5);
  87.150 -
  87.151 -        bClassLabel.setLabelFor(bClassField);
  87.152 -        org.openide.awt.Mnemonics.setLocalizedText(bClassLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeClass")); // NOI18N
  87.153 -
  87.154 -        bClassField.setColumns(5);
  87.155 -
  87.156 -        aClassLabel.setLabelFor(aClassField);
  87.157 -        org.openide.awt.Mnemonics.setLocalizedText(aClassLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterClass")); // NOI18N
  87.158 -
  87.159 -        aClassField.setColumns(5);
  87.160 -
  87.161 -        aClassHeaderLabel.setLabelFor(aClassHeaderField);
  87.162 -        org.openide.awt.Mnemonics.setLocalizedText(aClassHeaderLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterClassHeader")); // NOI18N
  87.163 -
  87.164 -        aClassHeaderField.setColumns(5);
  87.165 -
  87.166 -        bFieldsLabel.setLabelFor(bFieldsField);
  87.167 -        org.openide.awt.Mnemonics.setLocalizedText(bFieldsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeFields")); // NOI18N
  87.168 -
  87.169 -        bFieldsField.setColumns(5);
  87.170 -
  87.171 -        aFieldsLabel.setLabelFor(aFieldsField);
  87.172 -        org.openide.awt.Mnemonics.setLocalizedText(aFieldsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterFields")); // NOI18N
  87.173 -
  87.174 -        aFieldsField.setColumns(5);
  87.175 -
  87.176 -        bMethodsLabel.setLabelFor(bMethodsField);
  87.177 -        org.openide.awt.Mnemonics.setLocalizedText(bMethodsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeMethods")); // NOI18N
  87.178 -
  87.179 -        bMethodsField.setColumns(5);
  87.180 -
  87.181 -        aMethodsLabel.setLabelFor(aMethodsField);
  87.182 -        org.openide.awt.Mnemonics.setLocalizedText(aMethodsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterMethods")); // NOI18N
  87.183 -
  87.184 -        aMethodsField.setColumns(5);
  87.185 -
  87.186 -        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
  87.187 -        this.setLayout(layout);
  87.188 -        layout.setHorizontalGroup(
  87.189 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  87.190 -            .addGroup(layout.createSequentialGroup()
  87.191 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  87.192 -                    .addComponent(bPackageLabel)
  87.193 -                    .addComponent(aPackageLabel)
  87.194 -                    .addComponent(bImportsLabel)
  87.195 -                    .addComponent(aImports)
  87.196 -                    .addComponent(bClassLabel)
  87.197 -                    .addComponent(aClassLabel)
  87.198 -                    .addComponent(aClassHeaderLabel)
  87.199 -                    .addComponent(bFieldsLabel)
  87.200 -                    .addComponent(aFieldsLabel)
  87.201 -                    .addComponent(bMethodsLabel)
  87.202 -                    .addComponent(aMethodsLabel))
  87.203 -                .addGap(6, 6, 6)
  87.204 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  87.205 -                    .addComponent(aMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.206 -                    .addComponent(bMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.207 -                    .addComponent(aFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.208 -                    .addComponent(bFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.209 -                    .addComponent(aClassHeaderField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.210 -                    .addComponent(aClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.211 -                    .addComponent(bClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.212 -                    .addComponent(aImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.213 -                    .addComponent(bImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.214 -                    .addComponent(aPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.215 -                    .addComponent(bPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
  87.216 -        );
  87.217 -
  87.218 -        layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {aClassField, aClassHeaderField, aFieldsField, aImportsField, aMethodsField, aPackageField, bClassField, bFieldsField, bImportsField, bMethodsField, bPackageField});
  87.219 -
  87.220 -        layout.setVerticalGroup(
  87.221 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  87.222 -            .addGroup(layout.createSequentialGroup()
  87.223 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  87.224 -                    .addComponent(bPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.225 -                    .addComponent(bPackageLabel))
  87.226 -                .addGap(4, 4, 4)
  87.227 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  87.228 -                    .addComponent(aPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.229 -                    .addComponent(aPackageLabel))
  87.230 -                .addGap(4, 4, 4)
  87.231 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  87.232 -                    .addComponent(bImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.233 -                    .addComponent(bImportsLabel))
  87.234 -                .addGap(4, 4, 4)
  87.235 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  87.236 -                    .addComponent(aImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.237 -                    .addComponent(aImports))
  87.238 -                .addGap(4, 4, 4)
  87.239 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  87.240 -                    .addComponent(bClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.241 -                    .addComponent(bClassLabel))
  87.242 -                .addGap(4, 4, 4)
  87.243 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  87.244 -                    .addComponent(aClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.245 -                    .addComponent(aClassLabel))
  87.246 -                .addGap(4, 4, 4)
  87.247 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  87.248 -                    .addComponent(aClassHeaderField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.249 -                    .addComponent(aClassHeaderLabel))
  87.250 -                .addGap(4, 4, 4)
  87.251 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  87.252 -                    .addComponent(bFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.253 -                    .addComponent(bFieldsLabel))
  87.254 -                .addGap(4, 4, 4)
  87.255 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  87.256 -                    .addComponent(aFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.257 -                    .addComponent(aFieldsLabel))
  87.258 -                .addGap(4, 4, 4)
  87.259 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  87.260 -                    .addComponent(bMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.261 -                    .addComponent(bMethodsLabel))
  87.262 -                .addGap(4, 4, 4)
  87.263 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  87.264 -                    .addComponent(aMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
  87.265 -                    .addComponent(aMethodsLabel)))
  87.266 -        );
  87.267 -
  87.268 -        layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {aClassField, aClassHeaderField, aFieldsField, aImportsField, aMethodsField, aPackageField, bClassField, bFieldsField, bImportsField, bMethodsField, bPackageField});
  87.269 -
  87.270 -    }// </editor-fold>//GEN-END:initComponents
  87.271 -    
  87.272 -    
  87.273 -    // Variables declaration - do not modify//GEN-BEGIN:variables
  87.274 -    private javax.swing.JTextField aClassField;
  87.275 -    private javax.swing.JTextField aClassHeaderField;
  87.276 -    private javax.swing.JLabel aClassHeaderLabel;
  87.277 -    private javax.swing.JLabel aClassLabel;
  87.278 -    private javax.swing.JTextField aFieldsField;
  87.279 -    private javax.swing.JLabel aFieldsLabel;
  87.280 -    private javax.swing.JLabel aImports;
  87.281 -    private javax.swing.JTextField aImportsField;
  87.282 -    private javax.swing.JTextField aMethodsField;
  87.283 -    private javax.swing.JLabel aMethodsLabel;
  87.284 -    private javax.swing.JTextField aPackageField;
  87.285 -    private javax.swing.JLabel aPackageLabel;
  87.286 -    private javax.swing.JTextField bClassField;
  87.287 -    private javax.swing.JLabel bClassLabel;
  87.288 -    private javax.swing.JTextField bFieldsField;
  87.289 -    private javax.swing.JLabel bFieldsLabel;
  87.290 -    private javax.swing.JTextField bImportsField;
  87.291 -    private javax.swing.JLabel bImportsLabel;
  87.292 -    private javax.swing.JTextField bMethodsField;
  87.293 -    private javax.swing.JLabel bMethodsLabel;
  87.294 -    private javax.swing.JTextField bPackageField;
  87.295 -    private javax.swing.JLabel bPackageLabel;
  87.296 -    // End of variables declaration//GEN-END:variables
  87.297 -    
  87.298 -}
    88.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtImports.form	Fri Sep 18 16:20:24 2015 -0500
    88.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.3 @@ -1,129 +0,0 @@
    88.4 -<?xml version="1.0" encoding="UTF-8" ?>
    88.5 -
    88.6 -<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    88.7 -  <Properties>
    88.8 -    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    88.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;)"/>
   88.10 -    </Property>
   88.11 -  </Properties>
   88.12 -  <AuxValues>
   88.13 -    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   88.14 -    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   88.15 -    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   88.16 -    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
   88.17 -    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   88.18 -    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
   88.19 -    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
   88.20 -    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   88.21 -    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   88.22 -  </AuxValues>
   88.23 -
   88.24 -  <Layout>
   88.25 -    <DimensionLayout dim="0">
   88.26 -      <Group type="103" groupAlignment="0" attributes="0">
   88.27 -          <Group type="102" attributes="0">
   88.28 -              <Group type="103" groupAlignment="0" attributes="0">
   88.29 -                  <Component id="formatImportsCb" alignment="0" min="-2" max="-2" attributes="0"/>
   88.30 -                  <Component id="onePerLineCb" alignment="0" min="-2" max="-2" attributes="0"/>
   88.31 -                  <Component id="systemLibsCb" alignment="0" min="-2" max="-2" attributes="0"/>
   88.32 -                  <Component id="sortImportsCb" alignment="0" min="-2" max="-2" attributes="0"/>
   88.33 -                  <Component id="sepFromImpCb" alignment="0" min="-2" max="-2" attributes="0"/>
   88.34 -                  <Component id="removeDuplicateCb" alignment="0" min="-2" max="-2" attributes="0"/>
   88.35 -                  <Component id="preferSymbols" alignment="0" min="-2" max="-2" attributes="0"/>
   88.36 -                  <Group type="102" alignment="0" attributes="0">
   88.37 -                      <Component id="cleanupLabel" min="-2" max="-2" attributes="0"/>
   88.38 -                      <EmptySpace max="-2" attributes="0"/>
   88.39 -                      <Component id="cleanupCombo" min="-2" max="-2" attributes="0"/>
   88.40 -                  </Group>
   88.41 -              </Group>
   88.42 -              <EmptySpace max="32767" attributes="0"/>
   88.43 -          </Group>
   88.44 -      </Group>
   88.45 -    </DimensionLayout>
   88.46 -    <DimensionLayout dim="1">
   88.47 -      <Group type="103" groupAlignment="0" attributes="0">
   88.48 -          <Group type="102" alignment="0" attributes="0">
   88.49 -              <Component id="formatImportsCb" min="-2" max="-2" attributes="0"/>
   88.50 -              <EmptySpace type="separate" max="-2" attributes="0"/>
   88.51 -              <Component id="onePerLineCb" min="-2" max="-2" attributes="0"/>
   88.52 -              <EmptySpace max="-2" attributes="0"/>
   88.53 -              <Component id="systemLibsCb" min="-2" max="-2" attributes="0"/>
   88.54 -              <EmptySpace max="-2" attributes="0"/>
   88.55 -              <Component id="sortImportsCb" min="-2" max="-2" attributes="0"/>
   88.56 -              <EmptySpace max="-2" attributes="0"/>
   88.57 -              <Component id="sepFromImpCb" min="-2" max="-2" attributes="0"/>
   88.58 -              <EmptySpace max="-2" attributes="0"/>
   88.59 -              <Component id="removeDuplicateCb" min="-2" max="-2" attributes="0"/>
   88.60 -              <EmptySpace max="-2" attributes="0"/>
   88.61 -              <Component id="preferSymbols" min="-2" max="-2" attributes="0"/>
   88.62 -              <EmptySpace type="separate" max="-2" attributes="0"/>
   88.63 -              <Group type="103" groupAlignment="3" attributes="0">
   88.64 -                  <Component id="cleanupLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   88.65 -                  <Component id="cleanupCombo" alignment="3" min="-2" max="-2" attributes="0"/>
   88.66 -              </Group>
   88.67 -              <EmptySpace max="32767" attributes="0"/>
   88.68 -          </Group>
   88.69 -      </Group>
   88.70 -    </DimensionLayout>
   88.71 -  </Layout>
   88.72 -  <SubComponents>
   88.73 -    <Component class="javax.swing.JCheckBox" name="formatImportsCb">
   88.74 -      <Properties>
   88.75 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   88.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;)"/>
   88.77 -        </Property>
   88.78 -      </Properties>
   88.79 -    </Component>
   88.80 -    <Component class="javax.swing.JCheckBox" name="onePerLineCb">
   88.81 -      <Properties>
   88.82 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   88.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;)"/>
   88.84 -        </Property>
   88.85 -      </Properties>
   88.86 -    </Component>
   88.87 -    <Component class="javax.swing.JCheckBox" name="systemLibsCb">
   88.88 -      <Properties>
   88.89 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   88.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;)"/>
   88.91 -        </Property>
   88.92 -      </Properties>
   88.93 -    </Component>
   88.94 -    <Component class="javax.swing.JCheckBox" name="removeDuplicateCb">
   88.95 -      <Properties>
   88.96 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   88.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;)"/>
   88.98 -        </Property>
   88.99 -      </Properties>
  88.100 -    </Component>
  88.101 -    <Component class="javax.swing.JLabel" name="cleanupLabel">
  88.102 -      <Properties>
  88.103 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  88.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;)"/>
  88.105 -        </Property>
  88.106 -      </Properties>
  88.107 -    </Component>
  88.108 -    <Component class="javax.swing.JComboBox" name="cleanupCombo">
  88.109 -    </Component>
  88.110 -    <Component class="javax.swing.JCheckBox" name="preferSymbols">
  88.111 -      <Properties>
  88.112 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  88.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;)"/>
  88.114 -        </Property>
  88.115 -      </Properties>
  88.116 -    </Component>
  88.117 -    <Component class="javax.swing.JCheckBox" name="sortImportsCb">
  88.118 -      <Properties>
  88.119 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  88.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;)"/>
  88.121 -        </Property>
  88.122 -      </Properties>
  88.123 -    </Component>
  88.124 -    <Component class="javax.swing.JCheckBox" name="sepFromImpCb">
  88.125 -      <Properties>
  88.126 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  88.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;)"/>
  88.128 -        </Property>
  88.129 -      </Properties>
  88.130 -    </Component>
  88.131 -  </SubComponents>
  88.132 -</Form>
    89.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtImports.java	Fri Sep 18 16:20:24 2015 -0500
    89.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.3 @@ -1,169 +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-2006 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 -
   89.48 -package org.netbeans.modules.python.editor.options;
   89.49 -
   89.50 -import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
   89.51 -import static org.netbeans.modules.python.editor.options.FmtOptions.*;
   89.52 -import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
   89.53 -
   89.54 -/**
   89.55 - * Options related to imports
   89.56 - * 
   89.57 - * @author  Tor Norbye
   89.58 - */
   89.59 -public class FmtImports extends javax.swing.JPanel {
   89.60 -    
   89.61 -    /** Creates new form FmtImports */
   89.62 -    public FmtImports() {
   89.63 -        initComponents();
   89.64 -
   89.65 -        formatImportsCb.putClientProperty(OPTION_ID, formatImports);
   89.66 -        onePerLineCb.putClientProperty(OPTION_ID, oneImportPerLine);
   89.67 -        removeDuplicateCb.putClientProperty(OPTION_ID, removeDuplicates);
   89.68 -        systemLibsCb.putClientProperty(OPTION_ID, systemLibsFirst);
   89.69 -        cleanupCombo.putClientProperty(OPTION_ID, cleanupUnusedImports);
   89.70 -        preferSymbols.putClientProperty(OPTION_ID, preferSymbolImports);
   89.71 -        sortImportsCb.putClientProperty(OPTION_ID, sortImports);
   89.72 -        sepFromImpCb.putClientProperty(OPTION_ID, separateFromImps);
   89.73 -    }
   89.74 -    
   89.75 -    public static PreferencesCustomizer.Factory getController() {
   89.76 -        return new CategorySupport.Factory("imports", FmtImports.class,
   89.77 -                org.openide.util.NbBundle.getMessage(FmtImports.class, "SAMPLE_Imports"));
   89.78 -    }
   89.79 -    
   89.80 -    /** This method is called from within the constructor to
   89.81 -     * initialize the form.
   89.82 -     * WARNING: Do NOT modify this code. The content of this method is
   89.83 -     * always regenerated by the Form Editor.
   89.84 -     */
   89.85 -    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
   89.86 -    private void initComponents() {
   89.87 -
   89.88 -        formatImportsCb = new javax.swing.JCheckBox();
   89.89 -        onePerLineCb = new javax.swing.JCheckBox();
   89.90 -        systemLibsCb = new javax.swing.JCheckBox();
   89.91 -        removeDuplicateCb = new javax.swing.JCheckBox();
   89.92 -        cleanupLabel = new javax.swing.JLabel();
   89.93 -        cleanupCombo = new javax.swing.JComboBox();
   89.94 -        preferSymbols = new javax.swing.JCheckBox();
   89.95 -        sortImportsCb = new javax.swing.JCheckBox();
   89.96 -        sepFromImpCb = new javax.swing.JCheckBox();
   89.97 -
   89.98 -        setName(org.openide.util.NbBundle.getMessage(FmtImports.class, "LBL_Imports")); // NOI18N
   89.99 -
  89.100 -        org.openide.awt.Mnemonics.setLocalizedText(formatImportsCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.formatImportsCb.text")); // NOI18N
  89.101 -
  89.102 -        org.openide.awt.Mnemonics.setLocalizedText(onePerLineCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.onePerLineCb.text")); // NOI18N
  89.103 -
  89.104 -        org.openide.awt.Mnemonics.setLocalizedText(systemLibsCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.systemLibsCb.text")); // NOI18N
  89.105 -
  89.106 -        org.openide.awt.Mnemonics.setLocalizedText(removeDuplicateCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.removeDuplicateCb.text")); // NOI18N
  89.107 -
  89.108 -        org.openide.awt.Mnemonics.setLocalizedText(cleanupLabel, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.cleanupLabel.text")); // NOI18N
  89.109 -
  89.110 -        org.openide.awt.Mnemonics.setLocalizedText(preferSymbols, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.preferSymbols.text")); // NOI18N
  89.111 -
  89.112 -        org.openide.awt.Mnemonics.setLocalizedText(sortImportsCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.sortImportsCb.text")); // NOI18N
  89.113 -
  89.114 -        org.openide.awt.Mnemonics.setLocalizedText(sepFromImpCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.sepFromImpCb.text")); // NOI18N
  89.115 -
  89.116 -        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
  89.117 -        this.setLayout(layout);
  89.118 -        layout.setHorizontalGroup(
  89.119 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  89.120 -            .addGroup(layout.createSequentialGroup()
  89.121 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  89.122 -                    .addComponent(formatImportsCb)
  89.123 -                    .addComponent(onePerLineCb)
  89.124 -                    .addComponent(systemLibsCb)
  89.125 -                    .addComponent(sortImportsCb)
  89.126 -                    .addComponent(sepFromImpCb)
  89.127 -                    .addComponent(removeDuplicateCb)
  89.128 -                    .addComponent(preferSymbols)
  89.129 -                    .addGroup(layout.createSequentialGroup()
  89.130 -                        .addComponent(cleanupLabel)
  89.131 -                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  89.132 -                        .addComponent(cleanupCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
  89.133 -                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  89.134 -        );
  89.135 -        layout.setVerticalGroup(
  89.136 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  89.137 -            .addGroup(layout.createSequentialGroup()
  89.138 -                .addComponent(formatImportsCb)
  89.139 -                .addGap(18, 18, 18)
  89.140 -                .addComponent(onePerLineCb)
  89.141 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  89.142 -                .addComponent(systemLibsCb)
  89.143 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  89.144 -                .addComponent(sortImportsCb)
  89.145 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  89.146 -                .addComponent(sepFromImpCb)
  89.147 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  89.148 -                .addComponent(removeDuplicateCb)
  89.149 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  89.150 -                .addComponent(preferSymbols)
  89.151 -                .addGap(18, 18, 18)
  89.152 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  89.153 -                    .addComponent(cleanupLabel)
  89.154 -                    .addComponent(cleanupCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
  89.155 -                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  89.156 -        );
  89.157 -    }// </editor-fold>//GEN-END:initComponents
  89.158 -    
  89.159 -    
  89.160 -    // Variables declaration - do not modify//GEN-BEGIN:variables
  89.161 -    private javax.swing.JComboBox cleanupCombo;
  89.162 -    private javax.swing.JLabel cleanupLabel;
  89.163 -    private javax.swing.JCheckBox formatImportsCb;
  89.164 -    private javax.swing.JCheckBox onePerLineCb;
  89.165 -    private javax.swing.JCheckBox preferSymbols;
  89.166 -    private javax.swing.JCheckBox removeDuplicateCb;
  89.167 -    private javax.swing.JCheckBox sepFromImpCb;
  89.168 -    private javax.swing.JCheckBox sortImportsCb;
  89.169 -    private javax.swing.JCheckBox systemLibsCb;
  89.170 -    // End of variables declaration//GEN-END:variables
  89.171 -    
  89.172 -}
    90.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtOptions.java	Fri Sep 18 16:20:24 2015 -0500
    90.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.3 @@ -1,1035 +0,0 @@
    90.4 -/*
    90.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    90.6 - *
    90.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    90.8 - *
    90.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   90.10 - * Other names may be trademarks of their respective owners.
   90.11 - *
   90.12 - * The contents of this file are subject to the terms of either the GNU
   90.13 - * General Public License Version 2 only ("GPL") or the Common
   90.14 - * Development and Distribution License("CDDL") (collectively, the
   90.15 - * "License"). You may not use this file except in compliance with the
   90.16 - * License. You can obtain a copy of the License at
   90.17 - * http://www.netbeans.org/cddl-gplv2.html
   90.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   90.19 - * specific language governing permissions and limitations under the
   90.20 - * License.  When distributing the software, include this License Header
   90.21 - * Notice in each file and include the License file at
   90.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   90.23 - * particular file as subject to the "Classpath" exception as provided
   90.24 - * by Oracle in the GPL Version 2 section of the License file that
   90.25 - * accompanied this code. If applicable, add the following below the
   90.26 - * License Header, with the fields enclosed by brackets [] replaced by
   90.27 - * your own identifying information:
   90.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   90.29 - *
   90.30 - * Contributor(s):
   90.31 - *
   90.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   90.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
   90.34 - * Microsystems, Inc. All Rights Reserved.
   90.35 - *
   90.36 - * If you wish your version of this file to be governed by only the CDDL
   90.37 - * or only the GPL Version 2, indicate your decision by adding
   90.38 - * "[Contributor] elects to include this software in this distribution
   90.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   90.40 - * single choice of license, a recipient has the option to distribute
   90.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   90.42 - * to extend the choice of license to its licensees as provided above.
   90.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   90.44 - * Version 2 license, then the option applies only if the new code is
   90.45 - * made subject to such option by the copyright holder.
   90.46 - */
   90.47 -package org.netbeans.modules.python.editor.options;
   90.48 -
   90.49 -import java.awt.Component;
   90.50 -import java.awt.Container;
   90.51 -import java.awt.Rectangle;
   90.52 -import java.awt.event.ActionEvent;
   90.53 -import java.awt.event.ActionListener;
   90.54 -import java.io.BufferedWriter;
   90.55 -import java.io.File;
   90.56 -import java.io.FileWriter;
   90.57 -import java.io.IOException;
   90.58 -import java.util.Arrays;
   90.59 -import java.util.HashMap;
   90.60 -import java.util.HashSet;
   90.61 -import java.util.LinkedList;
   90.62 -import java.util.List;
   90.63 -import java.util.Map;
   90.64 -import java.util.Set;
   90.65 -import java.util.prefs.AbstractPreferences;
   90.66 -import java.util.prefs.BackingStoreException;
   90.67 -import java.util.prefs.Preferences;
   90.68 -import javax.swing.ComboBoxModel;
   90.69 -import javax.swing.DefaultComboBoxModel;
   90.70 -import javax.swing.JCheckBox;
   90.71 -import javax.swing.JComboBox;
   90.72 -import javax.swing.JComponent;
   90.73 -import javax.swing.JEditorPane;
   90.74 -import javax.swing.JPanel;
   90.75 -import javax.swing.JTextField;
   90.76 -import javax.swing.event.DocumentEvent;
   90.77 -import javax.swing.event.DocumentListener;
   90.78 -import javax.swing.text.BadLocationException;
   90.79 -import javax.swing.text.Document;
   90.80 -import org.netbeans.api.editor.settings.SimpleValueNames;
   90.81 -import static org.netbeans.modules.python.editor.options.CodeStyle.*;
   90.82 -import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
   90.83 -import org.netbeans.modules.options.editor.spi.PreviewProvider;
   90.84 -import org.netbeans.modules.python.api.PythonMIMEResolver;
   90.85 -import org.netbeans.modules.python.editor.PythonFormatter;
   90.86 -import org.netbeans.modules.python.editor.PythonParserResult;
   90.87 -import org.openide.cookies.SaveCookie;
   90.88 -import org.openide.filesystems.FileObject;
   90.89 -import org.openide.filesystems.FileUtil;
   90.90 -import org.openide.loaders.DataObject;
   90.91 -import org.openide.loaders.DataObjectNotFoundException;
   90.92 -import org.openide.text.CloneableEditorSupport;
   90.93 -import org.openide.util.Exceptions;
   90.94 -import org.openide.util.HelpCtx;
   90.95 -import org.openide.util.NbBundle;
   90.96 -
   90.97 -/**
   90.98 - *
   90.99 - * @author phrebejk
  90.100 - */
  90.101 -public class FmtOptions {
  90.102 -    public static final String expandTabToSpaces = SimpleValueNames.EXPAND_TABS;
  90.103 -    public static final String tabSize = SimpleValueNames.TAB_SIZE;
  90.104 -    public static final String spacesPerTab = SimpleValueNames.SPACES_PER_TAB;
  90.105 -    public static final String indentSize = SimpleValueNames.INDENT_SHIFT_WIDTH;
  90.106 -    public static final String continuationIndentSize = "continuationIndentSize"; //NOI18N
  90.107 -    public static final String labelIndent = "labelIndent"; //NOI18N
  90.108 -    public static final String absoluteLabelIndent = "absoluteLabelIndent"; //NOI18N
  90.109 -    public static final String indentTopLevelClassMembers = "indentTopLevelClassMembers"; //NOI18N
  90.110 -    public static final String indentCasesFromSwitch = "indentCasesFromSwitch"; //NOI18N
  90.111 -    public static final String rightMargin = SimpleValueNames.TEXT_LIMIT_WIDTH;
  90.112 -
  90.113 -    /*
  90.114 -    public static final String addLeadingStarInComment = "addLeadingStarInComment"; //NOI18N
  90.115 -
  90.116 -    public static final String preferLongerNames = "preferLongerNames"; //NOI18N
  90.117 -    public static final String fieldNamePrefix = "fieldNamePrefix"; //NOI18N
  90.118 -    public static final String fieldNameSuffix = "fieldNameSuffix"; //NOI18N
  90.119 -    public static final String staticFieldNamePrefix = "staticFieldNamePrefix"; //NOI18N
  90.120 -    public static final String staticFieldNameSuffix = "staticFieldNameSuffix"; //NOI18N
  90.121 -    public static final String parameterNamePrefix = "parameterNamePrefix"; //NOI18N
  90.122 -    public static final String parameterNameSuffix = "parameterNameSuffix"; //NOI18N
  90.123 -    public static final String localVarNamePrefix = "localVarNamePrefix"; //NOI18N
  90.124 -    public static final String localVarNameSuffix = "localVarNameSuffix"; //NOI18N
  90.125 -    public static final String qualifyFieldAccess = "qualifyFieldAccess"; //NOI18N
  90.126 -    public static final String useIsForBooleanGetters = "useIsForBooleanGetters"; //NOI18N
  90.127 -    public static final String addOverrideAnnotation = "addOverrideAnnotation"; //NOI18N
  90.128 -    public static final String makeLocalVarsFinal = "makeLocalVarsFinal"; //NOI18N
  90.129 -    public static final String makeParametersFinal = "makeParametersFinal"; //NOI18N
  90.130 -    public static final String classMembersOrder = "classMembersOrder"; //NOI18N
  90.131 -    
  90.132 -    public static final String alignMultilineMethodParams = "alignMultilineMethodParams"; //NOI18N
  90.133 -    public static final String alignMultilineCallArgs = "alignMultilineCallArgs"; //NOI18N
  90.134 -    public static final String alignMultilineAnnotationArgs = "alignMultilineAnnotationArgs"; //NOI18N
  90.135 -    public static final String alignMultilineImplements = "alignMultilineImplements"; //NOI18N
  90.136 -    public static final String alignMultilineThrows = "alignMultilineThrows"; //NOI18N
  90.137 -    public static final String alignMultilineParenthesized = "alignMultilineParenthesized"; //NOI18N
  90.138 -    public static final String alignMultilineBinaryOp = "alignMultilineBinaryOp"; //NOI18N
  90.139 -    public static final String alignMultilineTernaryOp = "alignMultilineTernaryOp"; //NOI18N
  90.140 -    public static final String alignMultilineAssignment = "alignMultilineAssignment"; //NOI18N
  90.141 -    public static final String alignMultilineFor = "alignMultilineFor"; //NOI18N
  90.142 -    public static final String alignMultilineArrayInit = "alignMultilineArrayInit"; //NOI18N
  90.143 -    public static final String placeElseOnNewLine = "placeElseOnNewLine"; //NOI18N
  90.144 -    public static final String placeWhileOnNewLine = "placeWhileOnNewLine"; //NOI18N
  90.145 -    public static final String placeCatchOnNewLine = "placeCatchOnNewLine"; //NOI18N
  90.146 -    public static final String placeFinallyOnNewLine = "placeFinallyOnNewLine"; //NOI18N
  90.147 -    public static final String placeNewLineAfterModifiers = "placeNewLineAfterModifiers"; //NOI18N
  90.148 -    
  90.149 -    public static final String wrapExtendsImplementsKeyword = "wrapExtendsImplementsKeyword"; //NOI18N
  90.150 -    public static final String wrapExtendsImplementsList = "wrapExtendsImplementsList"; //NOI18N
  90.151 -    public static final String wrapMethodParams = "wrapMethodParams"; //NOI18N
  90.152 -    public static final String wrapThrowsKeyword = "wrapThrowsKeyword"; //NOI18N
  90.153 -    public static final String wrapThrowsList = "wrapThrowsList"; //NOI18N
  90.154 -    public static final String wrapMethodCallArgs = "wrapMethodCallArgs"; //NOI18N
  90.155 -    public static final String wrapAnnotationArgs = "wrapAnnotationArgs"; //NOI18N
  90.156 -    public static final String wrapChainedMethodCalls = "wrapChainedMethodCalls"; //NOI18N
  90.157 -    public static final String wrapArrayInit = "wrapArrayInit"; //NOI18N
  90.158 -    public static final String wrapFor = "wrapFor"; //NOI18N
  90.159 -    public static final String wrapForStatement = "wrapForStatement"; //NOI18N
  90.160 -    public static final String wrapIfStatement = "wrapIfStatement"; //NOI18N
  90.161 -    public static final String wrapWhileStatement = "wrapWhileStatement"; //NOI18N
  90.162 -    public static final String wrapDoWhileStatement = "wrapDoWhileStatement"; //NOI18N
  90.163 -    public static final String wrapAssert = "wrapAssert"; //NOI18N
  90.164 -    public static final String wrapEnumConstants = "wrapEnumConstants"; //NOI18N
  90.165 -    public static final String wrapAnnotations = "wrapAnnotations"; //NOI18N
  90.166 -    public static final String wrapBinaryOps = "wrapBinaryOps"; //NOI18N
  90.167 -    public static final String wrapTernaryOps = "wrapTernaryOps"; //NOI18N
  90.168 -    public static final String wrapAssignOps = "wrapAssignOps"; //NOI18N
  90.169 -    
  90.170 -    public static final String blankLinesBeforePackage = "blankLinesBeforePackage"; //NOI18N
  90.171 -    public static final String blankLinesAfterPackage = "blankLinesAfterPackage"; //NOI18N
  90.172 -    public static final String blankLinesBeforeImports = "blankLinesBeforeImports"; //NOI18N
  90.173 -    public static final String blankLinesAfterImports = "blankLinesAfterImports"; //NOI18N
  90.174 -    public static final String blankLinesBeforeClass = "blankLinesBeforeClass"; //NOI18N
  90.175 -    public static final String blankLinesAfterClass = "blankLinesAfterClass"; //NOI18N
  90.176 -    public static final String blankLinesAfterClassHeader = "blankLinesAfterClassHeader"; //NOI18N
  90.177 -    public static final String blankLinesBeforeFields = "blankLinesBeforeFields"; //NOI18N
  90.178 -    public static final String blankLinesAfterFields = "blankLinesAfterFields"; //NOI18N
  90.179 -    public static final String blankLinesBeforeMethods = "blankLinesBeforeMethods"; //NOI18N
  90.180 -    public static final String blankLinesAfterMethods = "blankLinesAfterMethods"; //NOI18N
  90.181 -    
  90.182 -    public static final String spaceBeforeWhile = "spaceBeforeWhile"; //NOI18N
  90.183 -    public static final String spaceBeforeElse = "spaceBeforeElse"; //NOI18N
  90.184 -    public static final String spaceBeforeCatch = "spaceBeforeCatch"; //NOI18N
  90.185 -    public static final String spaceBeforeFinally = "spaceBeforeFinally"; //NOI18N
  90.186 -    public static final String spaceBeforeMethodDeclParen = "spaceBeforeMethodDeclParen"; //NOI18N
  90.187 -    public static final String spaceBeforeMethodCallParen = "spaceBeforeMethodCallParen"; //NOI18N
  90.188 -    public static final String spaceBeforeIfParen = "spaceBeforeIfParen"; //NOI18N
  90.189 -    public static final String spaceBeforeForParen = "spaceBeforeForParen"; //NOI18N
  90.190 -    public static final String spaceBeforeWhileParen = "spaceBeforeWhileParen"; //NOI18N
  90.191 -    public static final String spaceBeforeCatchParen = "spaceBeforeCatchParen"; //NOI18N
  90.192 -    public static final String spaceBeforeSwitchParen = "spaceBeforeSwitchParen"; //NOI18N
  90.193 -    public static final String spaceBeforeSynchronizedParen = "spaceBeforeSynchronizedParen"; //NOI18N
  90.194 -    public static final String spaceBeforeAnnotationParen = "spaceBeforeAnnotationParen"; //NOI18N    
  90.195 -    public static final String spaceAroundUnaryOps = "spaceAroundUnaryOps"; //NOI18N
  90.196 -    public static final String spaceAroundBinaryOps = "spaceAroundBinaryOps"; //NOI18N
  90.197 -    public static final String spaceAroundTernaryOps = "spaceAroundTernaryOps"; //NOI18N
  90.198 -    public static final String spaceAroundAssignOps = "spaceAroundAssignOps"; //NOI18N
  90.199 -    public static final String spaceBeforeClassDeclLeftBrace = "spaceBeforeClassDeclLeftBrace"; //NOI18N
  90.200 -    public static final String spaceBeforeMethodDeclLeftBrace = "spaceBeforeMethodDeclLeftBrace"; //NOI18N
  90.201 -    public static final String spaceBeforeIfLeftBrace = "spaceBeforeIfLeftBrace"; //NOI18N
  90.202 -    public static final String spaceBeforeElseLeftBrace = "spaceBeforeElseLeftBrace"; //NOI18N
  90.203 -    public static final String spaceBeforeWhileLeftBrace = "spaceBeforeWhileLeftBrace"; //NOI18N
  90.204 -    public static final String spaceBeforeForLeftBrace = "spaceBeforeForLeftBrace"; //NOI18N
  90.205 -    public static final String spaceBeforeDoLeftBrace = "spaceBeforeDoLeftBrace"; //NOI18N
  90.206 -    public static final String spaceBeforeSwitchLeftBrace = "spaceBeforeSwitchLeftBrace"; //NOI18N
  90.207 -    public static final String spaceBeforeTryLeftBrace = "spaceBeforeTryLeftBrace"; //NOI18N
  90.208 -    public static final String spaceBeforeCatchLeftBrace = "spaceBeforeCatchLeftBrace"; //NOI18N
  90.209 -    public static final String spaceBeforeFinallyLeftBrace = "spaceBeforeFinallyLeftBrace"; //NOI18N
  90.210 -    public static final String spaceBeforeSynchronizedLeftBrace = "spaceBeforeSynchronizedLeftBrace"; //NOI18N
  90.211 -    public static final String spaceBeforeStaticInitLeftBrace = "spaceBeforeStaticInitLeftBrace"; //NOI18N
  90.212 -    public static final String spaceBeforeArrayInitLeftBrace = "spaceBeforeArrayInitLeftBrace"; //NOI18N
  90.213 -    public static final String spaceWithinParens = "spaceWithinParens"; //NOI18N
  90.214 -    public static final String spaceWithinMethodDeclParens = "spaceWithinMethodDeclParens"; //NOI18N
  90.215 -    public static final String spaceWithinMethodCallParens = "spaceWithinMethodCallParens"; //NOI18N
  90.216 -    public static final String spaceWithinIfParens = "spaceWithinIfParens"; //NOI18N
  90.217 -    public static final String spaceWithinForParens = "spaceWithinForParens"; //NOI18N
  90.218 -    public static final String spaceWithinWhileParens = "spaceWithinWhileParens"; //NOI18N
  90.219 -    public static final String spaceWithinSwitchParens = "spaceWithinSwitchParens"; //NOI18N
  90.220 -    public static final String spaceWithinCatchParens = "spaceWithinCatchParens"; //NOI18N
  90.221 -    public static final String spaceWithinSynchronizedParens = "spaceWithinSynchronizedParens"; //NOI18N
  90.222 -    public static final String spaceWithinTypeCastParens = "spaceWithinTypeCastParens"; //NOI18N
  90.223 -    public static final String spaceWithinAnnotationParens = "spaceWithinAnnotationParens"; //NOI18N
  90.224 -    public static final String spaceWithinBraces = "spaceWithinBraces"; //NOI18N
  90.225 -    public static final String spaceWithinArrayInitBrackets = "spaceWithinArrayInitBrackets"; //NOI18N
  90.226 -    public static final String spaceBeforeComma = "spaceBeforeComma"; //NOI18N
  90.227 -    public static final String spaceAfterComma = "spaceAfterComma"; //NOI18N
  90.228 -    public static final String spaceBeforeSemi = "spaceBeforeSemi"; //NOI18N
  90.229 -    public static final String spaceAfterSemi = "spaceAfterSemi"; //NOI18N
  90.230 -    public static final String spaceBeforeColon = "spaceBeforeColon"; //NOI18N
  90.231 -    public static final String spaceAfterColon = "spaceAfterColon"; //NOI18N
  90.232 -    public static final String spaceAfterTypeCast = "spaceAfterTypeCast"; //NOI18N
  90.233 -     */
  90.234 -
  90.235 -    // Spaces
  90.236 -    public static final String addSpaceAroundOperators = "spaceAroundOperators"; //NOI18N
  90.237 -    public static final String removeSpaceInParens = "spaceInsideParens"; //NOI18N
  90.238 -    public static final String addSpaceAfterComma = "spaceAfterComma"; //NOI18N
  90.239 -    public static final String removeSpaceBeforeSep = "spaceBeforeSeparator"; //NOI18N
  90.240 -    public static final String removeSpaceInParamAssign = "spaceInKeywordAssign"; //NOI18N
  90.241 -    public static final String collapseSpaces = "collapseSpaces"; //NOI18N
  90.242 -    // Imports
  90.243 -    public static final String formatImports = "formatImports"; //NOI18N
  90.244 -    public static final String oneImportPerLine = "oneImportPerLine"; //NOI18N
  90.245 -    public static final String removeDuplicates = "removeDuplicates"; //NOI18N
  90.246 -    public static final String systemLibsFirst = "systemLibsFirst"; //NOI18N
  90.247 -    public static final String cleanupUnusedImports = "cleanupUnusedImports"; //NOI18N
  90.248 -    public static final String preferSymbolImports = "preferSymbolImports"; //NOI18N
  90.249 -    public static final String sortImports = "sortImports"; //NOI18N
  90.250 -    public static final String separateFromImps = "separateFromImps"; //NOI18N
  90.251 -    public static CodeStyleProducer codeStyleProducer;
  90.252 -    static final String CODE_STYLE_PROFILE = "CodeStyle"; // NOI18N
  90.253 -    static final String DEFAULT_PROFILE = "default"; // NOI18N
  90.254 -    static final String PROJECT_PROFILE = "project"; // NOI18N
  90.255 -    static final String usedProfile = "usedProfile"; // NOI18N
  90.256 -
  90.257 -    private FmtOptions() {
  90.258 -    }
  90.259 -
  90.260 -    public static int getDefaultAsInt(String key) {
  90.261 -        return Integer.parseInt(defaults.get(key));
  90.262 -    }
  90.263 -
  90.264 -    public static boolean getDefaultAsBoolean(String key) {
  90.265 -        return Boolean.parseBoolean(defaults.get(key));
  90.266 -    }
  90.267 -
  90.268 -    public static String getDefaultAsString(String key) {
  90.269 -        return defaults.get(key);
  90.270 -    }
  90.271 -
  90.272 -    public static boolean isInteger(String optionID) {
  90.273 -        String value = defaults.get(optionID);
  90.274 -
  90.275 -        try {
  90.276 -            Integer.parseInt(value);
  90.277 -            return true;
  90.278 -        } catch (NumberFormatException numberFormatException) {
  90.279 -            return false;
  90.280 -        }
  90.281 -    }
  90.282 -    // Private section ---------------------------------------------------------
  90.283 -    private static final String TRUE = "true";      // NOI18N
  90.284 -    private static final String FALSE = "false";    // NOI18N
  90.285 -    private static final String WRAP_ALWAYS = WrapStyle.WRAP_ALWAYS.name();
  90.286 -    //private static final String WRAP_IF_LONG  = WrapStyle.WRAP_IF_LONG.name();
  90.287 -    private static final String WRAP_NEVER = WrapStyle.WRAP_NEVER.name();
  90.288 -
  90.289 -    //private static final String CLEANUP_COMMENT  = ImportCleanupStyle.COMMENT_OUT.name();
  90.290 -    private static final String IMP_LEAVE_ALONE = ImportCleanupStyle.LEAVE_ALONE.name();
  90.291 -    private static Map<String, String> defaults;
  90.292 -
  90.293 -
  90.294 -    static {
  90.295 -        createDefaults();
  90.296 -    }
  90.297 -
  90.298 -    private static void createDefaults() {
  90.299 -        String defaultValues[][] = {
  90.300 -            {expandTabToSpaces, TRUE}, //NOI18N
  90.301 -            {tabSize, "4"}, //NOI18N
  90.302 -            {spacesPerTab, "4"}, //NOI18N
  90.303 -            {indentSize, "4"}, //NOI18N
  90.304 -            {continuationIndentSize, "8"}, //NOI18N
  90.305 -            {labelIndent, "0"}, //NOI18N
  90.306 -            {absoluteLabelIndent, FALSE}, //NOI18N
  90.307 -            {indentTopLevelClassMembers, TRUE}, //NOI18N
  90.308 -            {indentCasesFromSwitch, TRUE}, //NOI18N
  90.309 -            {rightMargin, "80"}, //NOI18N
  90.310 -
  90.311 -            /*
  90.312 -            { addLeadingStarInComment, TRUE}, //NOI18N
  90.313 -
  90.314 -            { preferLongerNames, TRUE}, //NOI18N
  90.315 -            { fieldNamePrefix, ""}, //NOI18N // XXX null
  90.316 -            { fieldNameSuffix, ""}, //NOI18N // XXX null
  90.317 -            { staticFieldNamePrefix, ""}, //NOI18N // XXX null
  90.318 -            { staticFieldNameSuffix, ""}, //NOI18N // XXX null
  90.319 -            { parameterNamePrefix, ""}, //NOI18N // XXX null
  90.320 -            { parameterNameSuffix, ""}, //NOI18N // XXX null
  90.321 -            { localVarNamePrefix, ""}, //NOI18N // XXX null
  90.322 -            { localVarNameSuffix, ""}, //NOI18N // XXX null
  90.323 -            { qualifyFieldAccess, FALSE}, //NOI18N // XXX
  90.324 -            { useIsForBooleanGetters, TRUE}, //NOI18N
  90.325 -            { addOverrideAnnotation, TRUE}, //NOI18N
  90.326 -            { makeLocalVarsFinal, FALSE}, //NOI18N
  90.327 -            { makeParametersFinal, FALSE}, //NOI18N
  90.328 -            { classMembersOrder, ""}, //NOI18N // XXX
  90.329 -
  90.330 -            { alignMultilineMethodParams, FALSE}, //NOI18N
  90.331 -            { alignMultilineCallArgs, FALSE}, //NOI18N
  90.332 -            { alignMultilineAnnotationArgs, FALSE}, //NOI18N
  90.333 -            { alignMultilineImplements, FALSE}, //NOI18N
  90.334 -            { alignMultilineThrows, FALSE}, //NOI18N
  90.335 -            { alignMultilineParenthesized, FALSE}, //NOI18N
  90.336 -            { alignMultilineBinaryOp, FALSE}, //NOI18N
  90.337 -            { alignMultilineTernaryOp, FALSE}, //NOI18N
  90.338 -            { alignMultilineAssignment, FALSE}, //NOI18N
  90.339 -            { alignMultilineFor, FALSE}, //NOI18N
  90.340 -            { alignMultilineArrayInit, FALSE}, //NOI18N
  90.341 -            { placeElseOnNewLine, FALSE}, //NOI18N 
  90.342 -            { placeWhileOnNewLine, FALSE}, //NOI18N
  90.343 -            { placeCatchOnNewLine, FALSE}, //NOI18N 
  90.344 -            { placeFinallyOnNewLine, FALSE}, //NOI18N 
  90.345 -            { placeNewLineAfterModifiers, FALSE}, //NOI18N
  90.346 -
  90.347 -            { wrapExtendsImplementsKeyword, WRAP_NEVER}, //NOI18N
  90.348 -            { wrapExtendsImplementsList, WRAP_NEVER}, //NOI18N
  90.349 -            { wrapMethodParams, WRAP_NEVER}, //NOI18N
  90.350 -            { wrapThrowsKeyword, WRAP_NEVER}, //NOI18N
  90.351 -            { wrapThrowsList, WRAP_NEVER}, //NOI18N
  90.352 -            { wrapMethodCallArgs, WRAP_NEVER}, //NOI18N
  90.353 -            { wrapAnnotationArgs, WRAP_NEVER}, //NOI18N
  90.354 -            { wrapChainedMethodCalls, WRAP_NEVER}, //NOI18N
  90.355 -            { wrapArrayInit, WRAP_NEVER}, //NOI18N
  90.356 -            { wrapFor, WRAP_NEVER}, //NOI18N
  90.357 -            { wrapForStatement, WRAP_ALWAYS}, //NOI18N
  90.358 -            { wrapIfStatement, WRAP_ALWAYS}, //NOI18N
  90.359 -            { wrapWhileStatement, WRAP_ALWAYS}, //NOI18N
  90.360 -            { wrapDoWhileStatement, WRAP_ALWAYS}, //NOI18N
  90.361 -            { wrapAssert, WRAP_NEVER}, //NOI18N
  90.362 -            { wrapEnumConstants, WRAP_NEVER}, //NOI18N
  90.363 -            { wrapAnnotations, WRAP_ALWAYS}, //NOI18N
  90.364 -            { wrapBinaryOps, WRAP_NEVER}, //NOI18N
  90.365 -            { wrapTernaryOps, WRAP_NEVER}, //NOI18N
  90.366 -            { wrapAssignOps, WRAP_NEVER}, //NOI18N
  90.367 -
  90.368 -            { blankLinesBeforePackage, "0"}, //NOI18N
  90.369 -            { blankLinesAfterPackage, "1"}, //NOI18N
  90.370 -            { blankLinesBeforeImports, "1"}, //NOI18N 
  90.371 -            { blankLinesAfterImports, "1"}, //NOI18N
  90.372 -            { blankLinesBeforeClass, "1"}, //NOI18N 
  90.373 -            { blankLinesAfterClass, "0"}, //NOI18N
  90.374 -            { blankLinesAfterClassHeader, "1"}, //NOI18N 
  90.375 -            { blankLinesBeforeFields, "0"}, //NOI18N 
  90.376 -            { blankLinesAfterFields, "0"}, //NOI18N
  90.377 -            { blankLinesBeforeMethods, "1"}, //NOI18N
  90.378 -            { blankLinesAfterMethods, "0"}, //NOI18N
  90.379 -
  90.380 -            { spaceBeforeWhile, TRUE}, //NOI18N // XXX
  90.381 -            { spaceBeforeElse, TRUE}, //NOI18N // XXX
  90.382 -            { spaceBeforeCatch, TRUE}, //NOI18N // XXX
  90.383 -            { spaceBeforeFinally, TRUE}, //NOI18N // XXX
  90.384 -            { spaceBeforeMethodDeclParen, FALSE}, //NOI18N
  90.385 -            { spaceBeforeMethodCallParen, FALSE}, //NOI18N
  90.386 -            { spaceBeforeIfParen, TRUE}, //NOI18N
  90.387 -            { spaceBeforeForParen, TRUE}, //NOI18N
  90.388 -            { spaceBeforeWhileParen, TRUE}, //NOI18N
  90.389 -            { spaceBeforeCatchParen, TRUE}, //NOI18N
  90.390 -            { spaceBeforeSwitchParen, TRUE}, //NOI18N
  90.391 -            { spaceBeforeSynchronizedParen, TRUE}, //NOI18N
  90.392 -            { spaceBeforeAnnotationParen, FALSE}, //NOI18N    
  90.393 -            { spaceAroundUnaryOps, FALSE}, //NOI18N
  90.394 -            { spaceAroundBinaryOps, TRUE}, //NOI18N
  90.395 -            { spaceAroundTernaryOps, TRUE}, //NOI18N
  90.396 -            { spaceAroundAssignOps, TRUE}, //NOI18N
  90.397 -            { spaceBeforeClassDeclLeftBrace, TRUE}, //NOI18N
  90.398 -            { spaceBeforeMethodDeclLeftBrace, TRUE}, //NOI18N
  90.399 -            { spaceBeforeIfLeftBrace, TRUE}, //NOI18N
  90.400 -            { spaceBeforeElseLeftBrace, TRUE}, //NOI18N
  90.401 -            { spaceBeforeWhileLeftBrace, TRUE}, //NOI18N
  90.402 -            { spaceBeforeForLeftBrace, TRUE}, //NOI18N
  90.403 -            { spaceBeforeDoLeftBrace, TRUE}, //NOI18N
  90.404 -            { spaceBeforeSwitchLeftBrace, TRUE}, //NOI18N
  90.405 -            { spaceBeforeTryLeftBrace, TRUE}, //NOI18N
  90.406 -            { spaceBeforeCatchLeftBrace, TRUE}, //NOI18N
  90.407 -            { spaceBeforeFinallyLeftBrace, TRUE}, //NOI18N
  90.408 -            { spaceBeforeSynchronizedLeftBrace, TRUE}, //NOI18N
  90.409 -            { spaceBeforeStaticInitLeftBrace, TRUE}, //NOI18N
  90.410 -            { spaceBeforeArrayInitLeftBrace, FALSE}, //NOI18N
  90.411 -            { spaceWithinParens, FALSE}, //NOI18N
  90.412 -            { spaceWithinMethodDeclParens, FALSE}, //NOI18N
  90.413 -            { spaceWithinMethodCallParens, FALSE}, //NOI18N
  90.414 -            { spaceWithinIfParens, FALSE}, //NOI18N
  90.415 -            { spaceWithinForParens, FALSE}, //NOI18N
  90.416 -            { spaceWithinWhileParens, FALSE}, //NOI18N
  90.417 -            { spaceWithinSwitchParens, FALSE}, //NOI18N
  90.418 -            { spaceWithinCatchParens, FALSE}, //NOI18N
  90.419 -            { spaceWithinSynchronizedParens, FALSE}, //NOI18N
  90.420 -            { spaceWithinTypeCastParens, FALSE}, //NOI18N
  90.421 -            { spaceWithinAnnotationParens, FALSE}, //NOI18N
  90.422 -            { spaceWithinBraces, FALSE}, //NOI18N
  90.423 -            { spaceWithinArrayInitBrackets, FALSE}, //NOI18N
  90.424 -            { spaceBeforeComma, FALSE}, //NOI18N
  90.425 -            { spaceAfterComma, TRUE}, //NOI18N
  90.426 -            { spaceBeforeSemi, FALSE}, //NOI18N
  90.427 -            { spaceAfterSemi, TRUE}, //NOI18N
  90.428 -            { spaceBeforeColon, TRUE}, //NOI18N
  90.429 -            { spaceAfterColon, TRUE}, //NOI18N
  90.430 -            { spaceAfterTypeCast, TRUE}, //NOI18N
  90.431 -             */
  90.432 -            // Spaces
  90.433 -            {addSpaceAroundOperators, TRUE},
  90.434 -            {removeSpaceInParens, TRUE},
  90.435 -            {addSpaceAfterComma, TRUE},
  90.436 -            {removeSpaceBeforeSep, TRUE},
  90.437 -            {removeSpaceInParamAssign, TRUE},
  90.438 -            {collapseSpaces, TRUE},
  90.439 -            // Imports
  90.440 -            {formatImports, TRUE},
  90.441 -            {oneImportPerLine, TRUE},
  90.442 -            {removeDuplicates, TRUE},
  90.443 -            {systemLibsFirst, TRUE},
  90.444 -            {preferSymbolImports, TRUE},
  90.445 -            {sortImports, TRUE},
  90.446 -            {cleanupUnusedImports, IMP_LEAVE_ALONE},
  90.447 -            {separateFromImps, FALSE},};
  90.448 -
  90.449 -        defaults = new HashMap<>();
  90.450 -
  90.451 -        for (java.lang.String[] strings : defaultValues) {
  90.452 -            defaults.put(strings[0], strings[1]);
  90.453 -        }
  90.454 -
  90.455 -    }
  90.456 -
  90.457 -    // Support section ---------------------------------------------------------
  90.458 -    public static class CategorySupport implements ActionListener, DocumentListener, PreviewProvider, PreferencesCustomizer {
  90.459 -        public static final String OPTION_ID = "org.netbeans.modules.python.editor.options.FormatingOptions.ID";
  90.460 -        private static final int LOAD = 0;
  90.461 -        private static final int STORE = 1;
  90.462 -        private static final int ADD_LISTENERS = 2;
  90.463 -        private static final ComboItem wrap[] = new ComboItem[]{
  90.464 -            new ComboItem(WrapStyle.WRAP_ALWAYS.name(), "LBL_wrp_WRAP_ALWAYS"), // NOI18N
  90.465 -            new ComboItem(WrapStyle.WRAP_IF_LONG.name(), "LBL_wrp_WRAP_IF_LONG"), // NOI18N
  90.466 -            new ComboItem(WrapStyle.WRAP_NEVER.name(), "LBL_wrp_WRAP_NEVER") // NOI18N
  90.467 -        };
  90.468 -        private static final ComboItem cleanupImports[] = new ComboItem[]{
  90.469 -            new ComboItem(ImportCleanupStyle.LEAVE_ALONE.name(), "LBL_imp_LEAVE_ALONE"), // NOI18N
  90.470 -            new ComboItem(ImportCleanupStyle.COMMENT_OUT.name(), "LBL_imp_COMMENT_OUT"), // NOI18N
  90.471 -            new ComboItem(ImportCleanupStyle.DELETE.name(), "LBL_imp_DELETE") // NOI18N
  90.472 -        };
  90.473 -        private final String previewText;
  90.474 -        private final String id;
  90.475 -        protected final JPanel panel;
  90.476 -        private final List<JComponent> components = new LinkedList<>();
  90.477 -        private JEditorPane previewPane;
  90.478 -        private final Preferences preferences;
  90.479 -        private final Preferences previewPrefs;
  90.480 -
  90.481 -        protected CategorySupport(Preferences preferences, String id, JPanel panel, String previewText, String[]... forcedOptions) {
  90.482 -            this.preferences = preferences;
  90.483 -            this.id = id;
  90.484 -            this.panel = panel;
  90.485 -            this.previewText = previewText != null ? previewText : NbBundle.getMessage(FmtOptions.class, "SAMPLE_Default"); //NOI18N
  90.486 -
  90.487 -            // Scan the panel for its components
  90.488 -            scan(panel, components);
  90.489 -
  90.490 -            // Initialize the preview preferences
  90.491 -            Preferences forcedPrefs = new PreviewPreferences();
  90.492 -            for (String[] option : forcedOptions) {
  90.493 -                forcedPrefs.put(option[0], option[1]);
  90.494 -            }
  90.495 -            this.previewPrefs = new ProxyPreferences(preferences, forcedPrefs);
  90.496 -
  90.497 -            // Load and hook up all the components
  90.498 -            loadFrom(preferences);
  90.499 -            addListeners();
  90.500 -        }
  90.501 -
  90.502 -        protected void addListeners() {
  90.503 -            scan(ADD_LISTENERS, null);
  90.504 -        }
  90.505 -
  90.506 -        protected void loadFrom(Preferences preferences) {
  90.507 -//            loaded = true;
  90.508 -            scan(LOAD, preferences);
  90.509 -//            loaded = false;
  90.510 -        }
  90.511 -//
  90.512 -//        public void applyChanges() {
  90.513 -//            storeTo(preferences);
  90.514 -//        }
  90.515 -//
  90.516 -
  90.517 -        protected void storeTo(Preferences p) {
  90.518 -            scan(STORE, p);
  90.519 -        }
  90.520 -
  90.521 -        protected void notifyChanged() {
  90.522 -//            if (loaded)
  90.523 -//                return;
  90.524 -            storeTo(preferences);
  90.525 -            refreshPreview();
  90.526 -        }
  90.527 -
  90.528 -        // ActionListener implementation ---------------------------------------
  90.529 -        @Override
  90.530 -        public void actionPerformed(ActionEvent e) {
  90.531 -            notifyChanged();
  90.532 -        }
  90.533 -
  90.534 -        // DocumentListener implementation -------------------------------------
  90.535 -        @Override
  90.536 -        public void insertUpdate(DocumentEvent e) {
  90.537 -            notifyChanged();
  90.538 -        }
  90.539 -
  90.540 -        @Override
  90.541 -        public void removeUpdate(DocumentEvent e) {
  90.542 -            notifyChanged();
  90.543 -        }
  90.544 -
  90.545 -        @Override
  90.546 -        public void changedUpdate(DocumentEvent e) {
  90.547 -            notifyChanged();
  90.548 -        }
  90.549 -
  90.550 -        // PreviewProvider methods -----------------------------------------------------
  90.551 -        @Override
  90.552 -        public JComponent getPreviewComponent() {
  90.553 -            if (previewPane == null) {
  90.554 -                previewPane = new JEditorPane();
  90.555 -                previewPane.getAccessibleContext().setAccessibleName(NbBundle.getMessage(FmtOptions.class, "AN_Preview")); //NOI18N
  90.556 -                previewPane.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(FmtOptions.class, "AD_Preview")); //NOI18N
  90.557 -                previewPane.putClientProperty("HighlightsLayerIncludes", "^org\\.netbeans\\.modules\\.editor\\.lib2\\.highlighting\\.SyntaxHighlighting$"); //NOI18N
  90.558 -                previewPane.setEditorKit(CloneableEditorSupport.getEditorKit(PythonMIMEResolver.PYTHON_MIME_TYPE));
  90.559 -                previewPane.setEditable(false);
  90.560 -            }
  90.561 -            return previewPane;
  90.562 -        }
  90.563 -
  90.564 -        @Override
  90.565 -        public void refreshPreview() {
  90.566 -            JEditorPane jep = (JEditorPane)getPreviewComponent();
  90.567 -            try {
  90.568 -                int rm = previewPrefs.getInt(rightMargin, getDefaultAsInt(rightMargin));
  90.569 -                jep.putClientProperty("TextLimitLine", rm); //NOI18N
  90.570 -            } catch (NumberFormatException e) {
  90.571 -                // Ignore it
  90.572 -            }
  90.573 -            try {
  90.574 -                Class.forName(CodeStyle.class.getName(), true, CodeStyle.class.getClassLoader());
  90.575 -            } catch (ClassNotFoundException cnfe) {
  90.576 -                // ignore
  90.577 -            }
  90.578 -
  90.579 -            CodeStyle codeStyle = codeStyleProducer.create(previewPrefs);
  90.580 -            jep.setIgnoreRepaint(true);
  90.581 -
  90.582 -//            if (jep.getDocument() instanceof BaseDocument) {
  90.583 -//                BaseDocument document = (BaseDocument) jep.getDocument();
  90.584 -//                final org.netbeans.editor.Formatter f = document.getFormatter();
  90.585 -//                try {
  90.586 -//                    f.reformatLock();
  90.587 -//                    try {
  90.588 -//                        int reformattedLen = f.reformat(document, 0, document.getLength());
  90.589 -//                    } catch (BadLocationException ex) {
  90.590 -//                        Exceptions.printStackTrace(ex);
  90.591 -//                    }
  90.592 -//                } finally {
  90.593 -//                    f.reformatUnlock();
  90.594 -//                }
  90.595 -//            }
  90.596 -
  90.597 -            // Hacky code to do preview: We want to preview blank text without
  90.598 -            // a data object... this doesn't work very well so requires some hacks
  90.599 -            // to create a temp file, format it, then save it and delete it
  90.600 -            // (to avoid save confirmation dialogs on the modified file etc)
  90.601 -            PythonFormatter formatter = new PythonFormatter(codeStyle);
  90.602 -            PythonParserResult info = null;
  90.603 -            File tmp = null;
  90.604 -            FileObject tmpFo = null;
  90.605 -            if (formatter.needsParserResult()) {
  90.606 -                try {
  90.607 -                    tmp = File.createTempFile("preview", ".py"); // NOI18N
  90.608 -                    BufferedWriter writer = new BufferedWriter(new FileWriter(tmp));
  90.609 -                    writer.write(previewText);
  90.610 -                    writer.close();
  90.611 -                    final FileObject fo = FileUtil.toFileObject(FileUtil.normalizeFile(tmp));
  90.612 -                    tmpFo = fo;
  90.613 -                    // TODO - I need to get the classpath involved here such that it can
  90.614 -                    // find used/unused libraries
  90.615 -//                    if (!SourceUtils.isScanInProgress()) {
  90.616 -//                        // I'm using custom GSF code here because I want to set up an explicit
  90.617 -//                        // source path for the fake file object which includes the Python
  90.618 -//                        // libraries (since we need them for the isSystemModule lookup
  90.619 -//                        //SourceModel model = SourceModelFactory.getInstance().getModel(fo);
  90.620 -//                        //if (model != null && !model.isScanInProgress()) {
  90.621 -//                        List<FileObject> roots = new ArrayList<FileObject>(new PythonLanguage().getCoreLibraries());
  90.622 -//
  90.623 -//                        final PythonPlatformManager manager = PythonPlatformManager.getInstance();
  90.624 -//                        final String platformName = manager.getDefaultPlatform();
  90.625 -//                        PythonPlatform activePlatform = manager.getPlatform(platformName);
  90.626 -//                        if (activePlatform != null) {
  90.627 -//                            roots.addAll(activePlatform.getUniqueLibraryRoots());
  90.628 -//                            ClassPath boot = ClassPathSupport.createClassPath(roots.toArray(new FileObject[roots.size()]));
  90.629 -//                            ClassPath source = ClassPathSupport.createClassPath(new FileObject[]{fo.getParent()});
  90.630 -//                            ClassPath compile = source;
  90.631 -//
  90.632 -//                            ClasspathInfo cpInfo = ClasspathInfo.create(boot, compile, source);
  90.633 -//                            Source model = Source.create(cpInfo, fo);
  90.634 -//                            if (model != null) {
  90.635 -//                                final CompilationInfo[] infoHolder = new CompilationInfo[1];
  90.636 -//                                //model.runUserActionTask(new CancellableTask<CompilationInfo>() {
  90.637 -//                                model.runUserActionTask(new CancellableTask<CompilationController>() {
  90.638 -//                                    public void cancel() {
  90.639 -//                                    }
  90.640 -//
  90.641 -//                                    //public void run(CompilationInfo info) throws Exception {
  90.642 -//                                    public void run(CompilationController info) throws Exception {
  90.643 -//                                        info.toPhase(Phase.RESOLVED);
  90.644 -//                                        infoHolder[0] = info;
  90.645 -//                                        // Force open so info.getFileObject will succeed
  90.646 -//                                        GsfUtilities.getDocument(fo, true);
  90.647 -//                                    }
  90.648 -//                                }, false);
  90.649 -//                                info = infoHolder[0];
  90.650 -//                            }
  90.651 -//                        }
  90.652 -//                    }
  90.653 -                } catch (IOException ex) {
  90.654 -                    Exceptions.printStackTrace(ex);
  90.655 -                }
  90.656 -            }
  90.657 -            try {
  90.658 -                if (info != null && info.getSnapshot().getSource().getDocument(false) != null) {
  90.659 -                    Document doc = info.getSnapshot().getSource().getDocument(false);
  90.660 -                    formatter.reformat(null, doc, 0, doc.getLength(), info);
  90.661 -                    jep.setText(doc.getText(0, doc.getLength()));
  90.662 -                    // Save file to avoid warning on exit
  90.663 -                    DataObject dobj = DataObject.find(info.getSnapshot().getSource().getFileObject());
  90.664 -                    SaveCookie cookie = dobj.getCookie(SaveCookie.class);
  90.665 -                    if (cookie != null) {
  90.666 -                        cookie.save();
  90.667 -                    }
  90.668 -                } else {
  90.669 -                    Document doc = jep.getDocument();
  90.670 -                    if (doc.getLength() > 0) {
  90.671 -                        doc.remove(0, doc.getLength());
  90.672 -                    }
  90.673 -                    doc.insertString(0, previewText, null);
  90.674 -                    formatter.reformat(null, doc, 0, doc.getLength(), null);
  90.675 -                    jep.setText(doc.getText(0, doc.getLength()));
  90.676 -                }
  90.677 -            } catch (DataObjectNotFoundException dof) {
  90.678 -                Exceptions.printStackTrace(dof);
  90.679 -            } catch (IOException | BadLocationException ioe) {
  90.680 -                Exceptions.printStackTrace(ioe);
  90.681 -            }
  90.682 -
  90.683 -            if (tmpFo != null) {
  90.684 -                try {
  90.685 -                    tmpFo.delete();
  90.686 -                } catch (IOException ex) {
  90.687 -                    Exceptions.printStackTrace(ex);
  90.688 -                }
  90.689 -            } else if (tmp != null) {
  90.690 -                tmp.delete();
  90.691 -            }
  90.692 -
  90.693 -
  90.694 -            jep.setIgnoreRepaint(false);
  90.695 -            jep.scrollRectToVisible(new Rectangle(0, 0, 10, 10));
  90.696 -            jep.repaint(100);
  90.697 -        }
  90.698 -
  90.699 -        // PreferencesCustomizer implementation --------------------------------
  90.700 -        @Override
  90.701 -        public JComponent getComponent() {
  90.702 -            return panel;
  90.703 -        }
  90.704 -
  90.705 -        @Override
  90.706 -        public String getDisplayName() {
  90.707 -            return panel.getName();
  90.708 -        }
  90.709 -
  90.710 -        @Override
  90.711 -        public String getId() {
  90.712 -            return id;
  90.713 -        }
  90.714 -
  90.715 -        @Override
  90.716 -        public HelpCtx getHelpCtx() {
  90.717 -            return null;
  90.718 -        }
  90.719 -
  90.720 -        // PreferencesCustomizer.Factory implementation ------------------------
  90.721 -        public static final class Factory implements PreferencesCustomizer.Factory {
  90.722 -            private final String id;
  90.723 -            private final Class<? extends JPanel> panelClass;
  90.724 -            private final String previewText;
  90.725 -            private final String[][] forcedOptions;
  90.726 -
  90.727 -            public Factory(String id, Class<? extends JPanel> panelClass, String previewText, String[]... forcedOptions) {
  90.728 -                this.id = id;
  90.729 -                this.panelClass = panelClass;
  90.730 -                this.previewText = previewText;
  90.731 -                this.forcedOptions = forcedOptions;
  90.732 -            }
  90.733 -
  90.734 -            @Override
  90.735 -            public PreferencesCustomizer create(Preferences preferences) {
  90.736 -                try {
  90.737 -                    return new CategorySupport(preferences, id, panelClass.newInstance(), previewText, forcedOptions);
  90.738 -                } catch (IllegalAccessException | InstantiationException e) {
  90.739 -                    return null;
  90.740 -                }
  90.741 -            }
  90.742 -        } // End of CategorySupport.Factory class
  90.743 -
  90.744 -        // Private methods -----------------------------------------------------
  90.745 -        private void performOperation(int operation, JComponent jc, String optionID, Preferences p) {
  90.746 -            switch (operation) {
  90.747 -            case LOAD:
  90.748 -                loadData(jc, optionID, p);
  90.749 -                break;
  90.750 -            case STORE:
  90.751 -                storeData(jc, optionID, p);
  90.752 -                break;
  90.753 -            case ADD_LISTENERS:
  90.754 -                addListener(jc);
  90.755 -                break;
  90.756 -            }
  90.757 -        }
  90.758 -
  90.759 -        private void scan(int what, Preferences p) {
  90.760 -            for (JComponent jc : components) {
  90.761 -                Object o = jc.getClientProperty(OPTION_ID);
  90.762 -                if (o instanceof String) {
  90.763 -                    performOperation(what, jc, (String)o, p);
  90.764 -                } else if (o instanceof String[]) {
  90.765 -                    for (String oid : (String[])o) {
  90.766 -                        performOperation(what, jc, oid, p);
  90.767 -                    }
  90.768 -                }
  90.769 -            }
  90.770 -        }
  90.771 -
  90.772 -        private void scan(Container container, List<JComponent> components) {
  90.773 -            for (Component c : container.getComponents()) {
  90.774 -                if (c instanceof JComponent) {
  90.775 -                    JComponent jc = (JComponent)c;
  90.776 -                    Object o = jc.getClientProperty(OPTION_ID);
  90.777 -                    if (o instanceof String || o instanceof String[]) {
  90.778 -                        components.add(jc);
  90.779 -                    }
  90.780 -                }
  90.781 -                if (c instanceof Container) {
  90.782 -                    scan((Container)c, components);
  90.783 -                }
  90.784 -            }
  90.785 -        }
  90.786 -
  90.787 -        /** Very smart method which tries to set the values in the components correctly
  90.788 -         */
  90.789 -        private void loadData(JComponent jc, String optionID, Preferences node) {
  90.790 -
  90.791 -            if (jc instanceof JTextField) {
  90.792 -                JTextField field = (JTextField)jc;
  90.793 -                field.setText(node.get(optionID, getDefaultAsString(optionID)));
  90.794 -            } else if (jc instanceof JCheckBox) {
  90.795 -                JCheckBox checkBox = (JCheckBox)jc;
  90.796 -                boolean df = getDefaultAsBoolean(optionID);
  90.797 -                checkBox.setSelected(node.getBoolean(optionID, df));
  90.798 -            } else if (jc instanceof JComboBox) {
  90.799 -                JComboBox cb = (JComboBox)jc;
  90.800 -                String value = node.get(optionID, getDefaultAsString(optionID));
  90.801 -                ComboBoxModel model = createModel(value);
  90.802 -                cb.setModel(model);
  90.803 -                ComboItem item = whichItem(value, model);
  90.804 -                cb.setSelectedItem(item);
  90.805 -            }
  90.806 -
  90.807 -        }
  90.808 -
  90.809 -        private void storeData(JComponent jc, String optionID, Preferences node) {
  90.810 -
  90.811 -            if (jc instanceof JTextField) {
  90.812 -                JTextField field = (JTextField)jc;
  90.813 -
  90.814 -                String text = field.getText();
  90.815 -
  90.816 -                // XXX test for numbers
  90.817 -                if (isInteger(optionID)) {
  90.818 -                    try {
  90.819 -                        int i = Integer.parseInt(text);
  90.820 -                    } catch (NumberFormatException e) {
  90.821 -                        return;
  90.822 -                    }
  90.823 -                }
  90.824 -
  90.825 -                // XXX: watch out, tabSize, spacesPerTab, indentSize and expandTabToSpaces
  90.826 -                // fall back on getGlopalXXX() values and not getDefaultAsXXX value,
  90.827 -                // which is why we must not remove them. Proper solution would be to
  90.828 -                // store formatting preferences to MimeLookup and not use NbPreferences.
  90.829 -                // The problem currently is that MimeLookup based Preferences do not support subnodes.
  90.830 -                if (!optionID.equals(tabSize) &&
  90.831 -                        !optionID.equals(spacesPerTab) && !optionID.equals(indentSize) &&
  90.832 -                        getDefaultAsString(optionID).equals(text)) {
  90.833 -                    node.remove(optionID);
  90.834 -                } else {
  90.835 -                    node.put(optionID, text);
  90.836 -                }
  90.837 -            } else if (jc instanceof JCheckBox) {
  90.838 -                JCheckBox checkBox = (JCheckBox)jc;
  90.839 -                if (!optionID.equals(expandTabToSpaces) && getDefaultAsBoolean(optionID) == checkBox.isSelected()) {
  90.840 -                    node.remove(optionID);
  90.841 -                } else {
  90.842 -                    node.putBoolean(optionID, checkBox.isSelected());
  90.843 -                }
  90.844 -            } else if (jc instanceof JComboBox) {
  90.845 -                JComboBox cb = (JComboBox)jc;
  90.846 -                // Logger.global.info( cb.getSelectedItem() + " " + optionID);
  90.847 -                String value = ((ComboItem)cb.getSelectedItem()).value;
  90.848 -                if (getDefaultAsString(optionID).equals(value)) {
  90.849 -                    node.remove(optionID);
  90.850 -                } else {
  90.851 -                    node.put(optionID, value);
  90.852 -                }
  90.853 -            }
  90.854 -        }
  90.855 -
  90.856 -        private void addListener(JComponent jc) {
  90.857 -            if (jc instanceof JTextField) {
  90.858 -                JTextField field = (JTextField)jc;
  90.859 -                field.addActionListener(this);
  90.860 -                field.getDocument().addDocumentListener(this);
  90.861 -            } else if (jc instanceof JCheckBox) {
  90.862 -                JCheckBox checkBox = (JCheckBox)jc;
  90.863 -                checkBox.addActionListener(this);
  90.864 -            } else if (jc instanceof JComboBox) {
  90.865 -                JComboBox cb = (JComboBox)jc;
  90.866 -                cb.addActionListener(this);
  90.867 -            }
  90.868 -        }
  90.869 -
  90.870 -        private ComboBoxModel createModel(String value) {
  90.871 -
  90.872 -            // is it imports?
  90.873 -            for (ComboItem comboItem : cleanupImports) {
  90.874 -                if (value.equals(comboItem.value)) {
  90.875 -                    return new DefaultComboBoxModel(cleanupImports);
  90.876 -                }
  90.877 -            }
  90.878 -
  90.879 -            // is it wrap
  90.880 -            for (ComboItem comboItem : wrap) {
  90.881 -                if (value.equals(comboItem.value)) {
  90.882 -                    return new DefaultComboBoxModel(wrap);
  90.883 -                }
  90.884 -            }
  90.885 -
  90.886 -            return null;
  90.887 -        }
  90.888 -
  90.889 -        private static ComboItem whichItem(String value, ComboBoxModel model) {
  90.890 -
  90.891 -            for (int i = 0; i < model.getSize(); i++) {
  90.892 -                ComboItem item = (ComboItem)model.getElementAt(i);
  90.893 -                if (value.equals(item.value)) {
  90.894 -                    return item;
  90.895 -                }
  90.896 -            }
  90.897 -            return null;
  90.898 -        }
  90.899 -
  90.900 -        private static class ComboItem {
  90.901 -            String value;
  90.902 -            String displayName;
  90.903 -
  90.904 -            public ComboItem(String value, String key) {
  90.905 -                this.value = value;
  90.906 -                this.displayName = NbBundle.getMessage(FmtOptions.class, key);
  90.907 -            }
  90.908 -
  90.909 -            @Override
  90.910 -            public String toString() {
  90.911 -                return displayName;
  90.912 -            }
  90.913 -        }
  90.914 -    }
  90.915 -
  90.916 -    public static class PreviewPreferences extends AbstractPreferences {
  90.917 -        private Map<String, Object> map = new HashMap<>();
  90.918 -
  90.919 -        public PreviewPreferences() {
  90.920 -            super(null, ""); // NOI18N
  90.921 -        }
  90.922 -
  90.923 -        @Override
  90.924 -        protected void putSpi(String key, String value) {
  90.925 -            map.put(key, value);
  90.926 -        }
  90.927 -
  90.928 -        @Override
  90.929 -        protected String getSpi(String key) {
  90.930 -            return (String)map.get(key);
  90.931 -        }
  90.932 -
  90.933 -        @Override
  90.934 -        protected void removeSpi(String key) {
  90.935 -            map.remove(key);
  90.936 -        }
  90.937 -
  90.938 -        @Override
  90.939 -        protected void removeNodeSpi() throws BackingStoreException {
  90.940 -            throw new UnsupportedOperationException("Not supported yet.");
  90.941 -        }
  90.942 -
  90.943 -        @Override
  90.944 -        protected String[] keysSpi() throws BackingStoreException {
  90.945 -            String array[] = new String[map.keySet().size()];
  90.946 -            return map.keySet().toArray(array);
  90.947 -        }
  90.948 -
  90.949 -        @Override
  90.950 -        protected String[] childrenNamesSpi() throws BackingStoreException {
  90.951 -            throw new UnsupportedOperationException("Not supported yet.");
  90.952 -        }
  90.953 -
  90.954 -        @Override
  90.955 -        protected AbstractPreferences childSpi(String name) {
  90.956 -            throw new UnsupportedOperationException("Not supported yet.");
  90.957 -        }
  90.958 -
  90.959 -        @Override
  90.960 -        protected void syncSpi() throws BackingStoreException {
  90.961 -            throw new UnsupportedOperationException("Not supported yet.");
  90.962 -        }
  90.963 -
  90.964 -        @Override
  90.965 -        protected void flushSpi() throws BackingStoreException {
  90.966 -            throw new UnsupportedOperationException("Not supported yet.");
  90.967 -        }
  90.968 -    }
  90.969 -
  90.970 -    // read-only, no subnodes
  90.971 -    public static final class ProxyPreferences extends AbstractPreferences {
  90.972 -        private final Preferences[] delegates;
  90.973 -
  90.974 -        public ProxyPreferences(Preferences... delegates) {
  90.975 -            super(null, ""); // NOI18N
  90.976 -            this.delegates = delegates;
  90.977 -        }
  90.978 -
  90.979 -        @Override
  90.980 -        protected void putSpi(String key, String value) {
  90.981 -            throw new UnsupportedOperationException("Not supported yet.");
  90.982 -        }
  90.983 -
  90.984 -        @Override
  90.985 -        protected String getSpi(String key) {
  90.986 -            for (Preferences p : delegates) {
  90.987 -                String value = p.get(key, null);
  90.988 -                if (value != null) {
  90.989 -                    return value;
  90.990 -                }
  90.991 -            }
  90.992 -            return null;
  90.993 -        }
  90.994 -
  90.995 -        @Override
  90.996 -        protected void removeSpi(String key) {
  90.997 -            throw new UnsupportedOperationException("Not supported yet.");
  90.998 -        }
  90.999 -
 90.1000 -        @Override
 90.1001 -        protected void removeNodeSpi() throws BackingStoreException {
 90.1002 -            throw new UnsupportedOperationException("Not supported yet.");
 90.1003 -        }
 90.1004 -
 90.1005 -        @Override
 90.1006 -        protected String[] keysSpi() throws BackingStoreException {
 90.1007 -            Set<String> keys = new HashSet<>();
 90.1008 -            for (Preferences p : delegates) {
 90.1009 -                keys.addAll(Arrays.asList(p.keys()));
 90.1010 -            }
 90.1011 -            return keys.toArray(new String[keys.size()]);
 90.1012 -        }
 90.1013 -
 90.1014 -        @Override
 90.1015 -        protected String[] childrenNamesSpi() throws BackingStoreException {
 90.1016 -            throw new UnsupportedOperationException("Not supported yet.");
 90.1017 -        }
 90.1018 -
 90.1019 -        @Override
 90.1020 -        protected AbstractPreferences childSpi(String name) {
 90.1021 -            throw new UnsupportedOperationException("Not supported yet.");
 90.1022 -        }
 90.1023 -
 90.1024 -        @Override
 90.1025 -        protected void syncSpi() throws BackingStoreException {
 90.1026 -            throw new UnsupportedOperationException("Not supported yet.");
 90.1027 -        }
 90.1028 -
 90.1029 -        @Override
 90.1030 -        protected void flushSpi() throws BackingStoreException {
 90.1031 -            throw new UnsupportedOperationException("Not supported yet.");
 90.1032 -        }
 90.1033 -    } // End of ProxyPreferences class
 90.1034 -
 90.1035 -    public static interface CodeStyleProducer {
 90.1036 -        public CodeStyle create(Preferences preferences);
 90.1037 -    }
 90.1038 -}
    91.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtSpaces.form	Fri Sep 18 16:20:24 2015 -0500
    91.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.3 @@ -1,104 +0,0 @@
    91.4 -<?xml version="1.0" encoding="UTF-8" ?>
    91.5 -
    91.6 -<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    91.7 -  <Properties>
    91.8 -    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    91.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;)"/>
   91.10 -    </Property>
   91.11 -    <Property name="opaque" type="boolean" value="false"/>
   91.12 -  </Properties>
   91.13 -  <AuxValues>
   91.14 -    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   91.15 -    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   91.16 -    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   91.17 -    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
   91.18 -    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   91.19 -    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
   91.20 -    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
   91.21 -    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   91.22 -    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   91.23 -  </AuxValues>
   91.24 -
   91.25 -  <Layout>
   91.26 -    <DimensionLayout dim="0">
   91.27 -      <Group type="103" groupAlignment="0" attributes="0">
   91.28 -          <Group type="102" attributes="0">
   91.29 -              <Group type="103" groupAlignment="0" attributes="0">
   91.30 -                  <Component id="addAroundOp" alignment="0" min="-2" max="-2" attributes="0"/>
   91.31 -                  <Group type="102" alignment="0" attributes="0">
   91.32 -                      <EmptySpace min="27" pref="27" max="27" attributes="0"/>
   91.33 -                      <Component id="removeInParam" min="-2" max="-2" attributes="0"/>
   91.34 -                  </Group>
   91.35 -                  <Component id="removeInParen" alignment="0" min="-2" max="-2" attributes="0"/>
   91.36 -                  <Component id="addAfterComma" alignment="0" min="-2" max="-2" attributes="0"/>
   91.37 -                  <Component id="removeBeforeSep" alignment="0" min="-2" max="-2" attributes="0"/>
   91.38 -                  <Component id="collapseSpacesCb" alignment="0" min="-2" max="-2" attributes="0"/>
   91.39 -              </Group>
   91.40 -              <EmptySpace max="32767" attributes="0"/>
   91.41 -          </Group>
   91.42 -      </Group>
   91.43 -    </DimensionLayout>
   91.44 -    <DimensionLayout dim="1">
   91.45 -      <Group type="103" groupAlignment="0" attributes="0">
   91.46 -          <Group type="102" alignment="0" attributes="0">
   91.47 -              <Component id="addAroundOp" min="-2" max="-2" attributes="0"/>
   91.48 -              <EmptySpace max="-2" attributes="0"/>
   91.49 -              <Component id="removeInParam" min="-2" max="-2" attributes="0"/>
   91.50 -              <EmptySpace max="-2" attributes="0"/>
   91.51 -              <Component id="removeInParen" min="-2" max="-2" attributes="0"/>
   91.52 -              <EmptySpace max="-2" attributes="0"/>
   91.53 -              <Component id="addAfterComma" min="-2" max="-2" attributes="0"/>
   91.54 -              <EmptySpace max="-2" attributes="0"/>
   91.55 -              <Component id="removeBeforeSep" min="-2" max="-2" attributes="0"/>
   91.56 -              <EmptySpace max="-2" attributes="0"/>
   91.57 -              <Component id="collapseSpacesCb" min="-2" max="-2" attributes="0"/>
   91.58 -              <EmptySpace max="32767" attributes="0"/>
   91.59 -          </Group>
   91.60 -      </Group>
   91.61 -    </DimensionLayout>
   91.62 -  </Layout>
   91.63 -  <SubComponents>
   91.64 -    <Component class="javax.swing.JCheckBox" name="addAroundOp">
   91.65 -      <Properties>
   91.66 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   91.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;)"/>
   91.68 -        </Property>
   91.69 -      </Properties>
   91.70 -    </Component>
   91.71 -    <Component class="javax.swing.JCheckBox" name="removeInParam">
   91.72 -      <Properties>
   91.73 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   91.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;)"/>
   91.75 -        </Property>
   91.76 -      </Properties>
   91.77 -    </Component>
   91.78 -    <Component class="javax.swing.JCheckBox" name="removeInParen">
   91.79 -      <Properties>
   91.80 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   91.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;)"/>
   91.82 -        </Property>
   91.83 -      </Properties>
   91.84 -    </Component>
   91.85 -    <Component class="javax.swing.JCheckBox" name="addAfterComma">
   91.86 -      <Properties>
   91.87 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   91.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;)"/>
   91.89 -        </Property>
   91.90 -      </Properties>
   91.91 -    </Component>
   91.92 -    <Component class="javax.swing.JCheckBox" name="removeBeforeSep">
   91.93 -      <Properties>
   91.94 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   91.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;)"/>
   91.96 -        </Property>
   91.97 -      </Properties>
   91.98 -    </Component>
   91.99 -    <Component class="javax.swing.JCheckBox" name="collapseSpacesCb">
  91.100 -      <Properties>
  91.101 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  91.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;)"/>
  91.103 -        </Property>
  91.104 -      </Properties>
  91.105 -    </Component>
  91.106 -  </SubComponents>
  91.107 -</Form>
    92.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtSpaces.java	Fri Sep 18 16:20:24 2015 -0500
    92.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.3 @@ -1,143 +0,0 @@
    92.4 -/*
    92.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    92.6 - *
    92.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    92.8 - *
    92.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   92.10 - * Other names may be trademarks of their respective owners.
   92.11 - *
   92.12 - * The contents of this file are subject to the terms of either the GNU
   92.13 - * General Public License Version 2 only ("GPL") or the Common
   92.14 - * Development and Distribution License("CDDL") (collectively, the
   92.15 - * "License"). You may not use this file except in compliance with the
   92.16 - * License. You can obtain a copy of the License at
   92.17 - * http://www.netbeans.org/cddl-gplv2.html
   92.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   92.19 - * specific language governing permissions and limitations under the
   92.20 - * License.  When distributing the software, include this License Header
   92.21 - * Notice in each file and include the License file at
   92.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   92.23 - * particular file as subject to the "Classpath" exception as provided
   92.24 - * by Oracle in the GPL Version 2 section of the License file that
   92.25 - * accompanied this code. If applicable, add the following below the
   92.26 - * License Header, with the fields enclosed by brackets [] replaced by
   92.27 - * your own identifying information:
   92.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   92.29 - *
   92.30 - * Contributor(s):
   92.31 - *
   92.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   92.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   92.34 - * Microsystems, Inc. All Rights Reserved.
   92.35 - *
   92.36 - * If you wish your version of this file to be governed by only the CDDL
   92.37 - * or only the GPL Version 2, indicate your decision by adding
   92.38 - * "[Contributor] elects to include this software in this distribution
   92.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   92.40 - * single choice of license, a recipient has the option to distribute
   92.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   92.42 - * to extend the choice of license to its licensees as provided above.
   92.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   92.44 - * Version 2 license, then the option applies only if the new code is
   92.45 - * made subject to such option by the copyright holder.
   92.46 - */
   92.47 -
   92.48 -package org.netbeans.modules.python.editor.options;
   92.49 -
   92.50 -import javax.swing.JPanel;
   92.51 -import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
   92.52 -import static org.netbeans.modules.python.editor.options.FmtOptions.*;
   92.53 -import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
   92.54 -
   92.55 -/**
   92.56 - * Preferences for formatting related to spaces
   92.57 - * 
   92.58 - * @author  Tor Norbye
   92.59 - */
   92.60 -public class FmtSpaces extends JPanel {
   92.61 -    public FmtSpaces() {
   92.62 -        initComponents();
   92.63 -
   92.64 -        addAroundOp.putClientProperty(OPTION_ID, addSpaceAroundOperators);
   92.65 -        addAfterComma.putClientProperty(OPTION_ID, addSpaceAfterComma);
   92.66 -        removeBeforeSep.putClientProperty(OPTION_ID, removeSpaceBeforeSep);
   92.67 -        removeInParam.putClientProperty(OPTION_ID, removeSpaceInParamAssign);
   92.68 -        removeInParen.putClientProperty(OPTION_ID, removeSpaceInParens);
   92.69 -        collapseSpacesCb.putClientProperty(OPTION_ID, collapseSpaces);
   92.70 -    }
   92.71 -
   92.72 -    public static PreferencesCustomizer.Factory getController() {
   92.73 -        return new CategorySupport.Factory("spaces", FmtSpaces.class, // NOI18N
   92.74 -                org.openide.util.NbBundle.getMessage(FmtSpaces.class, "SAMPLE_Spaces"));
   92.75 -    }
   92.76 -    
   92.77 -    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
   92.78 -    private void initComponents() {
   92.79 -
   92.80 -        addAroundOp = new javax.swing.JCheckBox();
   92.81 -        removeInParam = new javax.swing.JCheckBox();
   92.82 -        removeInParen = new javax.swing.JCheckBox();
   92.83 -        addAfterComma = new javax.swing.JCheckBox();
   92.84 -        removeBeforeSep = new javax.swing.JCheckBox();
   92.85 -        collapseSpacesCb = new javax.swing.JCheckBox();
   92.86 -
   92.87 -        setName(org.openide.util.NbBundle.getMessage(FmtSpaces.class, "LBL_Spaces")); // NOI18N
   92.88 -        setOpaque(false);
   92.89 -
   92.90 -        org.openide.awt.Mnemonics.setLocalizedText(addAroundOp, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.addAroundOp.text")); // NOI18N
   92.91 -
   92.92 -        org.openide.awt.Mnemonics.setLocalizedText(removeInParam, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.removeInParam.text")); // NOI18N
   92.93 -
   92.94 -        org.openide.awt.Mnemonics.setLocalizedText(removeInParen, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.removeInParen.text")); // NOI18N
   92.95 -
   92.96 -        org.openide.awt.Mnemonics.setLocalizedText(addAfterComma, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.addAfterComma.text")); // NOI18N
   92.97 -
   92.98 -        org.openide.awt.Mnemonics.setLocalizedText(removeBeforeSep, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.removeBeforeSep.text")); // NOI18N
   92.99 -
  92.100 -        org.openide.awt.Mnemonics.setLocalizedText(collapseSpacesCb, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.collapseSpacesCb.text")); // NOI18N
  92.101 -
  92.102 -        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
  92.103 -        this.setLayout(layout);
  92.104 -        layout.setHorizontalGroup(
  92.105 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  92.106 -            .addGroup(layout.createSequentialGroup()
  92.107 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  92.108 -                    .addComponent(addAroundOp)
  92.109 -                    .addGroup(layout.createSequentialGroup()
  92.110 -                        .addGap(27, 27, 27)
  92.111 -                        .addComponent(removeInParam))
  92.112 -                    .addComponent(removeInParen)
  92.113 -                    .addComponent(addAfterComma)
  92.114 -                    .addComponent(removeBeforeSep)
  92.115 -                    .addComponent(collapseSpacesCb))
  92.116 -                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  92.117 -        );
  92.118 -        layout.setVerticalGroup(
  92.119 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  92.120 -            .addGroup(layout.createSequentialGroup()
  92.121 -                .addComponent(addAroundOp)
  92.122 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  92.123 -                .addComponent(removeInParam)
  92.124 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  92.125 -                .addComponent(removeInParen)
  92.126 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  92.127 -                .addComponent(addAfterComma)
  92.128 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  92.129 -                .addComponent(removeBeforeSep)
  92.130 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  92.131 -                .addComponent(collapseSpacesCb)
  92.132 -                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  92.133 -        );
  92.134 -    }// </editor-fold>//GEN-END:initComponents
  92.135 -    
  92.136 -    
  92.137 -    // Variables declaration - do not modify//GEN-BEGIN:variables
  92.138 -    private javax.swing.JCheckBox addAfterComma;
  92.139 -    private javax.swing.JCheckBox addAroundOp;
  92.140 -    private javax.swing.JCheckBox collapseSpacesCb;
  92.141 -    private javax.swing.JCheckBox removeBeforeSep;
  92.142 -    private javax.swing.JCheckBox removeInParam;
  92.143 -    private javax.swing.JCheckBox removeInParen;
  92.144 -    // End of variables declaration//GEN-END:variables
  92.145 -    
  92.146 -}
    93.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtTabsIndents.form	Fri Sep 18 16:20:24 2015 -0500
    93.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    93.3 @@ -1,127 +0,0 @@
    93.4 -<?xml version="1.0" encoding="UTF-8" ?>
    93.5 -
    93.6 -<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    93.7 -  <Properties>
    93.8 -    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    93.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;)"/>
   93.10 -    </Property>
   93.11 -    <Property name="opaque" type="boolean" value="false"/>
   93.12 -  </Properties>
   93.13 -  <AuxValues>
   93.14 -    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   93.15 -    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   93.16 -    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   93.17 -    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
   93.18 -    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   93.19 -    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
   93.20 -    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
   93.21 -    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   93.22 -    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   93.23 -  </AuxValues>
   93.24 -
   93.25 -  <Layout>
   93.26 -    <DimensionLayout dim="0">
   93.27 -      <Group type="103" groupAlignment="0" attributes="0">
   93.28 -          <Group type="102" alignment="0" attributes="0">
   93.29 -              <Group type="103" groupAlignment="0" attributes="0">
   93.30 -                  <Component id="continuationIndentSizeLabel" max="32767" attributes="0"/>
   93.31 -                  <Component id="labelIndentLabel" min="-2" max="-2" attributes="0"/>
   93.32 -              </Group>
   93.33 -              <EmptySpace max="-2" attributes="0"/>
   93.34 -              <Group type="103" groupAlignment="1" attributes="0">
   93.35 -                  <Component id="continuationIndentSizeField" linkSize="2" min="-2" pref="36" max="-2" attributes="1"/>
   93.36 -                  <Component id="labelIndentField" linkSize="2" min="-2" pref="36" max="-2" attributes="1"/>
   93.37 -              </Group>
   93.38 -          </Group>
   93.39 -          <Component id="indentCasesFromSwitchCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
   93.40 -          <Component id="indentTopLevelClassMembersCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
   93.41 -          <Component id="absoluteLabelIndentCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
   93.42 -      </Group>
   93.43 -    </DimensionLayout>
   93.44 -    <DimensionLayout dim="1">
   93.45 -      <Group type="103" groupAlignment="0" attributes="0">
   93.46 -          <Group type="102" attributes="0">
   93.47 -              <EmptySpace max="-2" attributes="0"/>
   93.48 -              <Group type="103" groupAlignment="3" attributes="0">
   93.49 -                  <Component id="continuationIndentSizeLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   93.50 -                  <Component id="continuationIndentSizeField" alignment="3" min="-2" max="-2" attributes="0"/>
   93.51 -              </Group>
   93.52 -              <EmptySpace min="-2" max="-2" attributes="0"/>
   93.53 -              <Group type="103" groupAlignment="3" attributes="0">
   93.54 -                  <Component id="labelIndentLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   93.55 -                  <Component id="labelIndentField" alignment="3" min="-2" max="-2" attributes="0"/>
   93.56 -              </Group>
   93.57 -              <EmptySpace type="unrelated" max="-2" attributes="0"/>
   93.58 -              <Component id="absoluteLabelIndentCheckBox" min="-2" max="-2" attributes="0"/>
   93.59 -              <EmptySpace max="-2" attributes="0"/>
   93.60 -              <Component id="indentTopLevelClassMembersCheckBox" min="-2" max="-2" attributes="0"/>
   93.61 -              <EmptySpace max="-2" attributes="0"/>
   93.62 -              <Component id="indentCasesFromSwitchCheckBox" min="-2" max="-2" attributes="0"/>
   93.63 -              <EmptySpace max="32767" attributes="0"/>
   93.64 -          </Group>
   93.65 -      </Group>
   93.66 -    </DimensionLayout>
   93.67 -  </Layout>
   93.68 -  <SubComponents>
   93.69 -    <Component class="javax.swing.JLabel" name="continuationIndentSizeLabel">
   93.70 -      <Properties>
   93.71 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
   93.72 -          <ComponentRef name="continuationIndentSizeField"/>
   93.73 -        </Property>
   93.74 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   93.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;)"/>
   93.76 -        </Property>
   93.77 -      </Properties>
   93.78 -    </Component>
   93.79 -    <Component class="javax.swing.JTextField" name="continuationIndentSizeField">
   93.80 -    </Component>
   93.81 -    <Component class="javax.swing.JLabel" name="labelIndentLabel">
   93.82 -      <Properties>
   93.83 -        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
   93.84 -          <ComponentRef name="labelIndentField"/>
   93.85 -        </Property>
   93.86 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   93.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;)"/>
   93.88 -        </Property>
   93.89 -      </Properties>
   93.90 -    </Component>
   93.91 -    <Component class="javax.swing.JTextField" name="labelIndentField">
   93.92 -    </Component>
   93.93 -    <Component class="javax.swing.JCheckBox" name="absoluteLabelIndentCheckBox">
   93.94 -      <Properties>
   93.95 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   93.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;)"/>
   93.97 -        </Property>
   93.98 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
   93.99 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  93.100 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  93.101 -          </Border>
  93.102 -        </Property>
  93.103 -      </Properties>
  93.104 -    </Component>
  93.105 -    <Component class="javax.swing.JCheckBox" name="indentTopLevelClassMembersCheckBox">
  93.106 -      <Properties>
  93.107 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  93.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;)"/>
  93.109 -        </Property>
  93.110 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  93.111 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  93.112 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  93.113 -          </Border>
  93.114 -        </Property>
  93.115 -      </Properties>
  93.116 -    </Component>
  93.117 -    <Component class="javax.swing.JCheckBox" name="indentCasesFromSwitchCheckBox">
  93.118 -      <Properties>
  93.119 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  93.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;)"/>
  93.121 -        </Property>
  93.122 -        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  93.123 -          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
  93.124 -            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
  93.125 -          </Border>
  93.126 -        </Property>
  93.127 -      </Properties>
  93.128 -    </Component>
  93.129 -  </SubComponents>
  93.130 -</Form>
    94.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtTabsIndents.java	Fri Sep 18 16:20:24 2015 -0500
    94.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.3 @@ -1,196 +0,0 @@
    94.4 -/*
    94.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    94.6 - *
    94.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
    94.8 - *
    94.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   94.10 - * Other names may be trademarks of their respective owners.
   94.11 - *
   94.12 - * The contents of this file are subject to the terms of either the GNU
   94.13 - * General Public License Version 2 only ("GPL") or the Common
   94.14 - * Development and Distribution License("CDDL") (collectively, the
   94.15 - * "License"). You may not use this file except in compliance with the
   94.16 - * License. You can obtain a copy of the License at
   94.17 - * http://www.netbeans.org/cddl-gplv2.html
   94.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   94.19 - * specific language governing permissions and limitations under the
   94.20 - * License.  When distributing the software, include this License Header
   94.21 - * Notice in each file and include the License file at
   94.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   94.23 - * particular file as subject to the "Classpath" exception as provided
   94.24 - * by Oracle in the GPL Version 2 section of the License file that
   94.25 - * accompanied this code. If applicable, add the following below the
   94.26 - * License Header, with the fields enclosed by brackets [] replaced by
   94.27 - * your own identifying information:
   94.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   94.29 - *
   94.30 - * Contributor(s):
   94.31 - *
   94.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   94.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   94.34 - * Microsystems, Inc. All Rights Reserved.
   94.35 - *
   94.36 - * If you wish your version of this file to be governed by only the CDDL
   94.37 - * or only the GPL Version 2, indicate your decision by adding
   94.38 - * "[Contributor] elects to include this software in this distribution
   94.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   94.40 - * single choice of license, a recipient has the option to distribute
   94.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   94.42 - * to extend the choice of license to its licensees as provided above.
   94.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   94.44 - * Version 2 license, then the option applies only if the new code is
   94.45 - * made subject to such option by the copyright holder.
   94.46 - */
   94.47 -
   94.48 -package org.netbeans.modules.python.editor.options;
   94.49 -
   94.50 -import org.netbeans.modules.python.editor.options.CodeStyle.WrapStyle;
   94.51 -import static org.netbeans.modules.python.editor.options.FmtOptions.*;
   94.52 -import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
   94.53 -import org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport;
   94.54 -import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
   94.55 -
   94.56 -/**
   94.57 - *
   94.58 - * @author  phrebejk
   94.59 - */
   94.60 -public class FmtTabsIndents extends javax.swing.JPanel {
   94.61 -   
   94.62 -    /** Creates new form FmtTabsIndents */
   94.63 -    public FmtTabsIndents() {
   94.64 -        initComponents();
   94.65 -/*
   94.66 -//        expandTabCheckBox.putClientProperty(OPTION_ID, expandTabToSpaces);
   94.67 -//        tabSizeField.putClientProperty(OPTION_ID, tabSize);
   94.68 -//        indentSizeField.putClientProperty(OPTION_ID, new String [] { indentSize, spacesPerTab });
   94.69 -        continuationIndentSizeField.putClientProperty(OPTION_ID, continuationIndentSize);
   94.70 -        labelIndentField.putClientProperty(OPTION_ID, labelIndent);
   94.71 -        absoluteLabelIndentCheckBox.putClientProperty(OPTION_ID, absoluteLabelIndent);
   94.72 -        indentTopLevelClassMembersCheckBox.putClientProperty(OPTION_ID, indentTopLevelClassMembers);
   94.73 -        indentCasesFromSwitchCheckBox.putClientProperty(OPTION_ID, indentCasesFromSwitch);
   94.74 -//        rightMarginField.putClientProperty(OPTION_ID, rightMargin);
   94.75 -    }
   94.76 -    
   94.77 -    public static PreferencesCustomizer.Factory getController() {
   94.78 -        return new CategorySupport.Factory(PreferencesCustomizer.TABS_AND_INDENTS_ID, FmtTabsIndents.class, //NOI18N
   94.79 -                org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "SAMPLE_TabsIndents"), // NOI18N
   94.80 -                new String[] { FmtOptions.rightMargin, "30" }, //NOI18N
   94.81 -                new String[] { FmtOptions.wrapAnnotations, WrapStyle.WRAP_ALWAYS.name() },
   94.82 -                new String[] { FmtOptions.wrapArrayInit, WrapStyle.WRAP_ALWAYS.name() },
   94.83 -                new String[] { FmtOptions.wrapAssert, WrapStyle.WRAP_ALWAYS.name() },
   94.84 -                new String[] { FmtOptions.wrapAssignOps, WrapStyle.WRAP_ALWAYS.name() },
   94.85 -                new String[] { FmtOptions.wrapBinaryOps, WrapStyle.WRAP_ALWAYS.name() },
   94.86 -                new String[] { FmtOptions.wrapChainedMethodCalls, WrapStyle.WRAP_ALWAYS.name() },
   94.87 -                new String[] { FmtOptions.wrapDoWhileStatement, WrapStyle.WRAP_ALWAYS.name() },
   94.88 -                new String[] { FmtOptions.wrapEnumConstants, WrapStyle.WRAP_ALWAYS.name() },
   94.89 -                new String[] { FmtOptions.wrapExtendsImplementsKeyword, WrapStyle.WRAP_ALWAYS.name() },
   94.90 -                new String[] { FmtOptions.wrapExtendsImplementsList, WrapStyle.WRAP_ALWAYS.name() },
   94.91 -                new String[] { FmtOptions.wrapFor, WrapStyle.WRAP_ALWAYS.name() },
   94.92 -                new String[] { FmtOptions.wrapForStatement, WrapStyle.WRAP_ALWAYS.name() },
   94.93 -                new String[] { FmtOptions.wrapIfStatement, WrapStyle.WRAP_ALWAYS.name() },
   94.94 -                new String[] { FmtOptions.wrapMethodCallArgs, WrapStyle.WRAP_ALWAYS.name() },
   94.95 -                new String[] { FmtOptions.wrapMethodParams, WrapStyle.WRAP_ALWAYS.name() },
   94.96 -                new String[] { FmtOptions.wrapTernaryOps, WrapStyle.WRAP_ALWAYS.name() },
   94.97 -                new String[] { FmtOptions.wrapThrowsKeyword, WrapStyle.WRAP_ALWAYS.name() },
   94.98 -                new String[] { FmtOptions.wrapThrowsList, WrapStyle.WRAP_ALWAYS.name() },
   94.99 -                new String[] { FmtOptions.wrapWhileStatement, WrapStyle.WRAP_ALWAYS.name() },
  94.100 -                new String[] { FmtOptions.alignMultilineArrayInit, Boolean.FALSE.toString() },
  94.101 -                new String[] { FmtOptions.alignMultilineAssignment, Boolean.FALSE.toString() },
  94.102 -                new String[] { FmtOptions.alignMultilineBinaryOp, Boolean.FALSE.toString() },
  94.103 -                new String[] { FmtOptions.alignMultilineCallArgs, Boolean.FALSE.toString() },
  94.104 -                new String[] { FmtOptions.alignMultilineFor, Boolean.FALSE.toString() },
  94.105 -                new String[] { FmtOptions.alignMultilineImplements, Boolean.FALSE.toString() },
  94.106 -                new String[] { FmtOptions.alignMultilineMethodParams, Boolean.FALSE.toString() },
  94.107 -                new String[] { FmtOptions.alignMultilineParenthesized, Boolean.FALSE.toString() },
  94.108 -                new String[] { FmtOptions.alignMultilineTernaryOp, Boolean.FALSE.toString() },
  94.109 -                new String[] { FmtOptions.alignMultilineThrows, Boolean.FALSE.toString() }
  94.110 -                );
  94.111 - */
  94.112 -    }
  94.113 -    
  94.114 -    /** This method is called from within the constructor to
  94.115 -     * initialize the form.
  94.116 -     * WARNING: Do NOT modify this code. The content of this method is
  94.117 -     * always regenerated by the Form Editor.
  94.118 -     */
  94.119 -    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  94.120 -    private void initComponents() {
  94.121 -
  94.122 -        continuationIndentSizeLabel = new javax.swing.JLabel();
  94.123 -        continuationIndentSizeField = new javax.swing.JTextField();
  94.124 -        labelIndentLabel = new javax.swing.JLabel();
  94.125 -        labelIndentField = new javax.swing.JTextField();
  94.126 -        absoluteLabelIndentCheckBox = new javax.swing.JCheckBox();
  94.127 -        indentTopLevelClassMembersCheckBox = new javax.swing.JCheckBox();
  94.128 -        indentCasesFromSwitchCheckBox = new javax.swing.JCheckBox();
  94.129 -
  94.130 -        setName(org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_TabsAndIndents")); // NOI18N
  94.131 -        setOpaque(false);
  94.132 -
  94.133 -        continuationIndentSizeLabel.setLabelFor(continuationIndentSizeField);
  94.134 -        org.openide.awt.Mnemonics.setLocalizedText(continuationIndentSizeLabel, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_ContinuationIndentSize")); // NOI18N
  94.135 -
  94.136 -        labelIndentLabel.setLabelFor(labelIndentField);
  94.137 -        org.openide.awt.Mnemonics.setLocalizedText(labelIndentLabel, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_LabelIndent")); // NOI18N
  94.138 -
  94.139 -        org.openide.awt.Mnemonics.setLocalizedText(absoluteLabelIndentCheckBox, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_AbsoluteLabelIndent")); // NOI18N
  94.140 -        absoluteLabelIndentCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  94.141 -
  94.142 -        org.openide.awt.Mnemonics.setLocalizedText(indentTopLevelClassMembersCheckBox, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_IndentTopLevelClassMemberts")); // NOI18N
  94.143 -        indentTopLevelClassMembersCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  94.144 -
  94.145 -        org.openide.awt.Mnemonics.setLocalizedText(indentCasesFromSwitchCheckBox, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_IndentCasesFromSwitch")); // NOI18N
  94.146 -        indentCasesFromSwitchCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
  94.147 -
  94.148 -        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
  94.149 -        this.setLayout(layout);
  94.150 -        layout.setHorizontalGroup(
  94.151 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  94.152 -            .addGroup(layout.createSequentialGroup()
  94.153 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  94.154 -                    .addComponent(continuationIndentSizeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
  94.155 -                    .addComponent(labelIndentLabel))
  94.156 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  94.157 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
  94.158 -                    .addComponent(continuationIndentSizeField, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE)
  94.159 -                    .addComponent(labelIndentField, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE)))
  94.160 -            .addComponent(indentCasesFromSwitchCheckBox)
  94.161 -            .addComponent(indentTopLevelClassMembersCheckBox)
  94.162 -            .addComponent(absoluteLabelIndentCheckBox)
  94.163 -        );
  94.164 -
  94.165 -        layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {continuationIndentSizeField, labelIndentField});
  94.166 -
  94.167 -        layout.setVerticalGroup(
  94.168 -            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  94.169 -            .addGroup(layout.createSequentialGroup()
  94.170 -                .addContainerGap()
  94.171 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  94.172 -                    .addComponent(continuationIndentSizeLabel)
  94.173 -                    .addComponent(continuationIndentSizeField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
  94.174 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  94.175 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
  94.176 -                    .addComponent(labelIndentLabel)
  94.177 -                    .addComponent(labelIndentField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
  94.178 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
  94.179 -                .addComponent(absoluteLabelIndentCheckBox)
  94.180 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  94.181 -                .addComponent(indentTopLevelClassMembersCheckBox)
  94.182 -                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  94.183 -                .addComponent(indentCasesFromSwitchCheckBox)
  94.184 -                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
  94.185 -        );
  94.186 -    }// </editor-fold>//GEN-END:initComponents
  94.187 -    
  94.188 -    
  94.189 -    // Variables declaration - do not modify//GEN-BEGIN:variables
  94.190 -    private javax.swing.JCheckBox absoluteLabelIndentCheckBox;
  94.191 -    private javax.swing.JTextField continuationIndentSizeField;
  94.192 -    private javax.swing.JLabel continuationIndentSizeLabel;
  94.193 -    private javax.swing.JCheckBox indentCasesFromSwitchCheckBox;
  94.194 -    private javax.swing.JCheckBox indentTopLevelClassMembersCheckBox;
  94.195 -    private javax.swing.JTextField labelIndentField;
  94.196 -    private javax.swing.JLabel labelIndentLabel;
  94.197 -    // End of variables declaration//GEN-END:variables
  94.198 -    
  94.199 -}
    95.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtWrapping.form	Fri Sep 18 16:20:24 2015 -0500
    95.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.3 @@ -1,706 +0,0 @@
    95.4 -<?xml version="1.0" encoding="UTF-8" ?>
    95.5 -
    95.6 -<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    95.7 -  <Properties>
    95.8 -    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    95.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;)"/>
   95.10 -    </Property>
   95.11 -    <Property name="opaque" type="boolean" value="false"/>
   95.12 -  </Properties>
   95.13 -  <AuxValues>
   95.14 -    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   95.15 -    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   95.16 -    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   95.17 -    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
   95.18 -    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   95.19 -    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
   95.20 -    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
   95.21 -    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   95.22 -    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   95.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"/>
   95.24 -  </AuxValues>
   95.25 -
   95.26 -  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
   95.27 -  <SubComponents>
   95.28 -    <Container class="javax.swing.JScrollPane" name="scrollPane">
   95.29 -      <Properties>
   95.30 -        <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
   95.31 -          <Dimension value="[300, 200]"/>
   95.32 -        </Property>
   95.33 -        <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
   95.34 -          <Dimension value="[350, 600]"/>
   95.35 -        </Property>
   95.36 -      </Properties>
   95.37 -      <Constraints>
   95.38 -        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
   95.39 -          <BorderConstraints direction="Center"/>
   95.40 -        </Constraint>
   95.41 -      </Constraints>
   95.42 -
   95.43 -      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
   95.44 -      <SubComponents>
   95.45 -        <Container class="javax.swing.JPanel" name="panel1">
   95.46 -          <Properties>
   95.47 -            <Property name="opaque" type="boolean" value="false"/>
   95.48 -          </Properties>
   95.49 -
   95.50 -          <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
   95.51 -          <SubComponents>
   95.52 -            <Component class="javax.swing.JLabel" name="extendsImplemetsKeywordLabel">
   95.53 -              <Properties>
   95.54 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
   95.55 -                  <ComponentRef name="extendsImplementsKeywordCombo"/>
   95.56 -                </Property>
   95.57 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   95.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;)"/>
   95.59 -                </Property>
   95.60 -              </Properties>
   95.61 -              <Constraints>
   95.62 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
   95.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"/>
   95.64 -                </Constraint>
   95.65 -              </Constraints>
   95.66 -            </Component>
   95.67 -            <Component class="javax.swing.JComboBox" name="extendsImplementsKeywordCombo">
   95.68 -              <Properties>
   95.69 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
   95.70 -                  <StringArray count="4">
   95.71 -                    <StringItem index="0" value="Item 1"/>
   95.72 -                    <StringItem index="1" value="Item 2"/>
   95.73 -                    <StringItem index="2" value="Item 3"/>
   95.74 -                    <StringItem index="3" value="Item 4"/>
   95.75 -                  </StringArray>
   95.76 -                </Property>
   95.77 -              </Properties>
   95.78 -              <Constraints>
   95.79 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
   95.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"/>
   95.81 -                </Constraint>
   95.82 -              </Constraints>
   95.83 -            </Component>
   95.84 -            <Component class="javax.swing.JLabel" name="extendsImplementsListLabel">
   95.85 -              <Properties>
   95.86 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
   95.87 -                  <ComponentRef name="extendsImplementsListCombo"/>
   95.88 -                </Property>
   95.89 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   95.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;)"/>
   95.91 -                </Property>
   95.92 -              </Properties>
   95.93 -              <Constraints>
   95.94 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
   95.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"/>
   95.96 -                </Constraint>
   95.97 -              </Constraints>
   95.98 -            </Component>
   95.99 -            <Component class="javax.swing.JComboBox" name="extendsImplementsListCombo">
  95.100 -              <Properties>
  95.101 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.102 -                  <StringArray count="4">
  95.103 -                    <StringItem index="0" value="Item 1"/>
  95.104 -                    <StringItem index="1" value="Item 2"/>
  95.105 -                    <StringItem index="2" value="Item 3"/>
  95.106 -                    <StringItem index="3" value="Item 4"/>
  95.107 -                  </StringArray>
  95.108 -                </Property>
  95.109 -              </Properties>
  95.110 -              <Constraints>
  95.111 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.113 -                </Constraint>
  95.114 -              </Constraints>
  95.115 -            </Component>
  95.116 -            <Component class="javax.swing.JLabel" name="methodParamsLabel">
  95.117 -              <Properties>
  95.118 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.119 -                  <ComponentRef name="methodParamsCombo"/>
  95.120 -                </Property>
  95.121 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.123 -                </Property>
  95.124 -              </Properties>
  95.125 -              <Constraints>
  95.126 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.128 -                </Constraint>
  95.129 -              </Constraints>
  95.130 -            </Component>
  95.131 -            <Component class="javax.swing.JComboBox" name="methodParamsCombo">
  95.132 -              <Properties>
  95.133 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.134 -                  <StringArray count="4">
  95.135 -                    <StringItem index="0" value="Item 1"/>
  95.136 -                    <StringItem index="1" value="Item 2"/>
  95.137 -                    <StringItem index="2" value="Item 3"/>
  95.138 -                    <StringItem index="3" value="Item 4"/>
  95.139 -                  </StringArray>
  95.140 -                </Property>
  95.141 -              </Properties>
  95.142 -              <Constraints>
  95.143 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.145 -                </Constraint>
  95.146 -              </Constraints>
  95.147 -            </Component>
  95.148 -            <Component class="javax.swing.JLabel" name="methodCallArgsLabel">
  95.149 -              <Properties>
  95.150 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.151 -                  <ComponentRef name="methodCallArgsCombo"/>
  95.152 -                </Property>
  95.153 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.155 -                </Property>
  95.156 -              </Properties>
  95.157 -              <Constraints>
  95.158 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.160 -                </Constraint>
  95.161 -              </Constraints>
  95.162 -            </Component>
  95.163 -            <Component class="javax.swing.JComboBox" name="methodCallArgsCombo">
  95.164 -              <Properties>
  95.165 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.166 -                  <StringArray count="4">
  95.167 -                    <StringItem index="0" value="Item 1"/>
  95.168 -                    <StringItem index="1" value="Item 2"/>
  95.169 -                    <StringItem index="2" value="Item 3"/>
  95.170 -                    <StringItem index="3" value="Item 4"/>
  95.171 -                  </StringArray>
  95.172 -                </Property>
  95.173 -              </Properties>
  95.174 -              <Constraints>
  95.175 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.177 -                </Constraint>
  95.178 -              </Constraints>
  95.179 -            </Component>
  95.180 -            <Component class="javax.swing.JLabel" name="annotationArgsLabel">
  95.181 -              <Properties>
  95.182 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.183 -                  <ComponentRef name="annotationArgsCombo"/>
  95.184 -                </Property>
  95.185 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.187 -                </Property>
  95.188 -              </Properties>
  95.189 -              <Constraints>
  95.190 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.192 -                </Constraint>
  95.193 -              </Constraints>
  95.194 -            </Component>
  95.195 -            <Component class="javax.swing.JComboBox" name="annotationArgsCombo">
  95.196 -              <Properties>
  95.197 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.198 -                  <StringArray count="4">
  95.199 -                    <StringItem index="0" value="Item 1"/>
  95.200 -                    <StringItem index="1" value="Item 2"/>
  95.201 -                    <StringItem index="2" value="Item 3"/>
  95.202 -                    <StringItem index="3" value="Item 4"/>
  95.203 -                  </StringArray>
  95.204 -                </Property>
  95.205 -              </Properties>
  95.206 -              <Constraints>
  95.207 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.209 -                </Constraint>
  95.210 -              </Constraints>
  95.211 -            </Component>
  95.212 -            <Component class="javax.swing.JLabel" name="chainedMethodCallsLabel">
  95.213 -              <Properties>
  95.214 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.215 -                  <ComponentRef name="chainedMethodCallsCombo"/>
  95.216 -                </Property>
  95.217 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.219 -                </Property>
  95.220 -              </Properties>
  95.221 -              <Constraints>
  95.222 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.224 -                </Constraint>
  95.225 -              </Constraints>
  95.226 -            </Component>
  95.227 -            <Component class="javax.swing.JComboBox" name="chainedMethodCallsCombo">
  95.228 -              <Properties>
  95.229 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.230 -                  <StringArray count="4">
  95.231 -                    <StringItem index="0" value="Item 1"/>
  95.232 -                    <StringItem index="1" value="Item 2"/>
  95.233 -                    <StringItem index="2" value="Item 3"/>
  95.234 -                    <StringItem index="3" value="Item 4"/>
  95.235 -                  </StringArray>
  95.236 -                </Property>
  95.237 -              </Properties>
  95.238 -              <Constraints>
  95.239 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.241 -                </Constraint>
  95.242 -              </Constraints>
  95.243 -            </Component>
  95.244 -            <Component class="javax.swing.JLabel" name="throwsKeywordLabel">
  95.245 -              <Properties>
  95.246 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.247 -                  <ComponentRef name="throwsKeywordCombo"/>
  95.248 -                </Property>
  95.249 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.251 -                </Property>
  95.252 -              </Properties>
  95.253 -              <Constraints>
  95.254 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.256 -                </Constraint>
  95.257 -              </Constraints>
  95.258 -            </Component>
  95.259 -            <Component class="javax.swing.JComboBox" name="throwsKeywordCombo">
  95.260 -              <Properties>
  95.261 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.262 -                  <StringArray count="4">
  95.263 -                    <StringItem index="0" value="Item 1"/>
  95.264 -                    <StringItem index="1" value="Item 2"/>
  95.265 -                    <StringItem index="2" value="Item 3"/>
  95.266 -                    <StringItem index="3" value="Item 4"/>
  95.267 -                  </StringArray>
  95.268 -                </Property>
  95.269 -              </Properties>
  95.270 -              <Constraints>
  95.271 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.273 -                </Constraint>
  95.274 -              </Constraints>
  95.275 -            </Component>
  95.276 -            <Component class="javax.swing.JLabel" name="throwsListLabel">
  95.277 -              <Properties>
  95.278 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.279 -                  <ComponentRef name="throwsListCombo"/>
  95.280 -                </Property>
  95.281 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.283 -                </Property>
  95.284 -              </Properties>
  95.285 -              <Constraints>
  95.286 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.288 -                </Constraint>
  95.289 -              </Constraints>
  95.290 -            </Component>
  95.291 -            <Component class="javax.swing.JComboBox" name="throwsListCombo">
  95.292 -              <Properties>
  95.293 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.294 -                  <StringArray count="4">
  95.295 -                    <StringItem index="0" value="Item 1"/>
  95.296 -                    <StringItem index="1" value="Item 2"/>
  95.297 -                    <StringItem index="2" value="Item 3"/>
  95.298 -                    <StringItem index="3" value="Item 4"/>
  95.299 -                  </StringArray>
  95.300 -                </Property>
  95.301 -              </Properties>
  95.302 -              <Constraints>
  95.303 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.305 -                </Constraint>
  95.306 -              </Constraints>
  95.307 -            </Component>
  95.308 -            <Component class="javax.swing.JLabel" name="arrayInitLabel">
  95.309 -              <Properties>
  95.310 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.311 -                  <ComponentRef name="arrayInitCombo"/>
  95.312 -                </Property>
  95.313 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.315 -                </Property>
  95.316 -              </Properties>
  95.317 -              <Constraints>
  95.318 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.320 -                </Constraint>
  95.321 -              </Constraints>
  95.322 -            </Component>
  95.323 -            <Component class="javax.swing.JComboBox" name="arrayInitCombo">
  95.324 -              <Properties>
  95.325 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.326 -                  <StringArray count="4">
  95.327 -                    <StringItem index="0" value="Item 1"/>
  95.328 -                    <StringItem index="1" value="Item 2"/>
  95.329 -                    <StringItem index="2" value="Item 3"/>
  95.330 -                    <StringItem index="3" value="Item 4"/>
  95.331 -                  </StringArray>
  95.332 -                </Property>
  95.333 -              </Properties>
  95.334 -              <Constraints>
  95.335 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.337 -                </Constraint>
  95.338 -              </Constraints>
  95.339 -            </Component>
  95.340 -            <Component class="javax.swing.JLabel" name="forLabel">
  95.341 -              <Properties>
  95.342 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.343 -                  <ComponentRef name="forCombo"/>
  95.344 -                </Property>
  95.345 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.347 -                </Property>
  95.348 -              </Properties>
  95.349 -              <Constraints>
  95.350 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.352 -                </Constraint>
  95.353 -              </Constraints>
  95.354 -            </Component>
  95.355 -            <Component class="javax.swing.JComboBox" name="forCombo">
  95.356 -              <Properties>
  95.357 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.358 -                  <StringArray count="4">
  95.359 -                    <StringItem index="0" value="Item 1"/>
  95.360 -                    <StringItem index="1" value="Item 2"/>
  95.361 -                    <StringItem index="2" value="Item 3"/>
  95.362 -                    <StringItem index="3" value="Item 4"/>
  95.363 -                  </StringArray>
  95.364 -                </Property>
  95.365 -              </Properties>
  95.366 -              <Constraints>
  95.367 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.369 -                </Constraint>
  95.370 -              </Constraints>
  95.371 -            </Component>
  95.372 -            <Component class="javax.swing.JLabel" name="forStatementLabel">
  95.373 -              <Properties>
  95.374 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.375 -                  <ComponentRef name="forStatementCombo"/>
  95.376 -                </Property>
  95.377 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.379 -                </Property>
  95.380 -              </Properties>
  95.381 -              <Constraints>
  95.382 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.384 -                </Constraint>
  95.385 -              </Constraints>
  95.386 -            </Component>
  95.387 -            <Component class="javax.swing.JComboBox" name="forStatementCombo">
  95.388 -              <Properties>
  95.389 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.390 -                  <StringArray count="4">
  95.391 -                    <StringItem index="0" value="Item 1"/>
  95.392 -                    <StringItem index="1" value="Item 2"/>
  95.393 -                    <StringItem index="2" value="Item 3"/>
  95.394 -                    <StringItem index="3" value="Item 4"/>
  95.395 -                  </StringArray>
  95.396 -                </Property>
  95.397 -              </Properties>
  95.398 -              <Constraints>
  95.399 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.401 -                </Constraint>
  95.402 -              </Constraints>
  95.403 -            </Component>
  95.404 -            <Component class="javax.swing.JLabel" name="ifStatementLabel">
  95.405 -              <Properties>
  95.406 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.407 -                  <ComponentRef name="ifStatementCombo"/>
  95.408 -                </Property>
  95.409 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.411 -                </Property>
  95.412 -              </Properties>
  95.413 -              <Constraints>
  95.414 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.416 -                </Constraint>
  95.417 -              </Constraints>
  95.418 -            </Component>
  95.419 -            <Component class="javax.swing.JComboBox" name="ifStatementCombo">
  95.420 -              <Properties>
  95.421 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.422 -                  <StringArray count="4">
  95.423 -                    <StringItem index="0" value="Item 1"/>
  95.424 -                    <StringItem index="1" value="Item 2"/>
  95.425 -                    <StringItem index="2" value="Item 3"/>
  95.426 -                    <StringItem index="3" value="Item 4"/>
  95.427 -                  </StringArray>
  95.428 -                </Property>
  95.429 -              </Properties>
  95.430 -              <Constraints>
  95.431 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.433 -                </Constraint>
  95.434 -              </Constraints>
  95.435 -            </Component>
  95.436 -            <Component class="javax.swing.JLabel" name="whileStatementLabel">
  95.437 -              <Properties>
  95.438 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.439 -                  <ComponentRef name="whileStatementComboBox"/>
  95.440 -                </Property>
  95.441 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.443 -                </Property>
  95.444 -              </Properties>
  95.445 -              <Constraints>
  95.446 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.448 -                </Constraint>
  95.449 -              </Constraints>
  95.450 -            </Component>
  95.451 -            <Component class="javax.swing.JComboBox" name="whileStatementComboBox">
  95.452 -              <Properties>
  95.453 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.454 -                  <StringArray count="4">
  95.455 -                    <StringItem index="0" value="Item 1"/>
  95.456 -                    <StringItem index="1" value="Item 2"/>
  95.457 -                    <StringItem index="2" value="Item 3"/>
  95.458 -                    <StringItem index="3" value="Item 4"/>
  95.459 -                  </StringArray>
  95.460 -                </Property>
  95.461 -              </Properties>
  95.462 -              <Constraints>
  95.463 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.465 -                </Constraint>
  95.466 -              </Constraints>
  95.467 -            </Component>
  95.468 -            <Component class="javax.swing.JLabel" name="doWhileStatementLabel">
  95.469 -              <Properties>
  95.470 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.471 -                  <ComponentRef name="doWhileStatementCombo"/>
  95.472 -                </Property>
  95.473 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.475 -                </Property>
  95.476 -              </Properties>
  95.477 -              <Constraints>
  95.478 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.480 -                </Constraint>
  95.481 -              </Constraints>
  95.482 -            </Component>
  95.483 -            <Component class="javax.swing.JComboBox" name="doWhileStatementCombo">
  95.484 -              <Properties>
  95.485 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.486 -                  <StringArray count="4">
  95.487 -                    <StringItem index="0" value="Item 1"/>
  95.488 -                    <StringItem index="1" value="Item 2"/>
  95.489 -                    <StringItem index="2" value="Item 3"/>
  95.490 -                    <StringItem index="3" value="Item 4"/>
  95.491 -                  </StringArray>
  95.492 -                </Property>
  95.493 -              </Properties>
  95.494 -              <Constraints>
  95.495 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.497 -                </Constraint>
  95.498 -              </Constraints>
  95.499 -            </Component>
  95.500 -            <Component class="javax.swing.JLabel" name="assertLabel">
  95.501 -              <Properties>
  95.502 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.503 -                  <ComponentRef name="assertCombo"/>
  95.504 -                </Property>
  95.505 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.507 -                </Property>
  95.508 -              </Properties>
  95.509 -              <Constraints>
  95.510 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.512 -                </Constraint>
  95.513 -              </Constraints>
  95.514 -            </Component>
  95.515 -            <Component class="javax.swing.JComboBox" name="assertCombo">
  95.516 -              <Properties>
  95.517 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.518 -                  <StringArray count="4">
  95.519 -                    <StringItem index="0" value="Item 1"/>
  95.520 -                    <StringItem index="1" value="Item 2"/>
  95.521 -                    <StringItem index="2" value="Item 3"/>
  95.522 -                    <StringItem index="3" value="Item 4"/>
  95.523 -                  </StringArray>
  95.524 -                </Property>
  95.525 -              </Properties>
  95.526 -              <Constraints>
  95.527 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.529 -                </Constraint>
  95.530 -              </Constraints>
  95.531 -            </Component>
  95.532 -            <Component class="javax.swing.JLabel" name="enumConstantsLabel">
  95.533 -              <Properties>
  95.534 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.535 -                  <ComponentRef name="enumConstantsCombo"/>
  95.536 -                </Property>
  95.537 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.539 -                </Property>
  95.540 -              </Properties>
  95.541 -              <Constraints>
  95.542 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.544 -                </Constraint>
  95.545 -              </Constraints>
  95.546 -            </Component>
  95.547 -            <Component class="javax.swing.JComboBox" name="enumConstantsCombo">
  95.548 -              <Properties>
  95.549 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.550 -                  <StringArray count="4">
  95.551 -                    <StringItem index="0" value="Item 1"/>
  95.552 -                    <StringItem index="1" value="Item 2"/>
  95.553 -                    <StringItem index="2" value="Item 3"/>
  95.554 -                    <StringItem index="3" value="Item 4"/>
  95.555 -                  </StringArray>
  95.556 -                </Property>
  95.557 -              </Properties>
  95.558 -              <Constraints>
  95.559 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.561 -                </Constraint>
  95.562 -              </Constraints>
  95.563 -            </Component>
  95.564 -            <Component class="javax.swing.JLabel" name="annotationsLabel">
  95.565 -              <Properties>
  95.566 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.567 -                  <ComponentRef name="annotationsCombo"/>
  95.568 -                </Property>
  95.569 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.571 -                </Property>
  95.572 -              </Properties>
  95.573 -              <Constraints>
  95.574 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.576 -                </Constraint>
  95.577 -              </Constraints>
  95.578 -            </Component>
  95.579 -            <Component class="javax.swing.JComboBox" name="annotationsCombo">
  95.580 -              <Properties>
  95.581 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.582 -                  <StringArray count="4">
  95.583 -                    <StringItem index="0" value="Item 1"/>
  95.584 -                    <StringItem index="1" value="Item 2"/>
  95.585 -                    <StringItem index="2" value="Item 3"/>
  95.586 -                    <StringItem index="3" value="Item 4"/>
  95.587 -                  </StringArray>
  95.588 -                </Property>
  95.589 -              </Properties>
  95.590 -              <Constraints>
  95.591 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.593 -                </Constraint>
  95.594 -              </Constraints>
  95.595 -            </Component>
  95.596 -            <Component class="javax.swing.JLabel" name="binaryOpsLabel">
  95.597 -              <Properties>
  95.598 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.599 -                  <ComponentRef name="binaryOpsCombo"/>
  95.600 -                </Property>
  95.601 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.603 -                </Property>
  95.604 -              </Properties>
  95.605 -              <Constraints>
  95.606 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.608 -                </Constraint>
  95.609 -              </Constraints>
  95.610 -            </Component>
  95.611 -            <Component class="javax.swing.JComboBox" name="binaryOpsCombo">
  95.612 -              <Properties>
  95.613 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.614 -                  <StringArray count="4">
  95.615 -                    <StringItem index="0" value="Item 1"/>
  95.616 -                    <StringItem index="1" value="Item 2"/>
  95.617 -                    <StringItem index="2" value="Item 3"/>
  95.618 -                    <StringItem index="3" value="Item 4"/>
  95.619 -                  </StringArray>
  95.620 -                </Property>
  95.621 -              </Properties>
  95.622 -              <Constraints>
  95.623 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.625 -                </Constraint>
  95.626 -              </Constraints>
  95.627 -            </Component>
  95.628 -            <Component class="javax.swing.JLabel" name="ternaryOpsLabel">
  95.629 -              <Properties>
  95.630 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.631 -                  <ComponentRef name="ternaryOpsCombo"/>
  95.632 -                </Property>
  95.633 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.635 -                </Property>
  95.636 -              </Properties>
  95.637 -              <Constraints>
  95.638 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.640 -                </Constraint>
  95.641 -              </Constraints>
  95.642 -            </Component>
  95.643 -            <Component class="javax.swing.JComboBox" name="ternaryOpsCombo">
  95.644 -              <Properties>
  95.645 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.646 -                  <StringArray count="4">
  95.647 -                    <StringItem index="0" value="Item 1"/>
  95.648 -                    <StringItem index="1" value="Item 2"/>
  95.649 -                    <StringItem index="2" value="Item 3"/>
  95.650 -                    <StringItem index="3" value="Item 4"/>
  95.651 -                  </StringArray>
  95.652 -                </Property>
  95.653 -              </Properties>
  95.654 -              <Constraints>
  95.655 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.657 -                </Constraint>
  95.658 -              </Constraints>
  95.659 -            </Component>
  95.660 -            <Component class="javax.swing.JLabel" name="assignOpsLabel">
  95.661 -              <Properties>
  95.662 -                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  95.663 -                  <ComponentRef name="assignOpsCombo"/>
  95.664 -                </Property>
  95.665 -                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  95.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;)"/>
  95.667 -                </Property>
  95.668 -              </Properties>
  95.669 -              <Constraints>
  95.670 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.672 -                </Constraint>
  95.673 -              </Constraints>
  95.674 -            </Component>
  95.675 -            <Component class="javax.swing.JComboBox" name="assignOpsCombo">
  95.676 -              <Properties>
  95.677 -                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  95.678 -                  <StringArray count="4">
  95.679 -                    <StringItem index="0" value="Item 1"/>
  95.680 -                    <StringItem index="1" value="Item 2"/>
  95.681 -                    <StringItem index="2" value="Item 3"/>
  95.682 -                    <StringItem index="3" value="Item 4"/>
  95.683 -                  </StringArray>
  95.684 -                </Property>
  95.685 -              </Properties>
  95.686 -              <Constraints>
  95.687 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.689 -                </Constraint>
  95.690 -              </Constraints>
  95.691 -            </Component>
  95.692 -            <Container class="javax.swing.JPanel" name="spacerPanel1">
  95.693 -              <Properties>
  95.694 -                <Property name="opaque" type="boolean" value="false"/>
  95.695 -              </Properties>
  95.696 -              <Constraints>
  95.697 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  95.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"/>
  95.699 -                </Constraint>
  95.700 -              </Constraints>
  95.701 -
  95.702 -              <Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
  95.703 -            </Container>
  95.704 -          </SubComponents>
  95.705 -        </Container>
  95.706 -      </SubComponents>
  95.707 -    </Container>
  95.708 -  </SubComponents>
  95.709 -</Form>
    96.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/FmtWrapping.java	Fri Sep 18 16:20:24 2015 -0500
    96.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.3 @@ -1,505 +0,0 @@
    96.4 -/*
    96.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    96.6 - *
    96.7 - * Copyright 1997-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 - * Contributor(s):
   96.31 - *
   96.32 - * The Original Software is NetBeans. The Initial Developer of the Original
   96.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
   96.34 - * Microsystems, Inc. All Rights Reserved.
   96.35 - *
   96.36 - * If you wish your version of this file to be governed by only the CDDL
   96.37 - * or only the GPL Version 2, indicate your decision by adding
   96.38 - * "[Contributor] elects to include this software in this distribution
   96.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   96.40 - * single choice of license, a recipient has the option to distribute
   96.41 - * your version of this file under either the CDDL, the GPL Version 2 or
   96.42 - * to extend the choice of license to its licensees as provided above.
   96.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   96.44 - * Version 2 license, then the option applies only if the new code is
   96.45 - * made subject to such option by the copyright holder.
   96.46 - */
   96.47 -
   96.48 -package org.netbeans.modules.python.editor.options;
   96.49 -
   96.50 -import org.netbeans.modules.python.editor.options.CodeStyle;
   96.51 -import static org.netbeans.modules.python.editor.options.FmtOptions.*;
   96.52 -import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
   96.53 -import org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport;
   96.54 -import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
   96.55 -
   96.56 -
   96.57 -/**
   96.58 - *
   96.59 - * @author  phrebejk
   96.60 - */
   96.61 -public class FmtWrapping extends javax.swing.JPanel {
   96.62 -    
   96.63 -    /** Creates new form FmtWrapping */
   96.64 -    public FmtWrapping() {
   96.65 -        initComponents();
   96.66 -        
   96.67 -        scrollPane.getViewport().setBackground(java.awt.SystemColor.controlLtHighlight);
   96.68 -        
   96.69 -/*
   96.70 -        extendsImplementsKeywordCombo.putClientProperty(OPTION_ID, wrapExtendsImplementsKeyword);
   96.71 -        extendsImplementsListCombo.putClientProperty(OPTION_ID, wrapExtendsImplementsList);
   96.72 -        methodParamsCombo.putClientProperty(OPTION_ID, wrapMethodParams);
   96.73 -        methodCallArgsCombo.putClientProperty(OPTION_ID, wrapMethodCallArgs);
   96.74 -        annotationArgsCombo.putClientProperty(OPTION_ID, wrapAnnotationArgs);
   96.75 -        chainedMethodCallsCombo.putClientProperty(OPTION_ID, wrapChainedMethodCalls);
   96.76 -        throwsKeywordCombo.putClientProperty(OPTION_ID, wrapThrowsKeyword);
   96.77 -        throwsListCombo.putClientProperty(OPTION_ID, wrapThrowsList);
   96.78 -        arrayInitCombo.putClientProperty(OPTION_ID, wrapArrayInit);
   96.79 -        forCombo.putClientProperty(OPTION_ID, wrapFor);
   96.80 -        forStatementCombo.putClientProperty(OPTION_ID, wrapForStatement );
   96.81 -        ifStatementCombo.putClientProperty(OPTION_ID, wrapIfStatement);
   96.82 -        whileStatementComboBox.putClientProperty(OPTION_ID, wrapWhileStatement);
   96.83 -        doWhileStatementCombo.putClientProperty(OPTION_ID, wrapDoWhileStatement);
   96.84 -        assertCombo.putClientProperty(OPTION_ID, wrapAssert);
   96.85 -        enumConstantsCombo.putClientProperty(OPTION_ID, wrapEnumConstants);
   96.86 -        annotationsCombo.putClientProperty(OPTION_ID, wrapAnnotations);
   96.87 -        binaryOpsCombo.putClientProperty(OPTION_ID, wrapBinaryOps);
   96.88 -        ternaryOpsCombo.putClientProperty(OPTION_ID, wrapTernaryOps);
   96.89 -        assignOpsCombo.putClientProperty(OPTION_ID, wrapAssignOps);
   96.90 -    }
   96.91 -    
   96.92 -    public static PreferencesCustomizer.Factory getController() {
   96.93 -        return new CategorySupport.Factory("wrapping", FmtWrapping.class, //NOI18N
   96.94 -                org.openide.util.NbBundle.getMessage(FmtWrapping.class, "SAMPLE_Wrapping"), //NOI18N
   96.95 -                new String[] { FmtOptions.rightMargin, "30" } //NOI18N
   96.96 -//                new String[] { FmtOptions.redundantDoWhileBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() },
   96.97 -//                new String[] { FmtOptions.redundantForBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() },
   96.98 -//                new String[] { FmtOptions.redundantIfBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() },
   96.99 -//                new String[] { FmtOptions.redundantWhileBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() }
  96.100 -        ); // NOI18N
  96.101 - */
  96.102 -    }
  96.103 -    
  96.104 -    /** This method is called from within the constructor to
  96.105 -     * initialize the form.
  96.106 -     * WARNING: Do NOT modify this code. The content of this method is
  96.107 -     * always regenerated by the Form Editor.
  96.108 -     */
  96.109 -    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  96.110 -    private void initComponents() {
  96.111 -        java.awt.GridBagConstraints gridBagConstraints;
  96.112 -
  96.113 -        scrollPane = new javax.swing.JScrollPane();
  96.114 -        panel1 = new javax.swing.JPanel();
  96.115 -        extendsImplemetsKeywordLabel = new javax.swing.JLabel();
  96.116 -        extendsImplementsKeywordCombo = new javax.swing.JComboBox();
  96.117 -        extendsImplementsListLabel = new javax.swing.JLabel();
  96.118 -        extendsImplementsListCombo = new javax.swing.JComboBox();
  96.119 -        methodParamsLabel = new javax.swing.JLabel();
  96.120 -        methodParamsCombo = new javax.swing.JComboBox();
  96.121 -        methodCallArgsLabel = new javax.swing.JLabel();
  96.122 -        methodCallArgsCombo = new javax.swing.JComboBox();
  96.123 -        annotationArgsLabel = new javax.swing.JLabel();
  96.124 -        annotationArgsCombo = new javax.swing.JComboBox();
  96.125 -        chainedMethodCallsLabel = new javax.swing.JLabel();
  96.126 -        chainedMethodCallsCombo = new javax.swing.JComboBox();
  96.127 -        throwsKeywordLabel = new javax.swing.JLabel();
  96.128 -        throwsKeywordCombo = new javax.swing.JComboBox();
  96.129 -        throwsListLabel = new javax.swing.JLabel();
  96.130 -        throwsListCombo = new javax.swing.JComboBox();
  96.131 -        arrayInitLabel = new javax.swing.JLabel();
  96.132 -        arrayInitCombo = new javax.swing.JComboBox();
  96.133 -        forLabel = new javax.swing.JLabel();
  96.134 -        forCombo = new javax.swing.JComboBox();
  96.135 -        forStatementLabel = new javax.swing.JLabel();
  96.136 -        forStatementCombo = new javax.swing.JComboBox();
  96.137 -        ifStatementLabel = new javax.swing.JLabel();
  96.138 -        ifStatementCombo = new javax.swing.JComboBox();
  96.139 -        whileStatementLabel = new javax.swing.JLabel();
  96.140 -        whileStatementComboBox = new javax.swing.JComboBox();
  96.141 -        doWhileStatementLabel = new javax.swing.JLabel();
  96.142 -        doWhileStatementCombo = new javax.swing.JComboBox();
  96.143 -        assertLabel = new javax.swing.JLabel();
  96.144 -        assertCombo = new javax.swing.JComboBox();
  96.145 -        enumConstantsLabel = new javax.swing.JLabel();
  96.146 -        enumConstantsCombo = new javax.swing.JComboBox();
  96.147 -        annotationsLabel = new javax.swing.JLabel();
  96.148 -        annotationsCombo = new javax.swing.JComboBox();
  96.149 -        binaryOpsLabel = new javax.swing.JLabel();
  96.150 -        binaryOpsCombo = new javax.swing.JComboBox();
  96.151 -        ternaryOpsLabel = new javax.swing.JLabel();
  96.152 -        ternaryOpsCombo = new javax.swing.JComboBox();
  96.153 -        assignOpsLabel = new javax.swing.JLabel();
  96.154 -        assignOpsCombo = new javax.swing.JComboBox();
  96.155 -        spacerPanel1 = new javax.swing.JPanel();
  96.156 -
  96.157 -        setName(org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_Wrapping")); // NOI18N
  96.158 -        setOpaque(false);
  96.159 -        setLayout(new java.awt.BorderLayout());
  96.160 -
  96.161 -        scrollPane.setMinimumSize(new java.awt.Dimension(300, 200));
  96.162 -        scrollPane.setPreferredSize(new java.awt.Dimension(350, 600));
  96.163 -
  96.164 -        panel1.setOpaque(false);
  96.165 -        panel1.setLayout(new java.awt.GridBagLayout());
  96.166 -
  96.167 -        extendsImplemetsKeywordLabel.setLabelFor(extendsImplementsKeywordCombo);
  96.168 -        org.openide.awt.Mnemonics.setLocalizedText(extendsImplemetsKeywordLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_extendsImplementsKeyword")); // NOI18N
  96.169 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.170 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.171 -        gridBagConstraints.insets = new java.awt.Insets(8, 8, 4, 0);
  96.172 -        panel1.add(extendsImplemetsKeywordLabel, gridBagConstraints);
  96.173 -
  96.174 -        extendsImplementsKeywordCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.175 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.176 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.177 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.178 -        gridBagConstraints.weightx = 1.0;
  96.179 -        gridBagConstraints.insets = new java.awt.Insets(8, 6, 4, 8);
  96.180 -        panel1.add(extendsImplementsKeywordCombo, gridBagConstraints);
  96.181 -
  96.182 -        extendsImplementsListLabel.setLabelFor(extendsImplementsListCombo);
  96.183 -        org.openide.awt.Mnemonics.setLocalizedText(extendsImplementsListLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_extendsImplementsList")); // NOI18N
  96.184 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.185 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.186 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.187 -        panel1.add(extendsImplementsListLabel, gridBagConstraints);
  96.188 -
  96.189 -        extendsImplementsListCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.190 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.191 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.192 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.193 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.194 -        panel1.add(extendsImplementsListCombo, gridBagConstraints);
  96.195 -
  96.196 -        methodParamsLabel.setLabelFor(methodParamsCombo);
  96.197 -        org.openide.awt.Mnemonics.setLocalizedText(methodParamsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_methodParameters")); // NOI18N
  96.198 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.199 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.200 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.201 -        panel1.add(methodParamsLabel, gridBagConstraints);
  96.202 -
  96.203 -        methodParamsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.204 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.205 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.206 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.207 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.208 -        panel1.add(methodParamsCombo, gridBagConstraints);
  96.209 -
  96.210 -        methodCallArgsLabel.setLabelFor(methodCallArgsCombo);
  96.211 -        org.openide.awt.Mnemonics.setLocalizedText(methodCallArgsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_methodCallArgs")); // NOI18N
  96.212 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.213 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.214 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.215 -        panel1.add(methodCallArgsLabel, gridBagConstraints);
  96.216 -
  96.217 -        methodCallArgsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.218 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.219 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.220 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.221 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.222 -        panel1.add(methodCallArgsCombo, gridBagConstraints);
  96.223 -
  96.224 -        annotationArgsLabel.setLabelFor(annotationArgsCombo);
  96.225 -        org.openide.awt.Mnemonics.setLocalizedText(annotationArgsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_annotationArgs")); // NOI18N
  96.226 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.227 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.228 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.229 -        panel1.add(annotationArgsLabel, gridBagConstraints);
  96.230 -
  96.231 -        annotationArgsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.232 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.233 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.234 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.235 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.236 -        panel1.add(annotationArgsCombo, gridBagConstraints);
  96.237 -
  96.238 -        chainedMethodCallsLabel.setLabelFor(chainedMethodCallsCombo);
  96.239 -        org.openide.awt.Mnemonics.setLocalizedText(chainedMethodCallsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_chainedMethodCalls")); // NOI18N
  96.240 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.241 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.242 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.243 -        panel1.add(chainedMethodCallsLabel, gridBagConstraints);
  96.244 -
  96.245 -        chainedMethodCallsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.246 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.247 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.248 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.249 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.250 -        panel1.add(chainedMethodCallsCombo, gridBagConstraints);
  96.251 -
  96.252 -        throwsKeywordLabel.setLabelFor(throwsKeywordCombo);
  96.253 -        org.openide.awt.Mnemonics.setLocalizedText(throwsKeywordLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_throwsKeyword")); // NOI18N
  96.254 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.255 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.256 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.257 -        panel1.add(throwsKeywordLabel, gridBagConstraints);
  96.258 -
  96.259 -        throwsKeywordCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.260 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.261 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.262 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.263 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.264 -        panel1.add(throwsKeywordCombo, gridBagConstraints);
  96.265 -
  96.266 -        throwsListLabel.setLabelFor(throwsListCombo);
  96.267 -        org.openide.awt.Mnemonics.setLocalizedText(throwsListLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_throwsList")); // NOI18N
  96.268 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.269 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.270 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.271 -        panel1.add(throwsListLabel, gridBagConstraints);
  96.272 -
  96.273 -        throwsListCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.274 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.275 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.276 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.277 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.278 -        panel1.add(throwsListCombo, gridBagConstraints);
  96.279 -
  96.280 -        arrayInitLabel.setLabelFor(arrayInitCombo);
  96.281 -        org.openide.awt.Mnemonics.setLocalizedText(arrayInitLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_arrayInit")); // NOI18N
  96.282 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.283 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.284 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.285 -        panel1.add(arrayInitLabel, gridBagConstraints);
  96.286 -
  96.287 -        arrayInitCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.288 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.289 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.290 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.291 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.292 -        panel1.add(arrayInitCombo, gridBagConstraints);
  96.293 -
  96.294 -        forLabel.setLabelFor(forCombo);
  96.295 -        org.openide.awt.Mnemonics.setLocalizedText(forLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_for")); // NOI18N
  96.296 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.297 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.298 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.299 -        panel1.add(forLabel, gridBagConstraints);
  96.300 -
  96.301 -        forCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.302 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.303 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.304 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.305 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.306 -        panel1.add(forCombo, gridBagConstraints);
  96.307 -
  96.308 -        forStatementLabel.setLabelFor(forStatementCombo);
  96.309 -        org.openide.awt.Mnemonics.setLocalizedText(forStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_forStatement")); // NOI18N
  96.310 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.311 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.312 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.313 -        panel1.add(forStatementLabel, gridBagConstraints);
  96.314 -
  96.315 -        forStatementCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.316 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.317 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.318 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.319 -        gridBagConstraints.weightx = 1.0;
  96.320 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.321 -        panel1.add(forStatementCombo, gridBagConstraints);
  96.322 -
  96.323 -        ifStatementLabel.setLabelFor(ifStatementCombo);
  96.324 -        org.openide.awt.Mnemonics.setLocalizedText(ifStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_ifStatement")); // NOI18N
  96.325 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.326 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.327 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.328 -        panel1.add(ifStatementLabel, gridBagConstraints);
  96.329 -
  96.330 -        ifStatementCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.331 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.332 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.333 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.334 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.335 -        panel1.add(ifStatementCombo, gridBagConstraints);
  96.336 -
  96.337 -        whileStatementLabel.setLabelFor(whileStatementComboBox);
  96.338 -        org.openide.awt.Mnemonics.setLocalizedText(whileStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_whileStatement")); // NOI18N
  96.339 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.340 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.341 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.342 -        panel1.add(whileStatementLabel, gridBagConstraints);
  96.343 -
  96.344 -        whileStatementComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.345 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.346 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.347 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.348 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.349 -        panel1.add(whileStatementComboBox, gridBagConstraints);
  96.350 -
  96.351 -        doWhileStatementLabel.setLabelFor(doWhileStatementCombo);
  96.352 -        org.openide.awt.Mnemonics.setLocalizedText(doWhileStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_doWhileStatement")); // NOI18N
  96.353 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.354 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.355 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.356 -        panel1.add(doWhileStatementLabel, gridBagConstraints);
  96.357 -
  96.358 -        doWhileStatementCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.359 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.360 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.361 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.362 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.363 -        panel1.add(doWhileStatementCombo, gridBagConstraints);
  96.364 -
  96.365 -        assertLabel.setLabelFor(assertCombo);
  96.366 -        org.openide.awt.Mnemonics.setLocalizedText(assertLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_assert")); // NOI18N
  96.367 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.368 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.369 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.370 -        panel1.add(assertLabel, gridBagConstraints);
  96.371 -
  96.372 -        assertCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.373 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.374 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.375 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.376 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.377 -        panel1.add(assertCombo, gridBagConstraints);
  96.378 -
  96.379 -        enumConstantsLabel.setLabelFor(enumConstantsCombo);
  96.380 -        org.openide.awt.Mnemonics.setLocalizedText(enumConstantsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_enumConstants")); // NOI18N
  96.381 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.382 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.383 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.384 -        panel1.add(enumConstantsLabel, gridBagConstraints);
  96.385 -
  96.386 -        enumConstantsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.387 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.388 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.389 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.390 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.391 -        panel1.add(enumConstantsCombo, gridBagConstraints);
  96.392 -
  96.393 -        annotationsLabel.setLabelFor(annotationsCombo);
  96.394 -        org.openide.awt.Mnemonics.setLocalizedText(annotationsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_annotations")); // NOI18N
  96.395 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.396 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.397 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.398 -        panel1.add(annotationsLabel, gridBagConstraints);
  96.399 -
  96.400 -        annotationsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.401 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.402 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.403 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.404 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.405 -        panel1.add(annotationsCombo, gridBagConstraints);
  96.406 -
  96.407 -        binaryOpsLabel.setLabelFor(binaryOpsCombo);
  96.408 -        org.openide.awt.Mnemonics.setLocalizedText(binaryOpsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_binaryOps")); // NOI18N
  96.409 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.410 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.411 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.412 -        panel1.add(binaryOpsLabel, gridBagConstraints);
  96.413 -
  96.414 -        binaryOpsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.415 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.416 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.417 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.418 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.419 -        panel1.add(binaryOpsCombo, gridBagConstraints);
  96.420 -
  96.421 -        ternaryOpsLabel.setLabelFor(ternaryOpsCombo);
  96.422 -        org.openide.awt.Mnemonics.setLocalizedText(ternaryOpsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_ternaryOps")); // NOI18N
  96.423 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.424 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.425 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.426 -        panel1.add(ternaryOpsLabel, gridBagConstraints);
  96.427 -
  96.428 -        ternaryOpsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.429 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.430 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.431 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.432 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.433 -        panel1.add(ternaryOpsCombo, gridBagConstraints);
  96.434 -
  96.435 -        assignOpsLabel.setLabelFor(assignOpsCombo);
  96.436 -        org.openide.awt.Mnemonics.setLocalizedText(assignOpsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_assignOps")); // NOI18N
  96.437 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.438 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
  96.439 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
  96.440 -        panel1.add(assignOpsLabel, gridBagConstraints);
  96.441 -
  96.442 -        assignOpsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
  96.443 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.444 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.445 -        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
  96.446 -        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
  96.447 -        panel1.add(assignOpsCombo, gridBagConstraints);
  96.448 -
  96.449 -        spacerPanel1.setOpaque(false);
  96.450 -        gridBagConstraints = new java.awt.GridBagConstraints();
  96.451 -        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
  96.452 -        gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER;
  96.453 -        gridBagConstraints.weighty = 1.0;
  96.454 -        gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 8);
  96.455 -        panel1.add(spacerPanel1, gridBagConstraints);
  96.456 -
  96.457 -        scrollPane.setViewportView(panel1);
  96.458 -
  96.459 -        add(scrollPane, java.awt.BorderLayout.CENTER);
  96.460 -    }// </editor-fold>//GEN-END:initComponents
  96.461 -    
  96.462 -    // Variables declaration - do not modify//GEN-BEGIN:variables
  96.463 -    private javax.swing.JComboBox annotationArgsCombo;
  96.464 -    private javax.swing.JLabel annotationArgsLabel;
  96.465 -    private javax.swing.JComboBox annotationsCombo;
  96.466 -    private javax.swing.JLabel annotationsLabel;
  96.467 -    private javax.swing.JComboBox arrayInitCombo;
  96.468 -    private javax.swing.JLabel arrayInitLabel;
  96.469 -    private javax.swing.JComboBox assertCombo;
  96.470 -    private javax.swing.JLabel assertLabel;
  96.471 -    private javax.swing.JComboBox assignOpsCombo;
  96.472 -    private javax.swing.JLabel assignOpsLabel;
  96.473 -    private javax.swing.JComboBox binaryOpsCombo;
  96.474 -    private javax.swing.JLabel binaryOpsLabel;
  96.475 -    private javax.swing.JComboBox chainedMethodCallsCombo;
  96.476 -    private javax.swing.JLabel chainedMethodCallsLabel;
  96.477 -    private javax.swing.JComboBox doWhileStatementCombo;
  96.478 -    private javax.swing.JLabel doWhileStatementLabel;
  96.479 -    private javax.swing.JComboBox enumConstantsCombo;
  96.480 -    private javax.swing.JLabel enumConstantsLabel;
  96.481 -    private javax.swing.JComboBox extendsImplementsKeywordCombo;
  96.482 -    private javax.swing.JComboBox extendsImplementsListCombo;
  96.483 -    private javax.swing.JLabel extendsImplementsListLabel;
  96.484 -    private javax.swing.JLabel extendsImplemetsKeywordLabel;
  96.485 -    private javax.swing.JComboBox forCombo;
  96.486 -    private javax.swing.JLabel forLabel;
  96.487 -    private javax.swing.JComboBox forStatementCombo;
  96.488 -    private javax.swing.JLabel forStatementLabel;
  96.489 -    private javax.swing.JComboBox ifStatementCombo;
  96.490 -    private javax.swing.JLabel ifStatementLabel;
  96.491 -    private javax.swing.JComboBox methodCallArgsCombo;
  96.492 -    private javax.swing.JLabel methodCallArgsLabel;
  96.493 -    private javax.swing.JComboBox methodParamsCombo;
  96.494 -    private javax.swing.JLabel methodParamsLabel;
  96.495 -    private javax.swing.JPanel panel1;
  96.496 -    private javax.swing.JScrollPane scrollPane;
  96.497 -    private javax.swing.JPanel spacerPanel1;
  96.498 -    private javax.swing.JComboBox ternaryOpsCombo;
  96.499 -    private javax.swing.JLabel ternaryOpsLabel;
  96.500 -    private javax.swing.JComboBox throwsKeywordCombo;
  96.501 -    private javax.swing.JLabel throwsKeywordLabel;
  96.502 -    private javax.swing.JComboBox throwsListCombo;
  96.503 -    private javax.swing.JLabel throwsListLabel;
  96.504 -    private javax.swing.JComboBox whileStatementComboBox;
  96.505 -    private javax.swing.JLabel whileStatementLabel;
  96.506 -    // End of variables declaration//GEN-END:variables
  96.507 -    
  96.508 -}
    97.1 --- a/python.editor/src/org/netbeans/modules/python/editor/options/NumericKeyListener.java	Fri Sep 18 16:20:24 2015 -0500
    97.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    97.3 @@ -1,74 +0,0 @@
    97.4 -/*
    97.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    97.6 - *
    97.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    97.8 - *
    97.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   97.10 - * Other names may be trademarks of their respective owners.
   97.11 - *
   97.12 - * The contents of this file are subject to the terms of either the GNU
   97.13 - * General Public License Version 2 only ("GPL") or the Common
   97.14 - * Development and Distribution License("CDDL") (collectively, the
   97.15 - * "License"). You may not use this file except in compliance with the
   97.16 - * License. You can obtain a copy of the License at
   97.17 - * http://www.netbeans.org/cddl-gplv2.html
   97.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   97.19 - * specific language governing permissions and limitations under the
   97.20 - * License.  When distributing the software, include this License Header
   97.21 - * Notice in each file and include the License file at
   97.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   97.23 - * particular file as subject to the "Classpath" exception as provided
   97.24 - * by Oracle in the GPL Version 2 section of the License file that
   97.25 - * accompanied this code. If applicable, add the following below the
   97.26 - * License Header, with the fields enclosed by brackets [] replaced by
   97.27 - * your own identifying information:
   97.28 - * "Portions Copyrighted [year] [name of copyright owner]"
   97.29 - *
   97.30 - * If you wish your version of this file to be governed by only the CDDL
   97.31 - * or only the GPL Version 2, indicate your decision by adding
   97.32 - * "[Contributor] elects to include this software in this distribution
   97.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
   97.34 - * single choice of license, a recipient has the option to distribute
   97.35 - * your version of this file under either the CDDL, the GPL Version 2 or
   97.36 - * to extend the choice of license to its licensees as provided above.
   97.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
   97.38 - * Version 2 license, then the option applies only if the new code is
   97.39 - * made subject to such option by the copyright holder.
   97.40 - *
   97.41 - * Contributor(s):
   97.42 - *
   97.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
   97.44 - */
   97.45 -package org.netbeans.modules.python.editor.options;
   97.46 -
   97.47 -import java.awt.Component;
   97.48 -import java.awt.event.KeyEvent;
   97.49 -import java.awt.event.KeyListener;
   97.50 -
   97.51 -/**
   97.52 - *
   97.53 - * @author tester
   97.54 - */
   97.55 -public class NumericKeyListener implements KeyListener {
   97.56 -    public NumericKeyListener() {
   97.57 -    }
   97.58 -
   97.59 -    @Override
   97.60 -    public void keyPressed(KeyEvent evt) {
   97.61 -    }
   97.62 -
   97.63 -    @Override
   97.64 -    public void keyReleased(KeyEvent evt) {
   97.65 -    }
   97.66 -
   97.67 -    @Override
   97.68 -    public void keyTyped(KeyEvent evt) {
   97.69 -        if (!Character.isDigit(evt.getKeyChar()) && !Character.isISOControl(evt.getKeyChar())) {
   97.70 -            evt.consume();
   97.71 -            Component c = evt.getComponent();
   97.72 -            if (c != null) {
   97.73 -                c.getToolkit().beep();
   97.74 -            }
   97.75 -        }
   97.76 -    }
   97.77 -}
    98.1 --- a/python.editor/src/org/netbeans/modules/python/editor/refactoring/PythonElementCtx.java	Fri Sep 18 16:20:24 2015 -0500
    98.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/refactoring/PythonElementCtx.java	Mon Sep 21 13:01:16 2015 +0200
    98.3 @@ -32,15 +32,15 @@
    98.4  
    98.5  import java.util.Iterator;
    98.6  
    98.7 -import org.netbeans.modules.python.editor.elements.AstElement;
    98.8 -import org.netbeans.modules.python.editor.elements.Element;
    98.9 +import org.netbeans.modules.python.source.elements.AstElement;
   98.10 +import org.netbeans.modules.python.source.elements.Element;
   98.11  import org.netbeans.editor.BaseDocument;
   98.12  import org.netbeans.modules.csl.api.ElementKind;
   98.13  import org.netbeans.modules.csl.spi.GsfUtilities;
   98.14 -import org.netbeans.modules.python.editor.AstPath;
   98.15 -import org.netbeans.modules.python.editor.PythonAstUtils;
   98.16 -import org.netbeans.modules.python.editor.PythonParserResult;
   98.17 -import org.netbeans.modules.python.editor.elements.IndexedElement;
   98.18 +import org.netbeans.modules.python.source.AstPath;
   98.19 +import org.netbeans.modules.python.source.PythonAstUtils;
   98.20 +import org.netbeans.modules.python.source.PythonParserResult;
   98.21 +import org.netbeans.modules.python.source.elements.IndexedElement;
   98.22  import org.openide.filesystems.FileObject;
   98.23  import org.python.antlr.PythonTree;
   98.24  import org.python.antlr.ast.Assign;
    99.1 --- a/python.editor/src/org/netbeans/modules/python/editor/refactoring/PythonRefUtils.java	Fri Sep 18 16:20:24 2015 -0500
    99.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/refactoring/PythonRefUtils.java	Mon Sep 21 13:01:16 2015 +0200
    99.3 @@ -72,10 +72,10 @@
    99.4  import org.netbeans.modules.csl.api.ElementKind;
    99.5  import org.netbeans.modules.parsing.api.Source;
    99.6  import org.netbeans.modules.python.api.PythonMIMEResolver;
    99.7 -import org.netbeans.modules.python.editor.PythonAstUtils;
    99.8 -import org.netbeans.modules.python.editor.PythonParserResult;
    99.9 -import org.netbeans.modules.python.editor.PythonUtils;
   99.10 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
   99.11 +import org.netbeans.modules.python.source.PythonAstUtils;
   99.12 +import org.netbeans.modules.python.source.PythonParserResult;
   99.13 +import org.netbeans.modules.python.source.PythonUtils;
   99.14 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
   99.15  import org.openide.cookies.EditorCookie;
   99.16  import org.openide.filesystems.FileObject;
   99.17  import org.openide.util.Lookup;
   100.1 --- a/python.editor/src/org/netbeans/modules/python/editor/refactoring/PythonRefactoringsFactory.java	Fri Sep 18 16:20:24 2015 -0500
   100.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/refactoring/PythonRefactoringsFactory.java	Mon Sep 21 13:01:16 2015 +0200
   100.3 @@ -43,7 +43,7 @@
   100.4   */
   100.5  package org.netbeans.modules.python.editor.refactoring;
   100.6  
   100.7 -import org.netbeans.modules.python.editor.PythonUtils;
   100.8 +import org.netbeans.modules.python.source.PythonUtils;
   100.9  import org.netbeans.modules.refactoring.api.AbstractRefactoring;
  100.10  import org.netbeans.modules.refactoring.api.RenameRefactoring;
  100.11  import org.netbeans.modules.refactoring.api.WhereUsedQuery;
   101.1 --- a/python.editor/src/org/netbeans/modules/python/editor/refactoring/WhereUsedElement.java	Fri Sep 18 16:20:24 2015 -0500
   101.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/refactoring/WhereUsedElement.java	Mon Sep 21 13:01:16 2015 +0200
   101.3 @@ -54,9 +54,9 @@
   101.4  import org.netbeans.modules.csl.api.OffsetRange;
   101.5  import org.netbeans.modules.csl.api.UiUtils;
   101.6  import org.netbeans.modules.csl.spi.GsfUtilities;
   101.7 -import org.netbeans.modules.python.editor.PythonAstUtils;
   101.8 -import org.netbeans.modules.python.editor.PythonParserResult;
   101.9 -import org.netbeans.modules.python.editor.lexer.PythonLexerUtils;
  101.10 +import org.netbeans.modules.python.source.PythonAstUtils;
  101.11 +import org.netbeans.modules.python.source.PythonParserResult;
  101.12 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  101.13  import org.netbeans.modules.python.editor.refactoring.ui.ElementGripFactory;
  101.14  import org.netbeans.modules.refactoring.spi.SimpleRefactoringElementImplementation;
  101.15  import org.openide.filesystems.FileObject;
   102.1 --- a/python.editor/src/org/netbeans/modules/python/editor/refactoring/ui/RefactoringActionsProvider.java	Fri Sep 18 16:20:24 2015 -0500
   102.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/refactoring/ui/RefactoringActionsProvider.java	Mon Sep 21 13:01:16 2015 +0200
   102.3 @@ -64,14 +64,14 @@
   102.4  import org.netbeans.modules.refactoring.spi.ui.UI;
   102.5  import org.netbeans.modules.refactoring.spi.ui.ActionsImplementationProvider;
   102.6  import org.netbeans.modules.refactoring.spi.ui.RefactoringUI;
   102.7 -import org.netbeans.modules.python.editor.PythonAstUtils;
   102.8 -import org.netbeans.modules.python.editor.PythonIndex;
   102.9 -import org.netbeans.modules.python.editor.PythonParserResult;
  102.10 -import org.netbeans.modules.python.editor.PythonStructureScanner;
  102.11 -import org.netbeans.modules.python.editor.PythonStructureScanner.AnalysisResult;
  102.12 -import org.netbeans.modules.python.editor.PythonUtils;
  102.13 -import org.netbeans.modules.python.editor.elements.AstElement;
  102.14 -import org.netbeans.modules.python.editor.elements.Element;
  102.15 +import org.netbeans.modules.python.source.PythonAstUtils;
  102.16 +import org.netbeans.modules.python.source.PythonIndex;
  102.17 +import org.netbeans.modules.python.source.PythonParserResult;
  102.18 +import org.netbeans.modules.python.source.PythonStructureScanner;
  102.19 +import org.netbeans.modules.python.source.PythonStructureScanner.AnalysisResult;
  102.20 +import org.netbeans.modules.python.source.PythonUtils;
  102.21 +import org.netbeans.modules.python.source.elements.AstElement;
  102.22 +import org.netbeans.modules.python.source.elements.Element;
  102.23  import org.openide.ErrorManager;
  102.24  import org.openide.cookies.EditorCookie;
  102.25  import org.openide.filesystems.FileObject;
   103.1 --- a/python.editor/src/org/netbeans/modules/python/editor/scopes/ArgListCompiler.java	Fri Sep 18 16:20:24 2015 -0500
   103.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   103.3 @@ -1,121 +0,0 @@
   103.4 -// Copyright (c) Corporation for National Research Initiatives
   103.5 -package org.netbeans.modules.python.editor.scopes;
   103.6 -
   103.7 -import java.util.ArrayList;
   103.8 -
   103.9 -import java.util.List;
  103.10 -import org.python.antlr.PythonTree;
  103.11 -import org.python.antlr.Visitor;
  103.12 -import org.python.antlr.ast.Assign;
  103.13 -import org.python.antlr.ast.Name;
  103.14 -import org.python.antlr.ast.Suite;
  103.15 -import org.python.antlr.ast.Tuple;
  103.16 -import org.python.antlr.ast.arguments;
  103.17 -import org.python.antlr.ast.expr_contextType;
  103.18 -import org.python.antlr.base.expr;
  103.19 -import org.python.antlr.base.stmt;
  103.20 -
  103.21 -/** Based on org.python.compiler.ArgListCompiler */
  103.22 -public class ArgListCompiler extends Visitor {
  103.23 -    public boolean arglist, keywordlist;
  103.24 -    public List<expr> defaults;
  103.25 -    public List<String> names;
  103.26 -    public ArrayList<PythonTree> nodes;
  103.27 -    public List<String> fpnames;
  103.28 -    public List<stmt> init_code;
  103.29 -    private SymbolTable symbolTable;
  103.30 -
  103.31 -    public ArgListCompiler(SymbolTable symbolTable) {
  103.32 -        this.symbolTable = symbolTable;
  103.33 -        arglist = keywordlist = false;
  103.34 -        defaults = null;
  103.35 -        names = new ArrayList<>();
  103.36 -        nodes = new ArrayList<>();
  103.37 -        fpnames = new ArrayList<>();
  103.38 -        init_code = new ArrayList<>();
  103.39 -    }
  103.40 -
  103.41 -    public void reset() {
  103.42 -        arglist = keywordlist = false;
  103.43 -        defaults = null;
  103.44 -        names.clear();
  103.45 -        nodes.clear();
  103.46 -        init_code.clear();
  103.47 -    }
  103.48 -
  103.49 -    public void appendInitCode(Suite node) {
  103.50 -        node.getInternalBody().addAll(0, init_code);
  103.51 -    }
  103.52 -
  103.53 -    public List<expr> getDefaults() {
  103.54 -        return defaults;
  103.55 -    }
  103.56 -
  103.57 -    public void visitArgs(arguments args) throws Exception {
  103.58 -        for (int i = 0; i < args.getInternalArgs().size(); i++) {
  103.59 -            expr node = args.getInternalArgs().get(i);
  103.60 -            String name = (String)visit(node);
  103.61 -            names.add(name);
  103.62 -            nodes.add(node);
  103.63 -            if (node instanceof Tuple) {
  103.64 -                List<expr> targets = new ArrayList<>();
  103.65 -                targets.add(node);
  103.66 -                Assign ass = new Assign(node,
  103.67 -                        targets,
  103.68 -                        new Name(node, name, expr_contextType.Load));
  103.69 -                init_code.add(ass);
  103.70 -            }
  103.71 -        }
  103.72 -        if (args.getInternalVararg() != null) {
  103.73 -            arglist = true;
  103.74 -            names.add(args.getInternalVararg());
  103.75 -            //nodes.add(null); // no corresponding node?
  103.76 -            nodes.add(args); // just use the corresponding args node instead
  103.77 -        }
  103.78 -        if (args.getInternalKwarg() != null) {
  103.79 -            keywordlist = true;
  103.80 -            names.add(args.getInternalKwarg());
  103.81 -            //nodes.add(null); // no corresponding node?
  103.82 -            nodes.add(args); // just use the corresponding args node instead
  103.83 -        }
  103.84 -
  103.85 -        defaults = args.getInternalDefaults();
  103.86 -        for (int i = 0; i < defaults.size(); i++) {
  103.87 -            if (defaults.get(i) == null) {
  103.88 -                symbolTable.error("non-default argument follows default argument", true,
  103.89 -                        args.getInternalArgs().get(args.getInternalArgs().size() - defaults.size() + i));
  103.90 -            }
  103.91 -        }
  103.92 -    }
  103.93 -
  103.94 -    @Override
  103.95 -    public Object visitName(Name node) throws Exception {
  103.96 -        //FIXME: do we need Store and Param, or just Param?
  103.97 -        if (node.getInternalCtx() != expr_contextType.Store && node.getInternalCtx() != expr_contextType.Param) {
  103.98 -            return null;
  103.99 -        }
 103.100 -
 103.101 -        if (fpnames.contains(node.getInternalId())) {
 103.102 -            symbolTable.error("duplicate argument name found: " +
 103.103 -                    node.getInternalId(), true, node);
 103.104 -        }
 103.105 -        fpnames.add(node.getInternalId());
 103.106 -        return node.getInternalId();
 103.107 -    }
 103.108 -
 103.109 -    @Override
 103.110 -    public Object visitTuple(Tuple node) throws Exception {
 103.111 -        StringBuffer name = new StringBuffer("(");
 103.112 -        List<expr> elts = node.getInternalElts();
 103.113 -        if (elts != null) {
 103.114 -            int n = elts.size();
 103.115 -            for (int i = 0; i < n - 1; i++) {
 103.116 -                name.append(visit(elts.get(i)));
 103.117 -                name.append(", ");
 103.118 -            }
 103.119 -            name.append(visit(elts.get(n - 1)));
 103.120 -        }
 103.121 -        name.append(")");
 103.122 -        return name.toString();
 103.123 -    }
 103.124 -}
   104.1 --- a/python.editor/src/org/netbeans/modules/python/editor/scopes/ScopeConstants.java	Fri Sep 18 16:20:24 2015 -0500
   104.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   104.3 @@ -1,28 +0,0 @@
   104.4 -package org.netbeans.modules.python.editor.scopes;
   104.5 -
   104.6 -/** Based on org.python.compiler.ScopeConstants in Jython */
   104.7 -public interface ScopeConstants {
   104.8 -    public final static int BOUND = 1 << 0;
   104.9 -    public final static int NGLOBAL = 1 << 1; // func scope expl global
  104.10 -    public final static int PARAM = 1 << 2;
  104.11 -    public final static int FROM_PARAM = 1 << 3;
  104.12 -    public final static int CELL = 1 << 4;
  104.13 -    public final static int FREE = 1 << 5;
  104.14 -    public final static int CLASS_GLOBAL = 1 << 6; // class scope expl global
  104.15 -    public final static int READ = 1 << 7;
  104.16 -    public final static int CALLED = 1 << 8;
  104.17 -    public final static int DEF = 1 << 9;
  104.18 -    public final static int IMPORTED = 1 << 10;
  104.19 -    public final static int CLASS = 1 << 11;
  104.20 -    public final static int FUNCTION = 1 << 12;
  104.21 -    public final static int MEMBER = 1 << 13;
  104.22 -    public final static int GENERATOR = 1 << 13; // it's a generator expression
  104.23 -    public final static int PRIVATE = 1 << 14;
  104.24 -    public final static int ALIAS = 1 << 15;
  104.25 -    public final static int PROTECTED = 1 << 16;
  104.26 -    public final static int BOUND_IN_CONSTRUCTOR = 1 << 17;
  104.27 -    public final static int GLOBAL = NGLOBAL | CLASS_GLOBAL; // all global
  104.28 -    public final static int TOPSCOPE = 0;
  104.29 -    public final static int FUNCSCOPE = 1;
  104.30 -    public final static int CLASSSCOPE = 2;
  104.31 -}
   105.1 --- a/python.editor/src/org/netbeans/modules/python/editor/scopes/ScopeInfo.java	Fri Sep 18 16:20:24 2015 -0500
   105.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   105.3 @@ -1,575 +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.Collections;
   105.9 -import java.util.HashMap;
  105.10 -import java.util.LinkedHashMap;
  105.11 -import java.util.Map;
  105.12 -import java.util.List;
  105.13 -
  105.14 -import org.netbeans.modules.python.editor.AstPath;
  105.15 -import org.netbeans.modules.python.editor.PythonAstUtils;
  105.16 -import org.python.antlr.ParseException;
  105.17 -import org.python.antlr.PythonTree;
  105.18 -import org.python.antlr.ast.Assign;
  105.19 -import org.python.antlr.ast.Attribute;
  105.20 -import org.python.antlr.ast.ClassDef;
  105.21 -import org.python.antlr.ast.Name;
  105.22 -import org.python.antlr.ast.Return;
  105.23 -import org.python.antlr.ast.Tuple;
  105.24 -import org.python.antlr.base.expr;
  105.25 -import static org.netbeans.modules.python.editor.scopes.ScopeConstants.*;
  105.26 -
  105.27 -/** 
  105.28 - * Based on org.python.compiler.ScopeInfo in Jython
  105.29 - *
  105.30 - * See {@link ScopesCompiler} for details on my modifications
  105.31 - */
  105.32 -@SuppressWarnings("unchecked")
  105.33 -public class ScopeInfo extends Object {
  105.34 -    public PythonTree scope_node;
  105.35 -    public String scope_name;
  105.36 -    public int level;
  105.37 -    public int func_level;
  105.38 -    public boolean hidden;
  105.39 -
  105.40 -    public String dump() {
  105.41 -        StringBuilder sb = new StringBuilder();
  105.42 -
  105.43 -        for (int i = 0; i < level; i++) {
  105.44 -            sb.append("    ");
  105.45 -        }
  105.46 -        sb.append("=============================================\n");
  105.47 -        for (int i = 0; i < level; i++) {
  105.48 -            sb.append("    ");
  105.49 -        }
  105.50 -        sb.append(((kind != CLASSSCOPE) ? scope_name : "class " +
  105.51 -                scope_name) + ": " + scope_node + " : " + PythonAstUtils.getRange(scope_node) + "\n");
  105.52 -        //for(int i=0; i<level; i++) sb.append("    ");
  105.53 -        //sb.append("UP=" + up);
  105.54 -        //sb.append("   NESTED=" + nested);
  105.55 -        //sb.append("\n");
  105.56 -
  105.57 -
  105.58 -        // Sort to make test output stable
  105.59 -        List<String> keys = new ArrayList<>(tbl.keySet());
  105.60 -        Collections.sort(keys);
  105.61 -        for (String name : keys) {
  105.62 -            SymInfo info = tbl.get(name);
  105.63 -            for (int i = 0; i < level; i++) {
  105.64 -                sb.append("    ");
  105.65 -            }
  105.66 -            sb.append(name);
  105.67 -            sb.append(" ");
  105.68 -            sb.append(info.dumpFlags(this));
  105.69 -            sb.append("\n");
  105.70 -        }
  105.71 -
  105.72 -        if (inner_free.size() > 0 || cellvars.size() > 0 || jy_paramcells.size() > 0 ||
  105.73 -                jy_npurecell != 0 /*|| cell != 0 || distance != 0 || up != null*/) {
  105.74 -            for (int i = 0; i < level; i++) {
  105.75 -                sb.append("    ");
  105.76 -            }
  105.77 -            sb.append("---------------------------------------------\n");
  105.78 -        }
  105.79 -
  105.80 -        if (inner_free.size() > 0) {
  105.81 -            List<String> sorted = new ArrayList<>();
  105.82 -            for (String s : inner_free.keySet()) {
  105.83 -                sorted.add(s + "=" + inner_free.get(s));
  105.84 -            }
  105.85 -            Collections.sort(sorted);
  105.86 -
  105.87 -            for (int i = 0; i < level; i++) {
  105.88 -                sb.append("    ");
  105.89 -            }
  105.90 -            sb.append("inner_free: {"); // NOI18N
  105.91 -            boolean first = true;
  105.92 -            for (String s : sorted) {
  105.93 -                if (first) {
  105.94 -                    first = false;
  105.95 -                } else {
  105.96 -                    sb.append(", "); // NOI18N
  105.97 -                }
  105.98 -                sb.append(s);
  105.99 -            }
 105.100 -            sb.append("}\n"); // NOI18N
 105.101 -        }
 105.102 -        if (cellvars.size() > 0) {
 105.103 -            Collections.sort(cellvars);
 105.104 -            for (int i = 0; i < level; i++) {
 105.105 -                sb.append("    ");
 105.106 -            }
 105.107 -            sb.append("cellvars: " + cellvars.toString() + "\n"); // TODO - sort
 105.108 -        }
 105.109 -        if (jy_paramcells.size() > 0) {
 105.110 -            Collections.sort(jy_paramcells);
 105.111 -            for (int i = 0; i < level; i++) {
 105.112 -                sb.append("    ");
 105.113 -            }
 105.114 -            sb.append("jy_paramcells: " + jy_paramcells.toString() + "\n"); // TODO - sort
 105.115 -        }
 105.116 -        if (jy_npurecell != 0) {
 105.117 -            for (int i = 0; i < level; i++) {
 105.118 -                sb.append("    ");
 105.119 -            }
 105.120 -            sb.append("jy_npurecell: " + jy_npurecell + "\n"); // TODO - sort
 105.121 -        }
 105.122 -        //if (cell != 0) {
 105.123 -        //    for(int i=0; i<level; i++) sb.append("    ");
 105.124 -        //    sb.append("cell: " + cell + "\n"); // TODO - sort
 105.125 -        //}
 105.126 -        //if (distance != 0) {
 105.127 -        //    for(int i=0; i<level; i++) sb.append("    ");
 105.128 -        //    sb.append("distance: " + distance + "\n"); // TODO - sort
 105.129 -        //}
 105.130 -        //if (up != null) {
 105.131 -        //    for(int i=0; i<level; i++) sb.append("    ");
 105.132 -        //    sb.append("up: " + up.scope_node);
 105.133 -        //}
 105.134 -
 105.135 -        if (attributes.size() > 0) {
 105.136 -            for (int i = 0; i < level; i++) {
 105.137 -                sb.append("    ");
 105.138 -            }
 105.139 -            sb.append("------ Attributes ---------------------------------------\n"); // NOI18N
 105.140 -            // Sort
 105.141 -            List<String> attributeNames = new ArrayList<>(attributes.keySet());
 105.142 -            Collections.sort(attributeNames);
 105.143 -            for (String attributeName : attributeNames) {
 105.144 -                for (int i = 0; i < level; i++) {
 105.145 -                    sb.append("    ");
 105.146 -                }
 105.147 -                sb.append(attributeName);
 105.148 -                sb.append(" : "); // NOI18N
 105.149 -                sb.append(attributes.get(attributeName));
 105.150 -                sb.append("\n"); // NOI18N
 105.151 -            }
 105.152 -        }
 105.153 -
 105.154 -        return sb.toString();
 105.155 -    }
 105.156 -
 105.157 -    public ScopeInfo(String name, PythonTree node, int level, int kind,
 105.158 -            int func_level, ArgListCompiler ac) {
 105.159 -        scope_name = name;
 105.160 -        scope_node = node;
 105.161 -        this.level = level;
 105.162 -        this.kind = kind;
 105.163 -        this.func_level = func_level;
 105.164 -        this.ac = ac;
 105.165 -    }
 105.166 -    public int kind;
 105.167 -    public boolean unqual_exec;
 105.168 -    public boolean exec;
 105.169 -    public boolean from_import_star;
 105.170 -    public boolean contains_ns_free_vars;
 105.171 -    public boolean generator;
 105.172 -    private boolean hasReturnWithValue;
 105.173 -    public int yield_count;
 105.174 -    public int max_with_count;
 105.175 -    public ArgListCompiler ac;
 105.176 -    public Map<String, SymInfo> tbl = new LinkedHashMap<>();
 105.177 -
 105.178 -    // define a separate dictionary for dynamic bounded variables
 105.179 -    public Map<String, SymInfo> attributes = new HashMap<>();
 105.180 -    public List<String> names = new ArrayList<>();
 105.181 -
 105.182 -    private void addAttributeEntry(String name, PythonTree node, int flags) {
 105.183 -        SymInfo info = attributes.get(name);
 105.184 -        if (info == null) {
 105.185 -            SymInfo entry = new SymInfo(flags);
 105.186 -            if (SymInfo.isPrivateName(name)) {
 105.187 -                entry.flags |= PRIVATE;
 105.188 -            } else if (SymInfo.isProtectedName(name)) {
 105.189 -                entry.flags |= PROTECTED;
 105.190 -            }
 105.191 -            entry.node = node;
 105.192 -            attributes.put(name, entry);
 105.193 -        }
 105.194 -    }
 105.195 -
 105.196 -    private void addToClassScope(String name, PythonTree node, boolean inConstructor) {
 105.197 -        int flags = CLASSSCOPE | BOUND | MEMBER;
 105.198 -        if (inConstructor) {
 105.199 -            flags |= BOUND_IN_CONSTRUCTOR;
 105.200 -        }
 105.201 -        addAttributeEntry(name, node, flags);
 105.202 -    }
 105.203 -
 105.204 -    public ScopeInfo getClassScope() {
 105.205 -        ScopeInfo cur = this;
 105.206 -        while ((cur != null) &&
 105.207 -                (!(cur.scope_node instanceof ClassDef))) {
 105.208 -            cur = cur.nested;
 105.209 -        }
 105.210 -        return cur;
 105.211 -    }
 105.212 -
 105.213 -    private boolean belongsToExprList(List<expr> types, expr cur) {
 105.214 -        return types != null && types.contains(cur);
 105.215 -    }
 105.216 -
 105.217 -    boolean isAttributeAssigment(AstPath path, Attribute attr) {
 105.218 -        PythonTree leaf = path.leaf();
 105.219 -        Assign assign = null;
 105.220 -        expr target = attr; // default to single
 105.221 -        if (leaf instanceof Assign) {
 105.222 -            assign = (Assign)leaf;
 105.223 -        } else if (leaf instanceof Tuple) {
 105.224 -            // check for tuple assignment
 105.225 -            Tuple tuple = (Tuple)leaf;
 105.226 -            PythonTree tupleParent = path.leafParent();
 105.227 -            if (belongsToExprList(tuple.getInternalElts(), attr)) {
 105.228 -                if (tupleParent instanceof Assign) {
 105.229 -                    assign = (Assign)tupleParent;
 105.230 -                    target = tuple; // tuple assignment target
 105.231 -                }
 105.232 -            }
 105.233 -        }
 105.234 -        // check if we got assignment
 105.235 -        if (assign == null) {
 105.236 -            return false;
 105.237 -        }
 105.238 -        if (belongsToExprList(assign.getInternalTargets(), target)) {
 105.239 -            return true;
 105.240 -        }
 105.241 -        return false;
 105.242 -    }
 105.243 -
 105.244 -    public void addAttribute(AstPath path, String name, PythonTree node) {
 105.245 -        // deeply check assignment context for attribute.
 105.246 -        Attribute curAttr = (Attribute)node;
 105.247 -
 105.248 -        if (curAttr.getInternalValue() instanceof Attribute) {
 105.249 -            // recursice attributes( x.y.z.w ) to be handled later
 105.250 -        } else if (curAttr.getInternalValue() instanceof Name) {
 105.251 -
 105.252 -            Name parentName = (Name)curAttr.getInternalValue();
 105.253 -
 105.254 -            ScopeInfo classScope = getClassScope();
 105.255 -            boolean inConstructor = false;
 105.256 -            String parName = parentName.getInternalId();
 105.257 -
 105.258 -            // for simplicity handle only at classScope in current source
 105.259 -            if (classScope != null) {
 105.260 -                // check for self or inherited parent name prefix
 105.261 -                if ((parName.equals("self")) ||
 105.262 -                        (PythonAstUtils.getParentClassFromNode(path, classScope.scope_node, parName) != null)) {
 105.263 -                    if (!(parName.equals("self"))) {
 105.264 -                        // check classname not overridden by local scope variable
 105.265 -                        if (tbl.get(parName) != null) {
 105.266 -                            return;
 105.267 -                        }
 105.268 -                    }
 105.269 -                    if (scope_name.equals("__init__") || scope_name.equals("__new__")) {
 105.270 -                        inConstructor = true; // set in constructor
 105.271 -                    }
 105.272 -                    //
 105.273 -                    // put in class scope
 105.274 -                    if (isAttributeAssigment(path, curAttr)) {
 105.275 -                        classScope.addToClassScope(name, node, inConstructor);
 105.276 -                    } else {
 105.277 -                        // store at current scope if parName is not overriding
 105.278 -                        // classname at current scope
 105.279 -                        int flags = CLASSSCOPE | READ;
 105.280 -                        addAttributeEntry(name, node, flags);
 105.281 -                    }
 105.282 -                }
 105.283 -            }
 105.284 -        }
 105.285 -    }
 105.286 -
 105.287 -    public int addGlobal(String name, PythonTree node) {
 105.288 -        // global kind = func vs. class
 105.289 -        int global = kind == CLASSSCOPE ? CLASS_GLOBAL : NGLOBAL;
 105.290 -        SymInfo info = tbl.get(name);
 105.291 -        if (info == null) {
 105.292 -            SymInfo entry = new SymInfo(global | BOUND);
 105.293 -            if (SymInfo.isPrivateName(name)) {
 105.294 -                entry.flags |= PRIVATE;
 105.295 -            } else if (SymInfo.isProtectedName(name)) {
 105.296 -                entry.flags |= PROTECTED;
 105.297 -            }
 105.298 -            entry.node = node;
 105.299 -            tbl.put(name, entry);
 105.300 -            return -1;
 105.301 -        }
 105.302 -        int prev = info.flags;
 105.303 -        info.flags |= global | BOUND;
 105.304 -        return prev;
 105.305 -    }
 105.306 -    public int local = 0;
 105.307 -
 105.308 -    public void addParam(String name, PythonTree node) {
 105.309 -        SymInfo entry = new SymInfo(PARAM | BOUND, local++);
 105.310 -        entry.node = node;
 105.311 -        tbl.put(name, entry);
 105.312 -        names.add(name);
 105.313 -    }
 105.314 -
 105.315 -    // <netbeans>
 105.316 -    public boolean isUnused(String name) {
 105.317 -        SymInfo info = tbl.get(name);
 105.318 -        if (info != null) {
 105.319 -            return info.isUnused(this);
 105.320 -        }
 105.321 -        return false;
 105.322 -    }
 105.323 -
 105.324 -    public boolean isParameter(String name) {
 105.325 -        SymInfo info = tbl.get(name);
 105.326 -        if (info != null) {
 105.327 -            return info.isParameter();
 105.328 -        }
 105.329 -        return false;
 105.330 -    }
 105.331 -    // </netbeans>
 105.332 -
 105.333 -    public void markFromParam() {
 105.334 -        for (SymInfo info : tbl.values()) {
 105.335 -            info.flags |= FROM_PARAM;
 105.336 -        }
 105.337 -    }
 105.338 -
 105.339 -    public SymInfo addBound(String name, PythonTree node) {
 105.340 -        SymInfo info = tbl.get(name);
 105.341 -        if (info == null) {
 105.342 -            info = new SymInfo(BOUND);
 105.343 -            if (SymInfo.isPrivateName(name)) {
 105.344 -                info.flags |= PRIVATE;
 105.345 -            } else if (SymInfo.isProtectedName(name)) {
 105.346 -                info.flags |= PROTECTED;
 105.347 -            }
 105.348 -            tbl.put(name, info);
 105.349 -            info.node = node;
 105.350 -            return info;
 105.351 -        }
 105.352 -        info.flags |= BOUND;
 105.353 -
 105.354 -        return info;
 105.355 -    }
 105.356 -
 105.357 -    public SymInfo addUsed(String name, PythonTree node) {
 105.358 -        SymInfo info = tbl.get(name);
 105.359 -        if (info == null) {
 105.360 -            // <netbeans>
 105.361 -            info = new SymInfo(0);
 105.362 -            tbl.put(name, info);
 105.363 -            info.node = node;
 105.364 -        }
 105.365 -        info.flags |= READ;
 105.366 -
 105.367 -        return info;
 105.368 -        // </netbeans>
 105.369 -    }
 105.370 -
 105.371 -
 105.372 -    // <netbeans>
 105.373 -    void markCall(String name) {
 105.374 -        SymInfo entry = tbl.get(name);
 105.375 -        if (entry != null) {
 105.376 -            entry.flags |= CALLED;
 105.377 -        }
 105.378 -    }
 105.379 -    // </netbeans>
 105.380 -    private final static String PRESENT = new String("PRESENT");
 105.381 -    public HashMap<String, String> inner_free = new HashMap<>();
 105.382 -    public List<String> cellvars = new ArrayList<>();
 105.383 -    public List<String> jy_paramcells = new ArrayList<>();
 105.384 -    public int jy_npurecell;
 105.385 -    public int cell, distance;
 105.386 -    public ScopeInfo up;
 105.387 -    public ScopeInfo nested;
 105.388 -
 105.389 -    //Resolve the names used in the given scope, and mark any freevars used in the up scope
 105.390 -    public void cook(ScopeInfo up, int distance, SymbolTable ctxt) throws Exception {
 105.391 -        if (up == null) {
 105.392 -            return; // top level => nop
 105.393 -        }
 105.394 -        this.up = up;
 105.395 -        this.distance = distance;
 105.396 -        boolean func = kind == FUNCSCOPE;
 105.397 -        List<String> purecells = new ArrayList<>();
 105.398 -        cell = 0;
 105.399 -        boolean some_inner_free = inner_free.size() > 0;
 105.400 -
 105.401 -        for (String name : inner_free.keySet()) {
 105.402 -
 105.403 -            SymInfo info = tbl.get(name);
 105.404 -            if (info == null) {
 105.405 -                tbl.put(name, new SymInfo(FREE));
 105.406 -                continue;
 105.407 -            }
 105.408 -            int flags = info.flags;
 105.409 -            if (func) {
 105.410 -                // not func global and bound ?
 105.411 -                if ((flags & NGLOBAL) == 0 && (flags & BOUND) != 0) {
 105.412 -                    info.flags |= CELL;
 105.413 -                    if ((info.flags & PARAM) != 0) {
 105.414 -                        jy_paramcells.add(name);
 105.415 -                    }
 105.416 -                    cellvars.add(name);
 105.417 -                    info.env_index = cell++;
 105.418 -                    if ((flags & PARAM) == 0) {
 105.419 -                        purecells.add(name);
 105.420 -                    }
 105.421 -                    continue;
 105.422 -                }
 105.423 -            } else {
 105.424 -                info.flags |= FREE;
 105.425 -            }
 105.426 -        }
 105.427 -        boolean some_free = false;
 105.428 -
 105.429 -        boolean nested = up.kind != TOPSCOPE;
 105.430 -        for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
 105.431 -            String name = entry.getKey();
 105.432 -            SymInfo info = entry.getValue();
 105.433 -            int flags = info.flags;
 105.434 -            if (nested && (flags & FREE) != 0) {
 105.435 -                up.inner_free.put(name, PRESENT);
 105.436 -            }
 105.437 -            if ((flags & (GLOBAL | PARAM | CELL)) == 0) {
 105.438 -                if ((flags & BOUND) != 0) { // ?? only func
 105.439 -                    // System.err.println("local: "+name);
 105.440 -                    names.add(name);
 105.441 -                    info.locals_index = local++;
 105.442 -                    continue;
 105.443 -                }
 105.444 -                info.flags |= FREE;
 105.445 -                some_free = true;
 105.446 -                if (nested) {
 105.447 -                    up.inner_free.put(name, PRESENT);
 105.448 -                }
 105.449 -            }
 105.450 -
 105.451 -            // <netbeans>
 105.452 -            if ((info.flags & FREE) != 0) {
 105.453 -                // Mark definition symbol as read as well
 105.454 -                ScopeInfo curr = up;
 105.455 -                while (curr != null) {
 105.456 -                    SymInfo s = curr.tbl.get(name);
 105.457 -                    if (s != null && ((s.flags & BOUND) != 0)) {
 105.458 -                        s.flags |= READ;
 105.459 -                        s.flags |= (info.flags & (CALLED));
 105.460 -                        break;
 105.461 -                    }
 105.462 -                    curr = curr.up;
 105.463 -                    while (curr != null && curr.kind == CLASSSCOPE) {
 105.464 -                        curr = curr.up;
 105.465 -                    }
 105.466 -                }
 105.467 -            }
 105.468 -
 105.469 -            // </netbeans>
 105.470 -        }
 105.471 -        if ((jy_npurecell = purecells.size()) > 0) {
 105.472 -            int sz = purecells.size();
 105.473 -            for (int i = 0; i < sz; i++) {
 105.474 -                names.add(purecells.get(i));
 105.475 -            }
 105.476 -        }
 105.477 -
 105.478 -        if (some_free && nested) {
 105.479 -            up.contains_ns_free_vars = true;
 105.480 -        }
 105.481 -        // XXX - this doesn't catch all cases - may depend subtly
 105.482 -        // on how visiting NOW works with antlr compared to javacc
 105.483 -        if ((unqual_exec || from_import_star)) {
 105.484 -            if (some_inner_free) {
 105.485 -                dynastuff_trouble(true, ctxt);
 105.486 -            } else if (func_level > 1 && some_free) {
 105.487 -                dynastuff_trouble(false, ctxt);
 105.488 -            }
 105.489 -        }
 105.490 -
 105.491 -    }
 105.492 -
 105.493 -    private void dynastuff_trouble(boolean inner_free,
 105.494 -            SymbolTable ctxt) throws Exception {
 105.495 -        String illegal;
 105.496 -        if (unqual_exec && from_import_star) {
 105.497 -            illegal = "function '" + scope_name +
 105.498 -                    "' uses import * and bare exec, which are illegal";
 105.499 -        } else if (unqual_exec) {
 105.500 -            illegal = "unqualified exec is not allowed in function '" +
 105.501 -                    scope_name + "'";
 105.502 -        } else {
 105.503 -            illegal = "import * is not allowed in function '" + scope_name + "'";
 105.504 -        }
 105.505 -        String why;
 105.506 -        if (inner_free) {
 105.507 -            why = " because it contains a function with free variables";
 105.508 -        } else {
 105.509 -            why = " because it contains free variables";
 105.510 -        }
 105.511 -        ctxt.error(illegal + why, true, scope_node);
 105.512 -    }
 105.513 -    public List<String> freevars = new ArrayList<>();
 105.514 -
 105.515 -    /**
 105.516 -     * setup the closure on this scope using the scope passed into cook as up as
 105.517 -     * the containing scope
 105.518 -     */
 105.519 -    public void setup_closure() {
 105.520 -        setup_closure(up);
 105.521 -    }
 105.522 -
 105.523 -    /**
 105.524 -     * setup the closure on this scope using the passed in scope. This is used
 105.525 -     * by jythonc to setup its closures.
 105.526 -     */
 105.527 -    public void setup_closure(ScopeInfo up) {
 105.528 -        int free = cell; // env = cell...,free...
 105.529 -        Map<String, SymInfo> up_tbl = up.tbl;
 105.530 -        boolean nested = up.kind != TOPSCOPE;
 105.531 -        for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
 105.532 -            String name = entry.getKey();
 105.533 -            SymInfo info = entry.getValue();
 105.534 -            int flags = info.flags;
 105.535 -            if ((flags & FREE) != 0) {
 105.536 -                SymInfo up_info = up_tbl.get(name);
 105.537 -                // ?? differs from CPython -- what is the intended behaviour?
 105.538 -                if (up_info != null) {
 105.539 -                    int up_flags = up_info.flags;
 105.540 -                    if ((up_flags & (CELL | FREE)) != 0) {
 105.541 -                        info.env_index = free++;
 105.542 -                        freevars.add(name);
 105.543 -                        continue;
 105.544 -                    }
 105.545 -                    // ! func global affect nested scopes
 105.546 -                    if (nested && (up_flags & NGLOBAL) != 0) {
 105.547 -                        info.flags = NGLOBAL | BOUND;
 105.548 -                        continue;
 105.549 -                    }
 105.550 -                }
 105.551 -                info.flags &= ~FREE;
 105.552 -            }
 105.553 -        }
 105.554 -
 105.555 -    }
 105.556 -
 105.557 -    @Override
 105.558 -    public String toString() {
 105.559 -        return "ScopeInfo[" + scope_name + " " + kind + "]@" +
 105.560 -                System.identityHashCode(this);
 105.561 -    }
 105.562 -
 105.563 -    public void defineAsGenerator(expr node) {
 105.564 -        generator = true;
 105.565 -        if (hasReturnWithValue) {
 105.566 -            throw new ParseException("'return' with argument " +
 105.567 -                    "inside generator", node);
 105.568 -        }
 105.569 -    }
 105.570 -
 105.571 -    public void noteReturnValue(Return node) {
 105.572 -        if (generator) {
 105.573 -            throw new ParseException("'return' with argument " +
 105.574 -                    "inside generator", node);
 105.575 -        }
 105.576 -        hasReturnWithValue = true;
 105.577 -    }
 105.578 -}
   106.1 --- a/python.editor/src/org/netbeans/modules/python/editor/scopes/ScopesCompiler.java	Fri Sep 18 16:20:24 2015 -0500
   106.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   106.3 @@ -1,641 +0,0 @@
   106.4 -// (C) Copyright 2001 Samuele Pedroni
   106.5 -package org.netbeans.modules.python.editor.scopes;
   106.6 -
   106.7 -import java.util.ArrayList;
   106.8 -import java.util.List;
   106.9 -import java.util.Map;
  106.10 -import java.util.Set;
  106.11 -import java.util.Stack;
  106.12 -import org.netbeans.modules.python.editor.AstPath;
  106.13 -import org.openide.util.Exceptions;
  106.14 -import org.python.antlr.PythonTree;
  106.15 -import org.python.antlr.Visitor;
  106.16 -import org.python.antlr.ast.Assign;
  106.17 -import org.python.antlr.ast.Attribute;
  106.18 -import org.python.antlr.ast.Call;
  106.19 -import org.python.antlr.ast.ClassDef;
  106.20 -import org.python.antlr.ast.Delete;
  106.21 -import org.python.antlr.ast.Exec;
  106.22 -import org.python.antlr.ast.Expression;
  106.23 -import org.python.antlr.ast.FunctionDef;
  106.24 -import org.python.antlr.ast.GeneratorExp;
  106.25 -import org.python.antlr.ast.Global;
  106.26 -import org.python.antlr.ast.Import;
  106.27 -import org.python.antlr.ast.ImportFrom;
  106.28 -import org.python.antlr.ast.Interactive;
  106.29 -import org.python.antlr.ast.Lambda;
  106.30 -import org.python.antlr.ast.ListComp;
  106.31 -import org.python.antlr.ast.Name;
  106.32 -import org.python.antlr.ast.Return;
  106.33 -import org.python.antlr.ast.Str;
  106.34 -import org.python.antlr.ast.With;
  106.35 -import org.python.antlr.ast.Yield;
  106.36 -import org.python.antlr.ast.alias;
  106.37 -import org.python.antlr.ast.arguments;
  106.38 -import org.python.antlr.base.expr;
  106.39 -import org.python.antlr.ast.expr_contextType;
  106.40 -import org.python.antlr.base.stmt;
  106.41 -
  106.42 -/** 
  106.43 - * Based on org.python.compiler.ScopesCompiler in Jython
  106.44 - *
  106.45 - * Modifications I've made:
  106.46 - * - Methods for finding all the free variables
  106.47 - * - Methods for identifying unused bound variables
  106.48 - * - Track whether symbols are referenced as calls or not
  106.49 - *   (so I can determine whether to look in the index for
  106.50 - *    functions or data etc. when trying to resolve imports)
  106.51 - * - Track variable reads/writes
  106.52 - * - Track imports etc.
  106.53 - * - Add nodes to each SymInfo
  106.54 - * - Replace old style Java (Hashtable, Vector, implements ScopeConstants) with
  106.55 - *   modern Java (HashMap, ArrayList, import static)
  106.56 - * 
  106.57 - */
  106.58 -@SuppressWarnings("unchecked")
  106.59 -public class ScopesCompiler extends Visitor implements ScopeConstants {
  106.60 -    private SymbolTable symbolTable;
  106.61 -    private Stack scopes;
  106.62 -    private ScopeInfo cur = null;
  106.63 -    private Map<PythonTree, ScopeInfo> nodeScopes;
  106.64 -    private int level = 0;
  106.65 -    private int func_level = 0;
  106.66 -    private List<Import> imports;
  106.67 -    private List<PythonTree> mainImports;
  106.68 -    private List<ImportFrom> importsFrom;
  106.69 -    private Set<PythonTree> topLevelImports;
  106.70 -    private PythonTree root;
  106.71 -    private PythonTree parent;
  106.72 -    private AstPath path = new AstPath();
  106.73 -    /** List of symbols registered via __all__ = [ "foo", "bar" ] or __all__.extend() or __all__.append() */
  106.74 -    private List<Str> publicSymbols;
  106.75 -    /** Set to true if we encountered manipulation on __all__ that I don't understand */
  106.76 -    private boolean invalidPublicSymbols;
  106.77 -
  106.78 -    public ScopesCompiler(SymbolTable symbolTable, Map<PythonTree, ScopeInfo> nodeScopes, PythonTree root,
  106.79 -            List<Import> imports, List<ImportFrom> importsFrom, List<PythonTree> mainImports, Set<PythonTree> topLevelImports) {
  106.80 -        this.symbolTable = symbolTable;
  106.81 -        this.nodeScopes = nodeScopes;
  106.82 -        scopes = new Stack();
  106.83 -        this.root = root;
  106.84 -
  106.85 -        this.imports = imports;
  106.86 -        this.importsFrom = importsFrom;
  106.87 -        this.mainImports = mainImports;
  106.88 -        this.topLevelImports = topLevelImports;
  106.89 -    }
  106.90 -
  106.91 -    @Override
  106.92 -    public void traverse(PythonTree node) throws Exception {
  106.93 -        // Jython's parser often doesn't set the parent references correctly
  106.94 -        // so try to fix that here
  106.95 -        node.setParent(parent);
  106.96 -
  106.97 -        PythonTree oldParent = parent;
  106.98 -        parent = node;
  106.99 -
 106.100 -        path.descend(node);
 106.101 -        super.traverse(node);
 106.102 -        parent = oldParent;
 106.103 -        path.ascend();
 106.104 -    }
 106.105 -
 106.106 -    public void beginScope(String name, int kind, PythonTree node,
 106.107 -            ArgListCompiler ac) {
 106.108 -        if (cur != null) {
 106.109 -            scopes.push(cur);
 106.110 -        }
 106.111 -        if (kind == FUNCSCOPE) {
 106.112 -            func_level++;
 106.113 -        }
 106.114 -        cur = new ScopeInfo(name, node, level++, kind, func_level, ac);
 106.115 -        nodeScopes.put(node, cur);
 106.116 -    }
 106.117 -
 106.118 -    public void endScope() throws Exception {
 106.119 -        if (cur.kind == FUNCSCOPE) {
 106.120 -            func_level--;
 106.121 -        }
 106.122 -        level--;
 106.123 -        ScopeInfo up = null;
 106.124 -        if (!scopes.empty()) {
 106.125 -            up = (ScopeInfo)scopes.pop();
 106.126 -        }
 106.127 -        //Go into the stack to find a non class containing scope to use making the closure
 106.128 -        //See PEP 227
 106.129 -        int dist = 1;
 106.130 -        ScopeInfo referenceable = up;
 106.131 -        for (int i = scopes.size() - 1; i >= 0 && referenceable.kind == CLASSSCOPE; i--, dist++) {
 106.132 -            referenceable = ((ScopeInfo)scopes.get(i));
 106.133 -        }
 106.134 -        cur.cook(referenceable, dist, symbolTable);
 106.135 -//        cur.dump(); // debug
 106.136 -        cur = up;
 106.137 -    }
 106.138 -
 106.139 -    public void parse() {
 106.140 -        try {
 106.141 -            visit(root);
 106.142 -        } catch (Throwable t) {
 106.143 -            Exceptions.printStackTrace(t);
 106.144 -            //throw org.python.core.ParserFacade.fixParseError(null, t,
 106.145 -            //        code_compiler.getFilename());
 106.146 -        }
 106.147 -    }
 106.148 -
 106.149 -    @Override
 106.150 -    public Object visitInteractive(Interactive node) throws Exception {
 106.151 -        beginScope("<single-top>", TOPSCOPE, node, null);
 106.152 -        PythonTree oldParent = parent;
 106.153 -        parent = node;
 106.154 -        suite(node.getInternalBody());
 106.155 -        parent = oldParent;
 106.156 -        endScope();
 106.157 -        return null;
 106.158 -    }
 106.159 -
 106.160 -    @Override
 106.161 -    public Object visitModule(org.python.antlr.ast.Module node)
 106.162 -            throws Exception {
 106.163 -        List<stmt> body = node.getInternalBody();
 106.164 -        if (body != null && body.size() > 0) {
 106.165 -            boolean foundFirst = false;
 106.166 -            for (stmt stmt : body) {
 106.167 -                if (stmt != null) {
 106.168 -                    if (stmt instanceof Import || stmt instanceof ImportFrom) {
 106.169 -                        if (!foundFirst) {
 106.170 -                            foundFirst = true;
 106.171 -                        }
 106.172 -                        mainImports.add(stmt);
 106.173 -                    } else if (foundFirst) {
 106.174 -                        break;
 106.175 -                    }
 106.176 -                }
 106.177 -            }
 106.178 -        }
 106.179 -
 106.180 -        beginScope("<file-top>", TOPSCOPE, node, null);
 106.181 -
 106.182 -        PythonTree oldParent = parent;
 106.183 -        parent = node;
 106.184 -        suite(node.getInternalBody());
 106.185 -        parent = oldParent;
 106.186 -
 106.187 -        endScope();
 106.188 -        return null;
 106.189 -    }
 106.190 -
 106.191 -    @Override
 106.192 -    public Object visitExpression(Expression node) throws Exception {
 106.193 -        beginScope("<eval-top>", TOPSCOPE, node, null);
 106.194 -        visit(new Return(node, node.getInternalBody()));
 106.195 -        endScope();
 106.196 -        return null;
 106.197 -    }
 106.198 -
 106.199 -    private void def(String name, int extraFlags, PythonTree node) {
 106.200 -        SymInfo info = cur.addBound(name, node);
 106.201 -        // <netbeans>
 106.202 -        info.flags |= (DEF | extraFlags);
 106.203 -        info.node = node;
 106.204 -        // </netbeans>
 106.205 -    }
 106.206 -
 106.207 -    @Override
 106.208 -    public Object visitAssign(Assign node) throws Exception {
 106.209 -        List<expr> targets = node.getInternalTargets();
 106.210 -        if (targets != null && targets.size() == 1 && targets.get(0) instanceof Name) {
 106.211 -            Name lhs = (Name)targets.get(0);
 106.212 -            if ("__all__".equals(lhs.getInternalId())) { // NOI18N
 106.213 -                expr nodeValue = node.getInternalValue();
 106.214 -                if (!invalidPublicSymbols && nodeValue instanceof org.python.antlr.ast.List) {
 106.215 -                    org.python.antlr.ast.List allList = (org.python.antlr.ast.List)nodeValue;
 106.216 -                    if (allList != null) {
 106.217 -                        for (expr expr : allList.getInternalElts()) {
 106.218 -                            if (expr instanceof Str) {
 106.219 -                                Str str = (Str)expr;
 106.220 -                                if (publicSymbols == null) {
 106.221 -                                    publicSymbols = new ArrayList<>();
 106.222 -                                }
 106.223 -                                publicSymbols.add(str);
 106.224 -                            } else {
 106.225 -                                invalidPublicSymbols = true;
 106.226 -                            }
 106.227 -                        }
 106.228 -                    }
 106.229 -                } else {
 106.230 -                    invalidPublicSymbols = true;
 106.231 -                }
 106.232 -            }
 106.233 -        }
 106.234 -
 106.235 -        if (targets.size() > 0) {
 106.236 -            List<Name> names = new ArrayList<>(targets.size());
 106.237 -            boolean valid = true;
 106.238 -            for (expr et : targets) {
 106.239 -                if (et instanceof Name) {
 106.240 -                    Name name = (Name)et;
 106.241 -                    names.add(name);
 106.242 -                } else {
 106.243 -                    valid = false;
 106.244 -                }
 106.245 -            }
 106.246 -            if (valid) {
 106.247 -                expr nodeValue = node.getInternalValue();
 106.248 -                if (nodeValue instanceof Name) {
 106.249 -                    Name value = (Name)nodeValue;
 106.250 -
 106.251 -                    SymInfo rhsSym = cur.tbl.get(value.getInternalId());
 106.252 -                    if (rhsSym != null && rhsSym.isDef()) {
 106.253 -                        for (Name name : names) {
 106.254 -                            visitName(name);
 106.255 -                            SymInfo sym = cur.tbl.get(name.getInternalId());
 106.256 -                            if (sym != null) {
 106.257 -                                sym.flags |= ALIAS;
 106.258 -                                sym.flags |= (rhsSym.flags & (CLASS | FUNCTION));
 106.259 -                                sym.node = rhsSym.node;
 106.260 -                            }
 106.261 -                        }
 106.262 -                    }
 106.263 -                }
 106.264 -            }
 106.265 -        }
 106.266 -
 106.267 -        return super.visitAssign(node);
 106.268 -    }
 106.269 -
 106.270 -    @Override
 106.271 -    public Object visitFunctionDef(FunctionDef node) throws Exception {
 106.272 -        def(node.getInternalName(), FUNCTION, node);
 106.273 -        ArgListCompiler ac = new ArgListCompiler(symbolTable);
 106.274 -        ac.visitArgs(node.getInternalArgs());
 106.275 -
 106.276 -        List<expr> defaults = ac.getDefaults();
 106.277 -        for (int i = 0; i < defaults.size(); i++) {
 106.278 -            visit(defaults.get(i));
 106.279 -        }
 106.280 -
 106.281 -        List<expr> decs = node.getInternalDecorator_list();
 106.282 -        for (int i = decs.size() - 1; i >= 0; i--) {
 106.283 -            visit(decs.get(i));
 106.284 -        }
 106.285 -
 106.286 -        ScopeInfo parentScope = cur;
 106.287 -        beginScope(node.getInternalName(), FUNCSCOPE, node, ac);
 106.288 -        cur.nested = parentScope;
 106.289 -
 106.290 -        int n = ac.names.size();
 106.291 -        for (int i = 0; i < n; i++) {
 106.292 -            cur.addParam(ac.names.get(i), ac.nodes.get(i));
 106.293 -        }
 106.294 -        for (int i = 0; i < ac.init_code.size(); i++) {
 106.295 -            visit(ac.init_code.get(i));
 106.296 -        }
 106.297 -        cur.markFromParam();
 106.298 -
 106.299 -        PythonTree oldParent = parent;
 106.300 -        parent = node;
 106.301 -        suite(node.getInternalBody());
 106.302 -        parent = oldParent;
 106.303 -
 106.304 -        endScope();
 106.305 -        return null;
 106.306 -    }
 106.307 -
 106.308 -    @Override
 106.309 -    public Object visitLambda(Lambda node) throws Exception {
 106.310 -        ArgListCompiler ac = new ArgListCompiler(symbolTable);
 106.311 -        ac.visitArgs(node.getInternalArgs());
 106.312 -
 106.313 -        List<expr> defaults = ac.getDefaults();
 106.314 -        for (expr expr : defaults) {
 106.315 -            visit(expr);
 106.316 -        }
 106.317 -
 106.318 -        beginScope("<lambda>", FUNCSCOPE, node, ac);
 106.319 -        assert ac.names.size() == ac.nodes.size();
 106.320 -        for (int i = 0; i < ac.names.size(); i++) {
 106.321 -            cur.addParam(ac.names.get(i), ac.nodes.get(i));
 106.322 -        }
 106.323 -        for (Object o : ac.init_code) {
 106.324 -            visit((stmt)o);
 106.325 -        }
 106.326 -        cur.markFromParam();
 106.327 -        visit(node.getInternalBody());
 106.328 -        endScope();
 106.329 -        return null;
 106.330 -    }
 106.331 -
 106.332 -    public void suite(List<stmt> stmts) throws Exception {
 106.333 -        if (stmts != null) {
 106.334 -            for (int i = 0; i < stmts.size(); i++) {
 106.335 -                stmt s = stmts.get(i);
 106.336 -                path.descend(s);
 106.337 -                visit(s);
 106.338 -                path.ascend();
 106.339 -            }
 106.340 -        }
 106.341 -    }
 106.342 -
 106.343 -    @Override
 106.344 -    public Object visitImport(Import node) throws Exception {
 106.345 -        if (parent == root) {
 106.346 -            topLevelImports.add(node);
 106.347 -        }
 106.348 -        imports.add(node);
 106.349 -
 106.350 -        List<alias> names = node.getInternalNames();
 106.351 -        if (names != null) {
 106.352 -            for (alias alias : names) {
 106.353 -                String asname = alias.getInternalAsname();
 106.354 -                if (asname != null) {
 106.355 -                    SymInfo entry = cur.addBound(asname, node);
 106.356 -                    entry.flags |= IMPORTED;
 106.357 -                } else {
 106.358 -                    String name = alias.getInternalName();
 106.359 -                    if (name.indexOf('.') > 0) {
 106.360 -                        name = name.substring(0, name.indexOf('.'));
 106.361 -                    }
 106.362 -                    SymInfo entry = cur.addBound(name, node);
 106.363 -                    entry.flags |= IMPORTED;
 106.364 -                }
 106.365 -            }
 106.366 -        }
 106.367 -        return null;
 106.368 -    }
 106.369 -
 106.370 -    @Override
 106.371 -    public Object visitImportFrom(ImportFrom node) throws Exception {
 106.372 -        if (parent == root) {
 106.373 -            topLevelImports.add(node);
 106.374 -        }
 106.375 -        importsFrom.add(node);
 106.376 -
 106.377 -        //Future.checkFromFuture(node); // future stmt support
 106.378 -        List<alias> names = node.getInternalNames();
 106.379 -        if (names == null || names.size() == 0) {
 106.380 -            cur.from_import_star = true;
 106.381 -            return null;
 106.382 -        }
 106.383 -        for (alias alias : names) {
 106.384 -            String asname = alias.getInternalAsname();
 106.385 -            if (asname != null) {
 106.386 -                SymInfo entry = cur.addBound(asname, node);
 106.387 -                entry.flags |= IMPORTED;
 106.388 -            } else {
 106.389 -                SymInfo entry = cur.addBound(alias.getInternalName(), node);
 106.390 -                entry.flags |= IMPORTED;
 106.391 -            }
 106.392 -        }
 106.393 -        return null;
 106.394 -    }
 106.395 -
 106.396 -    @Override
 106.397 -    public Object visitGlobal(Global node) throws Exception {
 106.398 -        List<String> names = node.getInternalNames();
 106.399 -        for (String name : names) {
 106.400 -            int prev = cur.addGlobal(name, node);
 106.401 -            if (prev >= 0) {
 106.402 -                if ((prev & FROM_PARAM) != 0) {
 106.403 -                    symbolTable.error("name '" + name + "' is local and global", true, node);
 106.404 -                }
 106.405 -                if ((prev & GLOBAL) != 0) {
 106.406 -                    continue;
 106.407 -                }
 106.408 -                String what;
 106.409 -                if ((prev & BOUND) != 0) {
 106.410 -                    what = "assignment";
 106.411 -                } else {
 106.412 -                    what = "use";
 106.413 -                }
 106.414 -                symbolTable.error("name '" + name + "' declared global after " + what, false, node);
 106.415 -            }
 106.416 -        }
 106.417 -        return null;
 106.418 -    }
 106.419 -
 106.420 -    @Override
 106.421 -    public Object visitExec(Exec node) throws Exception {
 106.422 -        cur.exec = true;
 106.423 -        if (node.getInternalGlobals() == null && node.getInternalLocals() == null) {
 106.424 -            cur.unqual_exec = true;
 106.425 -        }
 106.426 -        traverse(node);
 106.427 -        return null;
 106.428 -    }
 106.429 -
 106.430 -    @Override
 106.431 -    public Object visitClassDef(ClassDef node) throws Exception {
 106.432 -        String name = node.getInternalName();
 106.433 -        def(name, CLASS, node);
 106.434 -        List<expr> bases = node.getInternalBases();
 106.435 -        if (bases != null) {
 106.436 -            for (expr expr : bases) {
 106.437 -                visit(expr);
 106.438 -            }
 106.439 -        }
 106.440 -        ScopeInfo parentScope = cur;
 106.441 -        beginScope(name, CLASSSCOPE, node, null);
 106.442 -        cur.nested = parentScope;
 106.443 -        PythonTree oldParent = parent;
 106.444 -        parent = node;
 106.445 -        suite(node.getInternalBody());
 106.446 -        parent = oldParent;
 106.447 -        endScope();
 106.448 -        return null;
 106.449 -    }
 106.450 -
 106.451 -    @Override
 106.452 -    public Object visitName(Name node) throws Exception {
 106.453 -        // Jython's parser doesn't always initialize the parent references correctly;
 106.454 -        // try to correct that here.
 106.455 -        node.setParent(parent);
 106.456 -
 106.457 -        String name = node.getInternalId();
 106.458 -        if (node.getInternalCtx() != expr_contextType.Load) {
 106.459 -            if (name.equals("__debug__")) {
 106.460 -                symbolTable.error("can not assign to __debug__", true, node);
 106.461 -            }
 106.462 -            cur.addBound(name, node);
 106.463 -        } else {
 106.464 -            cur.addUsed(name, node);
 106.465 -        }
 106.466 -        return null;
 106.467 -    }
 106.468 -
 106.469 -    // <netbeans>
 106.470 -    @Override
 106.471 -    public Object visitCall(Call node) throws Exception {
 106.472 -        Object ret = super.visitCall(node);
 106.473 -
 106.474 -        expr func = node.getInternalFunc();
 106.475 -        if (func instanceof Name) {
 106.476 -            Name name = (Name)func;
 106.477 -            cur.markCall(name.getInternalId());
 106.478 -        } else if (func instanceof Attribute) {
 106.479 -            Attribute attr = (Attribute)func;
 106.480 -            if (cur.attributes != null) {
 106.481 -                SymInfo funcSymbol = cur.attributes.get(attr.getInternalAttr());
 106.482 -                if (funcSymbol != null) {
 106.483 -                    funcSymbol.flags |= FUNCTION | CALLED; // mark as func/method call
 106.484 -                }
 106.485 -            }
 106.486 -
 106.487 -        }
 106.488 -
 106.489 -        return ret;
 106.490 -    }
 106.491 -
 106.492 -    @Override
 106.493 -    public Object visitDelete(Delete node) throws Exception {
 106.494 -        for (expr et : node.getInternalTargets()) {
 106.495 -            if (et instanceof Name) {
 106.496 -                String name = ((Name)et).getInternalId();
 106.497 -                cur.addUsed(name, node);
 106.498 -            }
 106.499 -        }
 106.500 -
 106.501 -        return super.visitDelete(node);
 106.502 -    }
 106.503 -
 106.504 -    @Override
 106.505 -    public Object visitAttribute(Attribute node) throws Exception {
 106.506 -        if (parent instanceof Call && node.getInternalValue() instanceof Name &&
 106.507 -                ("__all__".equals(((Name)node.getInternalValue()).getInternalId()))) {
 106.508 -            // If you for example call
 106.509 -            //    __all__.extend("foo")
 106.510 -            // or
 106.511 -            //    __all__.append("bar")
 106.512 -            // then I don't want to try to analyze __all__
 106.513 -            String nodeAttr = node.getInternalAttr();
 106.514 -            if ("extend".equals(nodeAttr) || "append".equals(nodeAttr)) { // NOI18N
 106.515 -                Call call = (Call)parent;
 106.516 -                List<expr> callArgs = call.getInternalArgs();
 106.517 -                if (callArgs != null) {
 106.518 -                    for (expr expr : callArgs) {
 106.519 -                        if (expr instanceof Str) {
 106.520 -                            if (publicSymbols == null) {
 106.521 -                                publicSymbols = new ArrayList<>();
 106.522 -                            }
 106.523 -                            publicSymbols.add((Str)expr);
 106.524 -                        } else if (expr instanceof org.python.antlr.ast.List) {
 106.525 -                            org.python.antlr.ast.List list = (org.python.antlr.ast.List)expr;
 106.526 -                            if (list != null) {
 106.527 -                                List<expr> elts = list.getInternalElts();
 106.528 -                                if (elts != null) {
 106.529 -                                    for (expr ex : elts) {
 106.530 -                                        if (ex instanceof Str) {
 106.531 -                                            Str str = (Str)ex;
 106.532 -                                            if (publicSymbols == null) {
 106.533 -                                                publicSymbols = new ArrayList<>();
 106.534 -                                            }
 106.535 -                                            publicSymbols.add(str);
 106.536 -                                        } else {
 106.537 -                                            invalidPublicSymbols = true;
 106.538 -                                        }
 106.539 -                                    }
 106.540 -                                }
 106.541 -                            }
 106.542 -                        } else {
 106.543 -                            invalidPublicSymbols = true;
 106.544 -                            break;
 106.545 -                        }
 106.546 -                    }
 106.547 -                }
 106.548 -            } else {
 106.549 -                invalidPublicSymbols = true;
 106.550 -            }
 106.551 -        } else {
 106.552 -            String nodeAttr = node.getInternalAttr();
 106.553 -            if (nodeAttr != null) {
 106.554 -                cur.addAttribute(path, nodeAttr, node);
 106.555 -            }
 106.556 -        }
 106.557 -        return super.visitAttribute(node);
 106.558 -    }
 106.559 -    // </netbeans>
 106.560 -
 106.561 -    @Override
 106.562 -    public Object visitListComp(ListComp node) throws Exception {
 106.563 -        String tmp = "_[" + node.getLine() + "_" + node.getCharPositionInLine() + "]";
 106.564 -        cur.addBound(tmp, node);
 106.565 -        traverse(node);
 106.566 -        return null;
 106.567 -    }
 106.568 -
 106.569 -    @Override
 106.570 -    public Object visitYield(Yield node) throws Exception {
 106.571 -        cur.defineAsGenerator(node);
 106.572 -        cur.yield_count++;
 106.573 -        traverse(node);
 106.574 -        return null;
 106.575 -    }
 106.576 -
 106.577 -    @Override
 106.578 -    public Object visitReturn(Return node) throws Exception {
 106.579 -        if (node.getInternalValue() != null) {
 106.580 -            cur.noteReturnValue(node);
 106.581 -        }
 106.582 -        traverse(node);
 106.583 -        return null;
 106.584 -    }
 106.585 -
 106.586 -    @Override
 106.587 -    public Object visitGeneratorExp(GeneratorExp node) throws Exception {
 106.588 -        // The first iterator is evaluated in the outer scope
 106.589 -        if (node.getInternalGenerators() != null && node.getInternalGenerators().size() > 0) {
 106.590 -            visit(node.getInternalGenerators().get(0).getInternalIter());
 106.591 -        }
 106.592 -        String bound_exp = "_(x)";
 106.593 -        String tmp = "_(" + node.getLine() + "_" + node.getCharPositionInLine() + ")";
 106.594 -        def(tmp, GENERATOR, node);
 106.595 -        ArgListCompiler ac = new ArgListCompiler(symbolTable);
 106.596 -        List<expr> args = new ArrayList<>();
 106.597 -        Name argsName = new Name(node.getToken(), bound_exp, expr_contextType.Param);
 106.598 -        args.add(argsName);
 106.599 -        ac.visitArgs(new arguments(node, args, null, null, new ArrayList<expr>()));
 106.600 -        beginScope(tmp, FUNCSCOPE, node, ac);
 106.601 -        cur.addParam(bound_exp, argsName);
 106.602 -        cur.markFromParam();
 106.603 -
 106.604 -        cur.defineAsGenerator(node);
 106.605 -        cur.yield_count++;
 106.606 -        // The reset of the iterators are evaluated in the inner scope
 106.607 -        if (node.getInternalElt() != null) {
 106.608 -            visit(node.getInternalElt());
 106.609 -        }
 106.610 -        if (node.getInternalGenerators() != null) {
 106.611 -            for (int i = 0; i < node.getInternalGenerators().size(); i++) {
 106.612 -                if (node.getInternalGenerators().get(i) != null) {
 106.613 -                    if (i == 0) {
 106.614 -                        visit(node.getInternalGenerators().get(i).getInternalTarget());
 106.615 -                        if (node.getInternalGenerators().get(i).getInternalIfs() != null) {
 106.616 -                            for (expr cond : node.getInternalGenerators().get(i).getInternalIfs()) {
 106.617 -                                if (cond != null) {
 106.618 -                                    visit(cond);
 106.619 -                                }
 106.620 -                            }
 106.621 -                        }
 106.622 -                    } else {
 106.623 -                        visit(node.getInternalGenerators().get(i));
 106.624 -                    }
 106.625 -                }
 106.626 -            }
 106.627 -        }
 106.628 -
 106.629 -        endScope();
 106.630 -        return null;
 106.631 -    }
 106.632 -
 106.633 -    @Override
 106.634 -    public Object visitWith(With node) throws Exception {
 106.635 -        cur.max_with_count++;
 106.636 -        traverse(node);
 106.637 -
 106.638 -        return null;
 106.639 -    }
 106.640 -
 106.641 -    public List<Str> getPublicSymbols() {
 106.642 -        return invalidPublicSymbols ? null : publicSymbols;
 106.643 -    }
 106.644 -}
   107.1 --- a/python.editor/src/org/netbeans/modules/python/editor/scopes/SymInfo.java	Fri Sep 18 16:20:24 2015 -0500
   107.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   107.3 @@ -1,209 +0,0 @@
   107.4 -package org.netbeans.modules.python.editor.scopes;
   107.5 -
   107.6 -import org.python.antlr.PythonTree;
   107.7 -import static org.netbeans.modules.python.editor.scopes.ScopeConstants.*;
   107.8 -
   107.9 -public class SymInfo extends Object {
  107.10 -    public SymInfo(int flags) {
  107.11 -        this.flags = flags;
  107.12 -    }
  107.13 -
  107.14 -    public SymInfo(int flags, int locals_index) {
  107.15 -        this.flags = flags;
  107.16 -        this.locals_index = locals_index;
  107.17 -    }
  107.18 -    public int flags;
  107.19 -    public int locals_index;
  107.20 -    public int env_index;
  107.21 -    public PythonTree node;
  107.22 -
  107.23 -    @Override
  107.24 -    public String toString() {
  107.25 -        return "SymInfo[" + flags + " " + locals_index + " " +
  107.26 -                env_index + "]" + dumpFlags(null);
  107.27 -    }
  107.28 -
  107.29 -    public String dumpFlags(ScopeInfo info) {
  107.30 -        StringBuilder sb = new StringBuilder();
  107.31 -        if ((flags & BOUND) != 0) {
  107.32 -            sb.append("[bound]");
  107.33 -        }
  107.34 -        // func scope global (affect nested scopes)
  107.35 -        // vs. class scope global
  107.36 -        if ((flags & NGLOBAL) != 0) {
  107.37 -            sb.append("[func-global]");
  107.38 -        } else if ((flags & CLASS_GLOBAL) != 0) {
  107.39 -            sb.append("[class-global]");
  107.40 -        }
  107.41 -        if ((flags & PARAM) != 0) {
  107.42 -            sb.append("[param]");
  107.43 -        } else if ((flags & FROM_PARAM) != 0) {
  107.44 -            sb.append("[from-param]");
  107.45 -        }
  107.46 -        if ((flags & CELL) != 0) {
  107.47 -            sb.append("[cell]");
  107.48 -        }
  107.49 -        if ((flags & FREE) != 0) {
  107.50 -            sb.append("[free]");
  107.51 -        }
  107.52 -        if (isImported()) {
  107.53 -            sb.append("[imported]");
  107.54 -        }
  107.55 -        if (isPrivate()) {
  107.56 -            sb.append("[private]");
  107.57 -        }
  107.58 -        if (isClass()) {
  107.59 -            sb.append("[class]");
  107.60 -        }
  107.61 -        if (isFunction()) {
  107.62 -            sb.append("[function]");
  107.63 -        }
  107.64 -        if (isData()) {
  107.65 -            sb.append("[data]");
  107.66 -        }
  107.67 -        if (isMember()) {
  107.68 -            sb.append("[member]");
  107.69 -        }
  107.70 -        if (isDef()) {
  107.71 -            sb.append("[def]");
  107.72 -        }
  107.73 -        if (isRead()) {
  107.74 -            sb.append("[read]");
  107.75 -        }
  107.76 -        if (isAlias()) {
  107.77 -            sb.append("[alias]");
  107.78 -        }
  107.79 -        if (isGeneratorExp()) {
  107.80 -            sb.append("[generator]");
  107.81 -        }
  107.82 -        if (isCalled()) {
  107.83 -            sb.append("[called]");
  107.84 -        }
  107.85 -        if (isProtected()) {
  107.86 -            sb.append("[protected]");
  107.87 -        }
  107.88 -        if (isBoundInConstructor()) {
  107.89 -            sb.append("[bound-in-constructor]");
  107.90 -        }
  107.91 -        if (isUnused(info)) {
  107.92 -            sb.append("[unused]");
  107.93 -        }
  107.94 -        if (isUnresolved()) {
  107.95 -            sb.append("[UNRESOLVED]");
  107.96 -        }
  107.97 -        sb.append("[node=");
  107.98 -        if (node != null) {
  107.99 -            sb.append(node.getClass().getSimpleName());
 107.100 -        } else {
 107.101 -            sb.append("null");
 107.102 -        }
 107.103 -        sb.append("]");
 107.104 -
 107.105 -        return sb.toString();
 107.106 -    }
 107.107 -
 107.108 -    public boolean isUnused(ScopeInfo info) {
 107.109 -        // Cannot correctly detect usage of variables in CLASSSCOPE
 107.110 -        return (info == null || info.kind == FUNCSCOPE || info.kind == TOPSCOPE) &&
 107.111 -                (flags & (READ | BOUND | DEF)) == BOUND;
 107.112 -    }
 107.113 -
 107.114 -    public boolean isParameter() {
 107.115 -        return (flags & (PARAM | FROM_PARAM)) != 0;
 107.116 -    }
 107.117 -
 107.118 -    public boolean isUnresolved() {
 107.119 -        return (flags & (BOUND | FREE)) == 0;
 107.120 -    }
 107.121 -
 107.122 -    public boolean isImported() {
 107.123 -        return (flags & IMPORTED) != 0;
 107.124 -    }
 107.125 -
 107.126 -    public boolean isData() {
 107.127 -        return (flags & (BOUND | DEF | CLASS | FUNCTION)) == (BOUND);
 107.128 -    }
 107.129 -
 107.130 -    public boolean isClass() {
 107.131 -        return (flags & CLASS) != 0;
 107.132 -    }
 107.133 -
 107.134 -    public boolean isDef() {
 107.135 -        return (flags & DEF) != 0;
 107.136 -    }
 107.137 -
 107.138 -    public boolean isFunction() {
 107.139 -        return (flags & FUNCTION) != 0;
 107.140 -    }
 107.141 -
 107.142 -    public boolean isBound() {
 107.143 -        return (flags & BOUND) != 0;
 107.144 -    }
 107.145 -
 107.146 -    public boolean isMember() {
 107.147 -        return (flags & MEMBER) != 0;
 107.148 -    }
 107.149 -
 107.150 -    public boolean isCalled() {
 107.151 -        return (flags & CALLED) != 0;
 107.152 -    }
 107.153 -
 107.154 -    public boolean isRead() {
 107.155 -        return (flags & READ) != 0;
 107.156 -    }
 107.157 -
 107.158 -    public boolean isGeneratorExp() {
 107.159 -        return (flags & GENERATOR) != 0;
 107.160 -    }
 107.161 -
 107.162 -    public boolean isFree() {
 107.163 -        return (flags & FREE) != 0;
 107.164 -    }
 107.165 -
 107.166 -    public boolean isPrivate() {
 107.167 -        return (flags & PRIVATE) != 0;
 107.168 -    }
 107.169 -
 107.170 -    public boolean isProtected() {
 107.171 -        return (flags & PROTECTED) != 0;
 107.172 -    }
 107.173 -
 107.174 -    public boolean isBoundInConstructor() {
 107.175 -        return (flags & BOUND_IN_CONSTRUCTOR) != 0;
 107.176 -    }
 107.177 -
 107.178 -    public boolean isAlias() {
 107.179 -        return (flags & ALIAS) != 0;
 107.180 -    }
 107.181 -
 107.182 -    public boolean isVariable(boolean mustBeBound) {
 107.183 -        int mask = mustBeBound ? BOUND : 0;
 107.184 -        return (flags & (BOUND | CALLED | DEF | IMPORTED | CLASS | FUNCTION | MEMBER | GENERATOR)) == mask;
 107.185 -    }
 107.186 -
 107.187 -    public static boolean isPrivateName(String name) {
 107.188 -        // Private variables: start with __ but doesn't end with __
 107.189 -        // Section 9.6 Private Variables - http://docs.python.org/tut/node11.html
 107.190 -        if (name.startsWith("__") && !name.endsWith("__")) { // NOI18N
 107.191 -            return true;
 107.192 -        } else if (name != null && name.startsWith("_") && !name.endsWith("_")) { // NOI18N
 107.193 -            // From PEP8: Single_leading_underscore: weak "internal use" indicator
 107.194 -            // (e.g. "from M import *" does not import objects whose name
 107.195 -            // starts with an underscore).
 107.196 -            return true;
 107.197 -        }
 107.198 -
 107.199 -        return false;
 107.200 -    }
 107.201 -
 107.202 -    public static boolean isProtectedName(String name) {
 107.203 -        // Protected variable starts with a single _
 107.204 -        // this is a convention only
 107.205 -        if (!name.startsWith("__")) { // NOI18N
 107.206 -            if (name.startsWith("_")) { // NOI18N
 107.207 -                return true;
 107.208 -            }
 107.209 -        }
 107.210 -        return false;
 107.211 -    }
 107.212 -}
   108.1 --- a/python.editor/src/org/netbeans/modules/python/editor/scopes/SymbolTable.java	Fri Sep 18 16:20:24 2015 -0500
   108.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   108.3 @@ -1,1249 +0,0 @@
   108.4 -/*
   108.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   108.6 - *
   108.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   108.8 - *
   108.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  108.10 - * Other names may be trademarks of their respective owners.
  108.11 - *
  108.12 - * The contents of this file are subject to the terms of either the GNU
  108.13 - * General Public License Version 2 only ("GPL") or the Common
  108.14 - * Development and Distribution License("CDDL") (collectively, the
  108.15 - * "License"). You may not use this file except in compliance with the
  108.16 - * License. You can obtain a copy of the License at
  108.17 - * http://www.netbeans.org/cddl-gplv2.html
  108.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  108.19 - * specific language governing permissions and limitations under the
  108.20 - * License.  When distributing the software, include this License Header
  108.21 - * Notice in each file and include the License file at
  108.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  108.23 - * particular file as subject to the "Classpath" exception as provided
  108.24 - * by Oracle in the GPL Version 2 section of the License file that
  108.25 - * accompanied this code. If applicable, add the following below the
  108.26 - * License Header, with the fields enclosed by brackets [] replaced by
  108.27 - * your own identifying information:
  108.28 - * "Portions Copyrighted [year] [name of copyright owner]"
  108.29 - *
  108.30 - * If you wish your version of this file to be governed by only the CDDL
  108.31 - * or only the GPL Version 2, indicate your decision by adding
  108.32 - * "[Contributor] elects to include this software in this distribution
  108.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
  108.34 - * single choice of license, a recipient has the option to distribute
  108.35 - * your version of this file under either the CDDL, the GPL Version 2 or
  108.36 - * to extend the choice of license to its licensees as provided above.
  108.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
  108.38 - * Version 2 license, then the option applies only if the new code is
  108.39 - * made subject to such option by the copyright holder.
  108.40 - *
  108.41 - * Contributor(s):
  108.42 - *
  108.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
  108.44 - */
  108.45 -package org.netbeans.modules.python.editor.scopes;
  108.46 -
  108.47 -import java.util.ArrayList;
  108.48 -import java.util.Collections;
  108.49 -import java.util.HashMap;
  108.50 -import java.util.HashSet;
  108.51 -import java.util.List;
  108.52 -import java.util.Map;
  108.53 -import java.util.Set;
  108.54 -import org.netbeans.modules.csl.api.ElementKind;
  108.55 -import org.netbeans.modules.csl.api.OffsetRange;
  108.56 -import org.netbeans.modules.csl.api.Severity;
  108.57 -import org.netbeans.modules.csl.api.Error;
  108.58 -import org.netbeans.modules.csl.spi.DefaultError;
  108.59 -import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
  108.60 -import org.netbeans.modules.python.editor.PythonAstUtils;
  108.61 -import org.netbeans.modules.python.editor.PythonIndex;
  108.62 -import org.netbeans.modules.python.editor.PythonIndexer;
  108.63 -import org.netbeans.modules.python.editor.PythonParserResult;
  108.64 -import org.netbeans.modules.python.editor.PythonUtils;
  108.65 -import org.netbeans.modules.python.editor.elements.AstElement;
  108.66 -import org.netbeans.modules.python.editor.elements.Element;
  108.67 -import org.netbeans.modules.python.editor.elements.IndexedElement;
  108.68 -import org.netbeans.modules.python.editor.imports.ImportEntry;
  108.69 -import org.netbeans.modules.python.editor.imports.ImportManager;
  108.70 -import org.netbeans.modules.python.editor.lexer.PythonTokenId;
  108.71 -import org.openide.filesystems.FileObject;
  108.72 -import org.openide.filesystems.FileStateInvalidException;
  108.73 -import org.openide.filesystems.FileUtil;
  108.74 -import org.openide.util.Exceptions;
  108.75 -import org.python.antlr.PythonTree;
  108.76 -import org.python.antlr.Visitor;
  108.77 -import org.python.antlr.ast.Attribute;
  108.78 -import org.python.antlr.ast.ClassDef;
  108.79 -import org.python.antlr.ast.Expression;
  108.80 -import org.python.antlr.ast.FunctionDef;
  108.81 -import org.python.antlr.ast.GeneratorExp;
  108.82 -import org.python.antlr.ast.Import;
  108.83 -import org.python.antlr.ast.ImportFrom;
  108.84 -import org.python.antlr.ast.Interactive;
  108.85 -import org.python.antlr.ast.Lambda;
  108.86 -import org.python.antlr.ast.Name;
  108.87 -import org.python.antlr.ast.Str;
  108.88 -import org.python.antlr.ast.alias;
  108.89 -import org.python.antlr.base.expr;
  108.90 -import static org.netbeans.modules.python.editor.scopes.ScopeConstants.*;
  108.91 -
  108.92 -/**
  108.93 - * A symbol table tracks a bunch of scopes and can answer questions about defined
  108.94 - * symbols.
  108.95 - *
  108.96 - * Based on Jython's ScopeManager.
  108.97 - *
  108.98 - * @author Tor Norbye
  108.99 - */
 108.100 -public class SymbolTable {
 108.101 -    private final static int YES = 1;
 108.102 -    private final static int NO = 0;
 108.103 -    private final static int CIRCULAR = -1;
 108.104 -    private Map<PythonTree, ScopeInfo> scopes = new HashMap<>();
 108.105 -    private PythonTree root;
 108.106 -    private FileObject fileObject;
 108.107 -    private List<Import> imports = new ArrayList<>();
 108.108 -    private List<ImportFrom> importsFrom = new ArrayList<>();
 108.109 -    private List<PythonTree> mainImports = new ArrayList<>();
 108.110 -    private Set<PythonTree> topLevelImports = new HashSet<>();
 108.111 -    private List<Error> errors;
 108.112 -    /** List of symbols registered via __all__ = [ "foo", "bar" ] or __all__.extend() or __all__.append() */
 108.113 -    private List<Str> publicSymbols;
 108.114 -    private final static HashMap<String, String> classAttributes = new HashMap<String, String>() {
 108.115 -        {
 108.116 -            put("__class__", "__class__");
 108.117 -            put("__bases__", "__bases__");
 108.118 -            put("__dict__", "__dict__");
 108.119 -            put("__doc__", "__doc__");
 108.120 -            put("__name__", "__bases");
 108.121 -        }
 108.122 -    };
 108.123 -    private HashMap<String, ClassDef> classes = new HashMap<>();
 108.124 -    // TODO - use WeakHashMap?
 108.125 -    static Map<String, Set<IndexedElement>> importedElements = new HashMap<>();
 108.126 -
 108.127 -    private HashMap<String, ClassDef> buildLocalClasses() {
 108.128 -        HashMap<String, ClassDef> localClasses = new HashMap<>();
 108.129 -        for (PythonTree cur : scopes.keySet()) {
 108.130 -            if (cur instanceof ClassDef) {
 108.131 -                ClassDef curClass = (ClassDef)cur;
 108.132 -                localClasses.put(curClass.getInternalName(), curClass);
 108.133 -            }
 108.134 -        }
 108.135 -        return localClasses;
 108.136 -    }
 108.137 -
 108.138 -    public SymbolTable(PythonTree root, FileObject fileObject) {
 108.139 -        this.root = root;
 108.140 -        this.fileObject = fileObject;
 108.141 -
 108.142 -        if (root != null) {
 108.143 -            try {
 108.144 -                ScopesCompiler compiler = new ScopesCompiler(this, scopes, root, imports, importsFrom, mainImports, topLevelImports);
 108.145 -                compiler.parse();
 108.146 -                publicSymbols = compiler.getPublicSymbols();
 108.147 -                classes = buildLocalClasses();
 108.148 -                if (publicSymbols != null) {
 108.149 -                    // Mark all other symbols private!
 108.150 -                    Set<String> names = new HashSet<>(publicSymbols.size() + 1);
 108.151 -                    names.add("__all__"); // __all__ itself is exported!
 108.152 -                    for (Str str : publicSymbols) {
 108.153 -                        String name = PythonAstUtils.getStrContent(str);
 108.154 -                        if (name != null) {
 108.155 -                            names.add(name);
 108.156 -                        }
 108.157 -                    }
 108.158 -
 108.159 -                    ScopeInfo topScope = scopes.get(root);
 108.160 -                    if (topScope != null) {
 108.161 -                        for (Map.Entry<String, SymInfo> entry : topScope.tbl.entrySet()) {
 108.162 -                            String name = entry.getKey();
 108.163 -                            if (!names.contains(name)) {
 108.164 -                                SymInfo sym = entry.getValue();
 108.165 -                                sym.flags |= PRIVATE;
 108.166 -                                if (sym.isDef() && sym.node != null) {
 108.167 -                                    ScopeInfo scope = scopes.get(sym.node);
 108.168 -                                    scope.hidden = true;
 108.169 -                                }
 108.170 -                            }
 108.171 -                        }
 108.172 -                    }
 108.173 -
 108.174 -                    for (Map.Entry<PythonTree, ScopeInfo> entry : scopes.entrySet()) {
 108.175 -                        ScopeInfo scope = entry.getValue();
 108.176 -                        boolean isHidden = false;
 108.177 -                        ScopeInfo curr = scope;
 108.178 -                        while (curr != null) {
 108.179 -                            if (curr.hidden) {
 108.180 -                                isHidden = true;
 108.181 -                                break;
 108.182 -                            }
 108.183 -                            if (curr.nested != null) {
 108.184 -                                curr = curr.nested;
 108.185 -                            } else {
 108.186 -                                curr = curr.up;
 108.187 -                            }
 108.188 -
 108.189 -                        }
 108.190 -                        if (isHidden) {
 108.191 -                            scope.hidden = true;
 108.192 -                        }
 108.193 -                    }
 108.194 -
 108.195 -                    // Mark all symbols private, unless the scope is a direct descendant
 108.196 -                    // of a public symbol
 108.197 -                    for (ScopeInfo scope : scopes.values()) {
 108.198 -                        if (scope.hidden) {
 108.199 -                            for (SymInfo sym : scope.tbl.values()) {
 108.200 -                                sym.flags |= PRIVATE;
 108.201 -                            }
 108.202 -                        }
 108.203 -                    }
 108.204 -                }
 108.205 -            } catch (Exception ex) {
 108.206 -                Exceptions.printStackTrace(ex);
 108.207 -            }
 108.208 -        }
 108.209 -    }
 108.210 -
 108.211 -    public boolean isPrivate(PythonTree node, String name) {
 108.212 -        ScopeInfo scope = scopes.get(node);
 108.213 -        if (scope == null) {
 108.214 -            scope = scopes.get(root);
 108.215 -        }
 108.216 -        if (scope != null) {
 108.217 -            if (scope.up != null) {
 108.218 -                if (scope.hidden) {
 108.219 -                    return true;
 108.220 -                }
 108.221 -                // Look in parent's scope table
 108.222 -                if (scope.nested != null) {
 108.223 -                    scope = scope.nested;
 108.224 -                } else {
 108.225 -                    scope = scope.up;
 108.226 -                }
 108.227 -                if (scope != null) {
 108.228 -                    SymInfo sym = scope.tbl.get(name);
 108.229 -                    if (sym != null) {
 108.230 -                        return sym.isPrivate();
 108.231 -                    }
 108.232 -                }
 108.233 -            } else {
 108.234 -                SymInfo sym = scope.tbl.get(name);
 108.235 -                if (sym != null) {
 108.236 -                    return sym.isPrivate();
 108.237 -                }
 108.238 -            }
 108.239 -        }
 108.240 -
 108.241 -        return false;
 108.242 -    }
 108.243 -
 108.244 -    public SymInfo findDeclaration(PythonTree scope, String name, boolean allowFree) {
 108.245 -        ScopeInfo scopeInfo = getScopeInfo(scope);
 108.246 -        if (scopeInfo != null) {
 108.247 -            SymInfo sym = scopeInfo.tbl.get(name);
 108.248 -            SymInfo orig = sym;
 108.249 -            while (sym != null && sym.isFree()) {
 108.250 -                scopeInfo = scopeInfo.up;
 108.251 -                while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 108.252 -                    scopeInfo = scopeInfo.up;
 108.253 -                }
 108.254 -                sym = scopeInfo.tbl.get(name);
 108.255 -            }
 108.256 -
 108.257 -            if (allowFree && sym == null && orig != null) {
 108.258 -                // Free variable -- might have to resolve it
 108.259 -                return orig;
 108.260 -            }
 108.261 -
 108.262 -            // Look for attributes too
 108.263 -            if (sym == null) {
 108.264 -                sym = scopeInfo.attributes.get(name);
 108.265 -                orig = sym;
 108.266 -                while (sym != null && sym.isFree()) {
 108.267 -                    scopeInfo = scopeInfo.up;
 108.268 -                    while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 108.269 -                        scopeInfo = scopeInfo.up;
 108.270 -                    }
 108.271 -                    sym = scopeInfo.tbl.get(name);
 108.272 -                }
 108.273 -
 108.274 -                if (allowFree && sym == null && orig != null) {
 108.275 -                    // Free variable -- might have to resolve it
 108.276 -                    return orig;
 108.277 -                }
 108.278 -            }
 108.279 -
 108.280 -            return sym;
 108.281 -        }
 108.282 -
 108.283 -        return null;
 108.284 -    }
 108.285 -
 108.286 -    public ScopeInfo getScopeInfo(PythonTree node) {
 108.287 -        return scopes.get(node);
 108.288 -    }
 108.289 -
 108.290 -    public List<Error> getErrors() {
 108.291 -        return errors != null ? errors : Collections.<Error>emptyList();
 108.292 -    }
 108.293 -
 108.294 -    public SymInfo findBySignature(ElementKind kind, String signature) {
 108.295 -        PythonTree scope = root;
 108.296 -        String name = signature;
 108.297 -        int dot = signature.lastIndexOf('.');
 108.298 -        if (dot != -1) {
 108.299 -            String clz = signature.substring(0, dot);
 108.300 -            name = signature.substring(dot + 1);
 108.301 -            SymInfo sym = findDeclaration(root, clz, true);
 108.302 -            if (sym != null && sym.node != null) {
 108.303 -                scope = sym.node;
 108.304 -            }
 108.305 -        }
 108.306 -        SymInfo sym = findDeclaration(scope, name, true);
 108.307 -
 108.308 -        return sym;
 108.309 -    }
 108.310 -
 108.311 -    private List<String> getModulesToStarImport() {
 108.312 -        List<String> modules = new ArrayList<>();
 108.313 -
 108.314 -        for (ImportFrom from : importsFrom) {
 108.315 -            List<alias> names = from.getInternalNames();
 108.316 -            if (names != null) {
 108.317 -                for (alias at : names) {
 108.318 -                    if ("*".equals(at.getInternalName())) { // NOI18N
 108.319 -                        modules.add(from.getInternalModule());
 108.320 -                    }
 108.321 -                }
 108.322 -            }
 108.323 -        }
 108.324 -
 108.325 -        modules.addAll(PythonIndex.BUILTIN_MODULES);
 108.326 -
 108.327 -        return modules;
 108.328 -    }
 108.329 -
 108.330 -    private void addSymbolsFromModule(PythonParserResult info, String module, String prefix, QuerySupport.Kind kind, Set<? super IndexedElement> result) {
 108.331 -        if (PythonIndex.isBuiltinModule(module)) {
 108.332 -            Set<IndexedElement> all = getAllSymbolsFromModule(info, module);
 108.333 -            for (IndexedElement e : all) {
 108.334 -                if (kind == QuerySupport.Kind.PREFIX) {
 108.335 -                    if (e.getName().startsWith(prefix)) {
 108.336 -                        result.add(e);
 108.337 -                    }
 108.338 -                } else if (kind == QuerySupport.Kind.EXACT) {
 108.339 -                    if (prefix.equals(e.getName())) {
 108.340 -                        result.add(e);
 108.341 -                    }
 108.342 -                } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX) {
 108.343 -                    if (e.getName().regionMatches(true, 0, prefix, 0, prefix.length())) {
 108.344 -                        result.add(e);
 108.345 -                    }
 108.346 -                }
 108.347 -            }
 108.348 -        } else {
 108.349 -            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 108.350 -            Set<IndexedElement> elements = index.getImportedElements(prefix, kind, Collections.singleton(module), null);
 108.351 -            for (IndexedElement e : elements) {
 108.352 -                result.add(e);
 108.353 -            }
 108.354 -        }
 108.355 -    }
 108.356 -
 108.357 -    private Set<IndexedElement> getAllSymbolsFromModule(PythonParserResult info, String module) {
 108.358 -        Set<IndexedElement> elements = importedElements.get(module);
 108.359 -        if (elements == null) {
 108.360 -            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 108.361 -            Set<String> systemHolder = new HashSet<>(3);
 108.362 -            elements = index.getImportedElements("", QuerySupport.Kind.PREFIX, Collections.singleton(module), systemHolder);
 108.363 -            // Cache system modules - don't cache local modules
 108.364 -            if (!systemHolder.isEmpty()) {
 108.365 -                importedElements.put(module, elements);
 108.366 -            }
 108.367 -        }
 108.368 -
 108.369 -        return elements;
 108.370 -    }
 108.371 -
 108.372 -    public Set<Element> getDefinedElements(PythonParserResult info, PythonTree scope, String prefix, QuerySupport.Kind kind) {
 108.373 -        Set<Element> elements = new HashSet<>(300);
 108.374 -        ScopeInfo scopeInfo = scopes.get(scope);
 108.375 -        String module = PythonUtils.getModuleName(fileObject);
 108.376 -        String url = fileObject.toURL().toExternalForm();
 108.377 -
 108.378 -        // Get builtin symbols
 108.379 -        for (String mod : getModulesToStarImport()) {
 108.380 -            addSymbolsFromModule(info, mod, prefix, kind, elements);
 108.381 -        }
 108.382 -
 108.383 -        // I can't just search the scope table for all variables in scope because this
 108.384 -        // will only include the local -bound- variables and the -used- free variables.
 108.385 -        // I need to find potential free variables as well. This means I should walk up
 108.386 -        // the scope chain and compute all eligible names. By keep track of the ones I've
 108.387 -        // already added I avoid adding references to variables I have re-bound in closer
 108.388 -        // scopes.
 108.389 -
 108.390 -        Set<String> added = new HashSet<>();
 108.391 -
 108.392 -        while (scopeInfo != null) {
 108.393 -            for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 108.394 -                String name = entry.getKey();
 108.395 -                if (added.contains(name)) {
 108.396 -                    // Something in narrower scope already processed this one
 108.397 -                    continue;
 108.398 -                }
 108.399 -                if (kind == QuerySupport.Kind.EXACT) {
 108.400 -                    if (!(name.equals(prefix))) {
 108.401 -                        continue;
 108.402 -                    }
 108.403 -                } else if (kind == QuerySupport.Kind.PREFIX) {
 108.404 -                    if (!name.startsWith(prefix)) {
 108.405 -                        continue;
 108.406 -                    }
 108.407 -                } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX) {
 108.408 -                    if (!name.regionMatches(true, 0, prefix, 0, prefix.length())) {
 108.409 -                        continue;
 108.410 -                    }
 108.411 -                }
 108.412 -                SymInfo sym = entry.getValue();
 108.413 -
 108.414 -                ScopeInfo curr = scopeInfo;
 108.415 -                while (sym != null && sym.isFree()) {
 108.416 -                    curr = curr.up;
 108.417 -                    while (curr != null && curr.kind == CLASSSCOPE) {
 108.418 -                        curr = curr.up;
 108.419 -                    }
 108.420 -                    if (curr == null) {
 108.421 -                        sym = null;
 108.422 -                        break;
 108.423 -                    }
 108.424 -                    sym = scopeInfo.tbl.get(name);
 108.425 -                }
 108.426 -                if (sym == null) {
 108.427 -                    continue;
 108.428 -                }
 108.429 -                if (sym.isUnresolved()) {
 108.430 -                    // Don't add completion items for stuff we're not sure about
 108.431 -                    continue;
 108.432 -                }
 108.433 -
 108.434 -                PythonTree node = sym.node;
 108.435 -                if (node == null) {
 108.436 -                    continue;
 108.437 -                }
 108.438 -
 108.439 -
 108.440 -                if (sym.isImported()) {
 108.441 -                    Element element = new AstElement(this, node, name, Character.isUpperCase(name.charAt(0)) ? ElementKind.CLASS : ElementKind.MODULE);
 108.442 -                    elements.add(element);
 108.443 -                } else if (sym.isDef()) {
 108.444 -                    String signature;
 108.445 -                    if (sym.isClass() && node instanceof ClassDef) {
 108.446 -                        signature = PythonIndexer.computeClassSig((ClassDef)node, sym);
 108.447 -                    } else if (sym.isFunction() && node instanceof FunctionDef) {
 108.448 -                        assert sym.isFunction() && node instanceof FunctionDef : name + ";" + sym + " in " + module;
 108.449 -                        signature = PythonIndexer.computeFunctionSig(name, (FunctionDef)node, sym);
 108.450 -                    } else {
 108.451 -                        // Probably a generator expression
 108.452 -                        continue;
 108.453 -                    }
 108.454 -                    //Element element = AstElement.create(null, node);
 108.455 -                    IndexedElement element = IndexedElement.create(signature, module, url, null);
 108.456 -                    element.setSmart(true);
 108.457 -                    elements.add(element);
 108.458 -                } else {
 108.459 -                    // TODO - class attributes?
 108.460 -                    Element element = new AstElement(this, node, name, ElementKind.VARIABLE);
 108.461 -                    elements.add(element);
 108.462 -                }
 108.463 -
 108.464 -                added.add(name);
 108.465 -            }
 108.466 -
 108.467 -            scopeInfo = scopeInfo.up;
 108.468 -            while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 108.469 -                scopeInfo = scopeInfo.up;
 108.470 -            }
 108.471 -        }
 108.472 -
 108.473 -        return elements;
 108.474 -    }
 108.475 -
 108.476 -    // Return all node references to the given name
 108.477 -    // This will include imports, calls, definitions, etc.
 108.478 -    public List<PythonTree> getOccurrences(PythonTree scope, String name, boolean abortOnFree) {
 108.479 -        ScopeInfo scopeInfo = scopes.get(scope);
 108.480 -        if (scopeInfo != null) {
 108.481 -            SymInfo sym = scopeInfo.tbl.get(name);
 108.482 -            while (sym != null && sym.isFree()) {
 108.483 -                if (abortOnFree) {
 108.484 -                    return null;
 108.485 -                }
 108.486 -                scopeInfo = scopeInfo.up;
 108.487 -                while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 108.488 -                    scopeInfo = scopeInfo.up;
 108.489 -                }
 108.490 -                sym = scopeInfo.tbl.get(name);
 108.491 -            }
 108.492 -
 108.493 -            if (sym != null) {
 108.494 -                NameNodeFinder finder = new NameNodeFinder(name, scopeInfo.scope_node);
 108.495 -                finder.run();
 108.496 -                return finder.getNodes();
 108.497 -            }
 108.498 -        }
 108.499 -
 108.500 -        return Collections.emptyList();
 108.501 -    }
 108.502 -
 108.503 -    /** Return a list of the variables visible from a given scope */
 108.504 -    public Set<String> getVarNames(PythonTree scope, boolean mustBeBound) {
 108.505 -        ScopeInfo scopeInfo = scopes.get(scope);
 108.506 -        Set<String> names = new HashSet<>();
 108.507 -        while (scopeInfo != null) {
 108.508 -            for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 108.509 -                String name = entry.getKey();
 108.510 -                SymInfo sym = entry.getValue();
 108.511 -                if (sym.isVariable(mustBeBound)) {
 108.512 -                    names.add(name);
 108.513 -                }
 108.514 -            }
 108.515 -            scopeInfo = scopeInfo.up;
 108.516 -            while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 108.517 -                scopeInfo = scopeInfo.up;
 108.518 -            }
 108.519 -        }
 108.520 -
 108.521 -        return names;
 108.522 -    }
 108.523 -
 108.524 -    public List<ImportEntry> getUnusedImports() {
 108.525 -        List<ImportEntry> unused = new ArrayList<>();
 108.526 -        ScopeInfo scopeInfo = scopes.get(root);
 108.527 -        for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 108.528 -            SymInfo sym = entry.getValue();
 108.529 -            if (sym.isImported() && !sym.isRead()) {
 108.530 -                String name = entry.getKey();
 108.531 -                if (name.equals("*")) { // NOI18N
 108.532 -                    // Not detecting usages of wildcard imports yet...
 108.533 -                    continue;
 108.534 -                }
 108.535 -                PythonTree node = sym.node;
 108.536 -                if (node instanceof Import) {
 108.537 -                    Import imp = (Import)node;
 108.538 -                    int ordinal = 0;
 108.539 -                    String module = null;
 108.540 -                    String asName = null;
 108.541 -                    List<alias> names = imp.getInternalNames();
 108.542 -                    if (names != null) {
 108.543 -                        for (alias at : names) {
 108.544 -                            if (name.equals(at.getInternalAsname())) {
 108.545 -                                module = at.getInternalName();
 108.546 -                                asName = at.getInternalAsname();
 108.547 -                                break;
 108.548 -                            } else if (name.equals(at.getInternalName())) {
 108.549 -                                module = at.getInternalName();
 108.550 -                                break;
 108.551 -                            }
 108.552 -                        }
 108.553 -                        if (module == null) {
 108.554 -                            // For imports with dotted names, like wsgiref.handlers,
 108.555 -                            // the symbol table entry is just "wsgiref", yet I have to match
 108.556 -                            // the symbols, so try again more carefully
 108.557 -                            for (alias at : names) {
 108.558 -                                if (at.getInternalAsname() != null && at.getInternalAsname().startsWith(name) &&
 108.559 -                                        at.getInternalAsname().charAt(name.length()) == '.') {
 108.560 -                                    module = at.getInternalName();
 108.561 -                                    asName = at.getInternalAsname();
 108.562 -                                    break;
 108.563 -                                } else if (at.getInternalName().startsWith(name) &&
 108.564 -                                        at.getInternalName().charAt(name.length()) == '.') {
 108.565 -                                    module = at.getInternalName();
 108.566 -                                    break;
 108.567 -                                }
 108.568 -                            }
 108.569 -                        }
 108.570 -                    }
 108.571 -                    unused.add(new ImportEntry(module, asName, true, imp, imp.getCharStartIndex() + (ordinal++)));
 108.572 -                } else if (node instanceof ImportFrom) {
 108.573 -                    ImportFrom imp = (ImportFrom)node;
 108.574 -                    if (ImportManager.isFutureImport(imp)) {
 108.575 -                        continue;
 108.576 -                    }
 108.577 -                    String module = imp.getInternalModule();
 108.578 -                    String origName = null;
 108.579 -                    String asName = null;
 108.580 -                    int ordinal = 0;
 108.581 -                    List<alias> names = imp.getInternalNames();
 108.582 -                    if (names != null) {
 108.583 -                        for (alias at : names) {
 108.584 -                            if (name.equals(at.getInternalAsname())) {
 108.585 -                                origName = at.getInternalName();
 108.586 -                                asName = at.getInternalAsname();
 108.587 -                                break;
 108.588 -                            } else if (name.equals(at.getInternalName())) {
 108.589 -                                origName = at.getInternalName();
 108.590 -                                break;
 108.591 -                            }
 108.592 -                        }
 108.593 -                        if (origName == null) {
 108.594 -                            // For imports with dotted names, like wsgiref.handlers,
 108.595 -                            // the symbol table entry is just "wsgiref", yet I have to match
 108.596 -                            // the symbols, so try again more carefully
 108.597 -                            for (alias at : names) {
 108.598 -                                if (at.getInternalAsname() != null && at.getInternalAsname().startsWith(name) &&
 108.599 -                                        at.getInternalAsname().charAt(name.length()) == '.') {
 108.600 -                                    origName = at.getInternalName();
 108.601 -                                    asName = at.getInternalAsname();
 108.602 -                                    break;
 108.603 -                                } else if (at.getInternalName().startsWith(name) &&
 108.604 -                                        at.getInternalName().charAt(name.length()) == '.') {
 108.605 -                                    origName = at.getInternalName();
 108.606 -                                    break;
 108.607 -                                }
 108.608 -                            }
 108.609 -                        }
 108.610 -                    }
 108.611 -                    unused.add(new ImportEntry(module, origName, asName, true, imp, imp.getCharStartIndex() + (ordinal++)));
 108.612 -                }
 108.613 -            }
 108.614 -        }
 108.615 -
 108.616 -        return unused;
 108.617 -    }
 108.618 -
 108.619 -    private class NameNodeFinder extends Visitor {
 108.620 -        private List<PythonTree> nodes = new ArrayList<>();
 108.621 -        private PythonTree startScope;
 108.622 -        private String name;
 108.623 -
 108.624 -        public NameNodeFinder(String name, PythonTree startScope) {
 108.625 -            this.name = name;
 108.626 -            this.startScope = startScope;
 108.627 -        }
 108.628 -
 108.629 -        public void run() {
 108.630 -            try {
 108.631 -                visit(startScope);
 108.632 -            } catch (Exception ex) {
 108.633 -                Exceptions.printStackTrace(ex);
 108.634 -            }
 108.635 -        }
 108.636 -
 108.637 -        @Override
 108.638 -        public Object visitImport(Import imp) throws Exception {
 108.639 -            List<alias> names = imp.getInternalNames();
 108.640 -            if (names != null && names.size() > 0) {
 108.641 -                boolean found = false;
 108.642 -                for (alias at : names) {
 108.643 -                    String asName = at.getInternalAsname();
 108.644 -                    if (asName != null) {
 108.645 -                        if (name.equals(asName)) {
 108.646 -                            found = true;
 108.647 -                            break;
 108.648 -                        }
 108.649 -                    } else if (name.equals(at.getInternalName())) {
 108.650 -                        found = true;
 108.651 -                        break;
 108.652 -                    }
 108.653 -                }
 108.654 -                if (found) {
 108.655 -                    nodes.add(imp);
 108.656 -                }
 108.657 -            }
 108.658 -            return super.visitImport(imp);
 108.659 -        }
 108.660 -
 108.661 -        @Override
 108.662 -        public Object visitImportFrom(ImportFrom imp) throws Exception {
 108.663 -            List<alias> names = imp.getInternalNames();
 108.664 -            if (names != null && names.size() > 0) {
 108.665 -                boolean found = false;
 108.666 -                for (alias at : names) {
 108.667 -                    String asName = at.getInternalAsname();
 108.668 -                    if (asName != null) {
 108.669 -                        if (name.equals(asName)) {
 108.670 -                            found = true;
 108.671 -                            break;
 108.672 -                        }
 108.673 -                    } else if (name.equals(at.getInternalName())) {
 108.674 -                        found = true;
 108.675 -                        break;
 108.676 -                    }
 108.677 -                }
 108.678 -                if (found) {
 108.679 -                    nodes.add(imp);
 108.680 -                }
 108.681 -            }
 108.682 -
 108.683 -            return super.visitImportFrom(imp);
 108.684 -        }
 108.685 -
 108.686 -        @Override
 108.687 -        public Object visitName(Name node) throws Exception {
 108.688 -            if (node.getInternalId().equals(name)) {
 108.689 -                nodes.add(node);
 108.690 -            }
 108.691 -            return super.visitName(node);
 108.692 -        }
 108.693 -
 108.694 -        @Override
 108.695 -        public Object visitFunctionDef(FunctionDef node) throws Exception {
 108.696 -            if (name.equals(node.getInternalName())) {
 108.697 -                nodes.add(node);
 108.698 -            }
 108.699 -
 108.700 -            if (isIncludedScope(node)) {
 108.701 -                return super.visitFunctionDef(node);
 108.702 -            } else {
 108.703 -                return null;
 108.704 -            }
 108.705 -        }
 108.706 -
 108.707 -        @Override
 108.708 -        public Object visitClassDef(ClassDef node) throws Exception {
 108.709 -            if (name.equals(node.getInternalName())) {
 108.710 -                nodes.add(node);
 108.711 -            }
 108.712 -
 108.713 -            if (isIncludedScope(node)) {
 108.714 -                return super.visitClassDef(node);
 108.715 -            } else {
 108.716 -                return null;
 108.717 -            }
 108.718 -        }
 108.719 -
 108.720 -        @Override
 108.721 -        public Object visitExpression(Expression node) throws Exception {
 108.722 -            if (isIncludedScope(node)) {
 108.723 -                return super.visitExpression(node);
 108.724 -            } else {
 108.725 -                return null;
 108.726 -            }
 108.727 -        }
 108.728 -
 108.729 -        @Override
 108.730 -        public Object visitInteractive(Interactive node) throws Exception {
 108.731 -            if (isIncludedScope(node)) {
 108.732 -                return super.visitInteractive(node);
 108.733 -            } else {
 108.734 -                return null;
 108.735 -            }
 108.736 -        }
 108.737 -
 108.738 -        @Override
 108.739 -        public Object visitLambda(Lambda node) throws Exception {
 108.740 -            if (isIncludedScope(node)) {
 108.741 -                return super.visitLambda(node);
 108.742 -            } else {
 108.743 -                return null;
 108.744 -            }
 108.745 -        }
 108.746 -
 108.747 -        @Override
 108.748 -        public Object visitGeneratorExp(GeneratorExp node) throws Exception {
 108.749 -            if (isIncludedScope(node)) {
 108.750 -                return super.visitGeneratorExp(node);
 108.751 -            } else {
 108.752 -                return null;
 108.753 -            }
 108.754 -        }
 108.755 -
 108.756 -        private boolean isIncludedScope(PythonTree node) {
 108.757 -            if (node == startScope) {
 108.758 -                return true;
 108.759 -            }
 108.760 -
 108.761 -            ScopeInfo info = scopes.get(node);
 108.762 -            if (info == null) {
 108.763 -                return false;
 108.764 -            }
 108.765 -
 108.766 -            SymInfo sym = info.tbl.get(name);
 108.767 -            // Skip scopes that redefine the variable
 108.768 -            if (sym != null && sym.isBound()) {
 108.769 -                return false;
 108.770 -            }
 108.771 -
 108.772 -            return true;
 108.773 -        }
 108.774 -
 108.775 -        public List<PythonTree> getNodes() {
 108.776 -            return nodes;
 108.777 -        }
 108.778 -    }
 108.779 -
 108.780 -    public Map<String, SymInfo> getUnresolvedNames(PythonParserResult info) {
 108.781 -        Map<String, SymInfo> unresolved = new HashMap<>();
 108.782 -        Set<String> builtin = getBuiltin(info);
 108.783 -
 108.784 -        for (ScopeInfo scopeInfo : scopes.values()) {
 108.785 -            Map<String, SymInfo> tbl = scopeInfo.tbl;
 108.786 -            for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
 108.787 -                SymInfo symInfo = entry.getValue();
 108.788 -                boolean isUnresolved = symInfo.isUnresolved();
 108.789 -                if (!isUnresolved && symInfo.isFree()) {
 108.790 -                    // Peek up scope stack
 108.791 -                    String name = entry.getKey();
 108.792 -                    SymInfo sym = symInfo;
 108.793 -                    ScopeInfo scope = scopeInfo;
 108.794 -                    while (sym != null && sym.isFree()) {
 108.795 -                        scope = scope.up;
 108.796 -                        while (scope != null && scope.kind == CLASSSCOPE) {
 108.797 -                            scope = scope.up;
 108.798 -                        }
 108.799 -                        sym = scope.tbl.get(name);
 108.800 -                    }
 108.801 -                    if (sym == null) {
 108.802 -                        isUnresolved = true;
 108.803 -                    } else {
 108.804 -                        isUnresolved = sym.isUnresolved();
 108.805 -                    }
 108.806 -                }
 108.807 -                if (isUnresolved) {
 108.808 -                    String key = entry.getKey();
 108.809 -                    if (!builtin.contains(key)) {
 108.810 -                        unresolved.put(key, symInfo);
 108.811 -                    }
 108.812 -                }
 108.813 -            }
 108.814 -        }
 108.815 -
 108.816 -        return unresolved;
 108.817 -    }
 108.818 -
 108.819 -    public List<Attribute> getNotInInitAttributes(PythonParserResult info) {
 108.820 -        List<Attribute> notInInitAttribs = new ArrayList<>();
 108.821 -        for (ScopeInfo scopeInfo : scopes.values()) {
 108.822 -            if (scopeInfo.scope_node instanceof ClassDef) {
 108.823 -                if (scopeInfo.attributes != null) {
 108.824 -                    for (Map.Entry<String, SymInfo> entry : scopeInfo.attributes.entrySet()) {
 108.825 -                        SymInfo symInfo = entry.getValue();
 108.826 -                        if (!symInfo.isBoundInConstructor()) {
 108.827 -                            notInInitAttribs.add((Attribute)symInfo.node);
 108.828 -                        }
 108.829 -                    }
 108.830 -                }
 108.831 -            }
 108.832 -        }
 108.833 -        return notInInitAttribs;
 108.834 -    }
 108.835 -
 108.836 -    private ScopeInfo getClassScope(String className) {
 108.837 -        for (ScopeInfo scopeInfo : scopes.values()) {
 108.838 -            if (scopeInfo.scope_node instanceof ClassDef) {
 108.839 -                ClassDef curClass = (ClassDef)scopeInfo.scope_node;
 108.840 -                if (curClass.getInternalName().equals(className)) {
 108.841 -                    return scopeInfo;
 108.842 -                }
 108.843 -            }
 108.844 -        }
 108.845 -        return null;
 108.846 -    }
 108.847 -
 108.848 -    private int belongsToParents(ClassDef cls, String name, HashMap<String, String> cycling) {
 108.849 -        List<expr> bases = cls.getInternalBases();
 108.850 -        if (bases == null || bases.size() == 0) {
 108.851 -            return NO; // no parents
 108.852 -        }
 108.853 -        for (expr base : bases) {
 108.854 -            String className = null;
 108.855 -            if (base instanceof Name) {
 108.856 -                className = ((Name)base).getInternalId();
 108.857 -            } else {
 108.858 -                // should be Attribute here( module.className form )
 108.859 -                // which imply imported from external scope
 108.860 -                // So we give up on scope returning optimistaically True
 108.861 -                return YES;
 108.862 -            }
 108.863 -            assert (className != null);
 108.864 -            if (cycling.get(className) != null) {
 108.865 -                cycling.clear();
 108.866 -                // put parent child conficting back in cycling
 108.867 -                cycling.put(className, cls.getInternalName());
 108.868 -                return CIRCULAR;
 108.869 -            }
 108.870 -            cycling.put(className, className);
 108.871 -            ScopeInfo localClassScope = getClassScope(className);
 108.872 -            if (localClassScope == null) {
 108.873 -                // return true (success) when at least one parent is outside module scope
 108.874 -                // just to notify caller to be optimistic and assume that
 108.875 -                // name is resolved by imported classes inheritance
 108.876 -                // scanning imported classed from here is discouraged for
 108.877 -                // performances reasons
 108.878 -                return YES;
 108.879 -            } else {
 108.880 -                if ((name != null) &&
 108.881 -                        (localClassScope.attributes.get(name) != null)) {
 108.882 -                    return YES;
 108.883 -                }
 108.884 -                // try recurse parentage to resolve attribute
 108.885 -                ClassDef parentClass = (ClassDef)localClassScope.scope_node;
 108.886 -                int recResult = belongsToParents(parentClass, name, cycling);
 108.887 -                if (recResult != NO) // stop on FOUND(YES) or CIRCULAR error
 108.888 -                {
 108.889 -                    return recResult;
 108.890 -                }
 108.891 -            }
 108.892 -        }
 108.893 -        return NO;
 108.894 -    }
 108.895 -
 108.896 -    private boolean isImported(String moduleName) {
 108.897 -        for (Import imported : imports) {
 108.898 -            List<alias> names = imported.getInternalNames();
 108.899 -            if (names != null) {
 108.900 -                for (alias cur : names) {
 108.901 -                    String name = cur.getInternalName();
 108.902 -                    String asName = cur.getInternalAsname();
 108.903 -                    if (((name != null) && (name.equals(moduleName))) ||
 108.904 -                            ((asName != null) && (asName.equals(moduleName)))) {
 108.905 -                        return true;
 108.906 -                    }
 108.907 -                }
 108.908 -            }
 108.909 -        }
 108.910 -        return false;
 108.911 -    }
 108.912 -
 108.913 -    private boolean isImportedFrom(String className) {
 108.914 -        for (ImportFrom importedFrom : importsFrom) {
 108.915 -            List<alias> names = importedFrom.getInternalNames();
 108.916 -            if (names != null) {
 108.917 -                for (alias cur : names) {
 108.918 -                    String name = cur.getInternalName();
 108.919 -                    String asName = cur.getInternalAsname();
 108.920 -                    if (((name != null) && (name.equals(className))) ||
 108.921 -                            ((asName != null) && (asName.equals(className)))) {
 108.922 -                        return true;
 108.923 -                    }
 108.924 -                }
 108.925 -            }
 108.926 -        }
 108.927 -        return false;
 108.928 -    }
 108.929 -
 108.930 -    public List<PythonTree> getUnresolvedParents(PythonParserResult info) {
 108.931 -        // deal with unresolved parents in inherit trees
 108.932 -        List<PythonTree> unresolvedParents = new ArrayList<>();
 108.933 -        PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 108.934 -
 108.935 -        for (String cur : classes.keySet()) {
 108.936 -            ClassDef cls = classes.get(cur);
 108.937 -            List<expr> bases = cls.getInternalBases();
 108.938 -            if (bases == null || bases.size() > 0) {
 108.939 -                // has parents
 108.940 -                for (expr base : bases) {
 108.941 -                    if (base instanceof Name) {
 108.942 -                        String className = ((Name)base).getInternalId();
 108.943 -                        Set<String> builtin = getBuiltin(info);
 108.944 -                        if ((!classes.containsKey(className)) &&
 108.945 -                                (!builtin.contains(className))) {
 108.946 -                            // check in from imports
 108.947 -                            if (!isImportedFrom(className)) {
 108.948 -                                unresolvedParents.add(base);
 108.949 -                            }
 108.950 -                        }
 108.951 -                    } else {
 108.952 -                        // should be Attribute here( module.className form )
 108.953 -                        // which imply imported from external scope
 108.954 -                        Attribute attr = (Attribute)base;
 108.955 -                        String clsName = attr.getInternalAttr();
 108.956 -                        if (attr.getInternalValue() instanceof Name) {
 108.957 -                            String moduleName = ((Name)(attr.getInternalValue())).getInternalId();
 108.958 -                            // check that import is resolved first
 108.959 -                            if (!isImported(moduleName)) {
 108.960 -                                unresolvedParents.add(base);
 108.961 -                            } else {
 108.962 -                                Set<IndexedElement> found = index.getImportedElements(clsName, QuerySupport.Kind.EXACT, Collections.<String>singleton(moduleName), null);
 108.963 -                                if (found.size() == 0) {
 108.964 -                                    unresolvedParents.add(base);
 108.965 -                                }
 108.966 -                            }
 108.967 -                        } else {
 108.968 -                            unresolvedParents.add(base);
 108.969 -                        }
 108.970 -                    }
 108.971 -                }
 108.972 -            }
 108.973 -        }
 108.974 -        return unresolvedParents;
 108.975 -    }
 108.976 -
 108.977 -    public HashMap<ClassDef, String> getClassesCyclingRedundancies(PythonParserResult info) {
 108.978 -        HashMap<ClassDef, String> cyclingRedundancies = new HashMap<>();
 108.979 -        for (String cur : classes.keySet()) {
 108.980 -            HashMap<String, String> returned = new HashMap<>();
 108.981 -            ClassDef curClass = classes.get(cur);
 108.982 -            if (!cyclingRedundancies.containsKey(curClass)) {
 108.983 -                if (belongsToParents(curClass, null, returned) == CIRCULAR) {
 108.984 -                    // store hashMap returned
 108.985 -                    Map.Entry<String, String> cycling = returned.entrySet().iterator().next();
 108.986 -                    cyclingRedundancies.put(curClass, cycling.getKey());
 108.987 -                }
 108.988 -            }
 108.989 -        }
 108.990 -        return cyclingRedundancies;
 108.991 -    }
 108.992 -
 108.993 -    public List<PythonTree> getUnresolvedAttributes(PythonParserResult info) {
 108.994 -        List<PythonTree> unresolvedNodes = new ArrayList<>();
 108.995 -        for (ScopeInfo scopeInfo : scopes.values()) {
 108.996 -            Set<String> unresolved = new HashSet<>();
 108.997 -            Map<String, SymInfo> tbl = scopeInfo.tbl;
 108.998 -            // unresolved attributes in local classes
 108.999 -            Map<String, SymInfo> attribs = scopeInfo.attributes;
108.1000 -            for (Map.Entry<String, SymInfo> curAttr : attribs.entrySet()) {
108.1001 -                SymInfo symInfo = curAttr.getValue();
108.1002 -                if (symInfo.isRead()) {
108.1003 -                    // check for builtin attribs first
108.1004 -                    if (classAttributes.get(curAttr.getKey()) == null) {
108.1005 -                        // not a builtin attribute
108.1006 -                        ScopeInfo parentScope = scopeInfo.getClassScope();
108.1007 -                        if (parentScope != null) {
108.1008 -                            // limit scope to Classes for self and inherited
108.1009 -                            Map<String, SymInfo> parentattribs = parentScope.attributes;
108.1010 -                            SymInfo classAttr = parentattribs.get(curAttr.getKey());
108.1011 -                            tbl = parentScope.tbl;
108.1012 -                            if (classAttr == null) {
108.1013 -                                // may be  also a reference to a method
108.1014 -                                classAttr = tbl.get(curAttr.getKey());
108.1015 -                            }
108.1016 -                            if (classAttr == null) {
108.1017 -                                // do not bother with method since they are
108.1018 -                                // managed by completion
108.1019 -                                ClassDef curClass = (ClassDef)parentScope.scope_node;
108.1020 -                                if (belongsToParents(curClass, curAttr.getKey(), new HashMap()) == NO) {
108.1021 -                                    if (!symInfo.isCalled()) {
108.1022 -                                        // no corresponding attributes
108.1023 -                                        //PythonTree tree = symInfo.node ;
108.1024 -                                        Attribute attr = (Attribute)symInfo.node;
108.1025 -                                        // Name name = new Name(tree.getToken(),attr.getInternalAttr(),attr.ctx) ;
108.1026 -                                        unresolvedNodes.add(attr);
108.1027 -                                    }
108.1028 -                                }
108.1029 -                            }
108.1030 -                        }
108.1031 -                    }
108.1032 -                }
108.1033 -            }
108.1034 -            if (unresolved.size() > 0) {
108.1035 -                NameFinder finder = new NameFinder(unresolved);
108.1036 -                List<Name> nodes = finder.run(scopeInfo.scope_node);
108.1037 -                unresolvedNodes.addAll(nodes);
108.1038 -            }
108.1039 -
108.1040 -        }
108.1041 -
108.1042 -        if (unresolvedNodes.size() > 1) {
108.1043 -            Collections.sort(unresolvedNodes, PythonUtils.ATTRIBUTE_NAME_NODE_COMPARATOR);
108.1044 -            //Collections.sort(unusedNodes, PythonUtils.NODE_POS_COMPARATOR);
108.1045 -        }
108.1046 -
108.1047 -        return unresolvedNodes;
108.1048 -    }
108.1049 -
108.1050 -    public List<PythonTree> getUnresolved(PythonParserResult info) {
108.1051 -        List<PythonTree> unresolvedNodes = new ArrayList<>();
108.1052 -        Set<String> builtin = getBuiltin(info);
108.1053 -
108.1054 -        for (ScopeInfo scopeInfo : scopes.values()) {
108.1055 -            Set<String> unresolved = new HashSet<>();
108.1056 -            Map<String, SymInfo> tbl = scopeInfo.tbl;
108.1057 -            for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
108.1058 -                SymInfo symInfo = entry.getValue();
108.1059 -                boolean isUnresolved = symInfo.isUnresolved();
108.1060 -                if (!isUnresolved && symInfo.isFree()) {
108.1061 -                    // Peek up scope stack
108.1062 -                    String name = entry.getKey();
108.1063 -                    SymInfo sym = symInfo;
108.1064 -                    ScopeInfo scope = scopeInfo;
108.1065 -                    while (sym != null && sym.isFree()) {
108.1066 -                        scope = scope.up;
108.1067 -                        while (scope != null && scope.kind == CLASSSCOPE) {
108.1068 -                            scope = scope.up;
108.1069 -                        }
108.1070 -                        sym = scope.tbl.get(name);
108.1071 -                    }
108.1072 -                    if (sym == null) {
108.1073 -                        isUnresolved = true;
108.1074 -                    } else {
108.1075 -                        isUnresolved = sym.isUnresolved();
108.1076 -                    }
108.1077 -                }
108.1078 -                if (isUnresolved) {
108.1079 -                    String key = entry.getKey();
108.1080 -                    if (!builtin.contains(key)) {
108.1081 -                        unresolved.add(key);
108.1082 -                    }
108.1083 -                }
108.1084 -            }
108.1085 -
108.1086 -
108.1087 -            if (unresolved.size() > 0) {
108.1088 -                // Check imports and see if it's resolved by existing imports
108.1089 -                PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
108.1090 -                // TODO - cache system libraries!
108.1091 -                // TODO - make method which doesn't create elements for these guys!
108.1092 -//                Set<IndexedElement> elements = index.getImportedElements("", NameKind.PREFIX, PythonIndex.ALL_SCOPE, imports, importsFrom);
108.1093 -//                for (IndexedElement e : elements) {
108.1094 -//                    unresolved.remove(e.getName());
108.1095 -//                }
108.1096 -                Set<String> wildcarded = index.getImportedFromWildcards(importsFrom);
108.1097 -                unresolved.removeAll(wildcarded);
108.1098 -
108.1099 -                if (unresolved.size() > 0) {
108.1100 -                    NameFinder finder = new NameFinder(unresolved);
108.1101 -                    List<Name> nodes = finder.run(scopeInfo.scope_node);
108.1102 -                    unresolvedNodes.addAll(nodes);
108.1103 -                }
108.1104 -            }
108.1105 -        }
108.1106 -
108.1107 -        if (unresolvedNodes.size() > 1) {
108.1108 -            Collections.sort(unresolvedNodes, PythonUtils.ATTRIBUTE_NAME_NODE_COMPARATOR);
108.1109 -            //Collections.sort(unusedNodes, PythonUtils.NODE_POS_COMPARATOR);
108.1110 -        }
108.1111 -
108.1112 -        return unresolvedNodes;
108.1113 -    }
108.1114 -
108.1115 -    public List<PythonTree> getUnused(boolean skipSelf, boolean skipParams) { // not used for unused imports, see separate method
108.1116 -        List<PythonTree> unusedNodes = new ArrayList<>();
108.1117 -
108.1118 -        for (ScopeInfo scopeInfo : scopes.values()) {
108.1119 -            if (scopeInfo.kind != FUNCSCOPE && scopeInfo.kind != TOPSCOPE && scopeInfo.kind != CLASSSCOPE) {
108.1120 -                continue;
108.1121 -            }
108.1122 -            Set<String> unused = new HashSet<>();
108.1123 -            Map<String, SymInfo> tbl = scopeInfo.tbl;
108.1124 -            for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
108.1125 -                SymInfo symInfo = entry.getValue();
108.1126 -                if (symInfo.isUnused(scopeInfo) && (!skipParams || !symInfo.isParameter())) {
108.1127 -                    String key = entry.getKey();
108.1128 -                    if (skipSelf && "self".equals(key)) { // NOI18N
108.1129 -                        continue;
108.1130 -                    }
108.1131 -                    unused.add(key);
108.1132 -                }
108.1133 -            }
108.1134 -
108.1135 -            if (unused.size() > 0) {
108.1136 -                NameFinder finder = new NameFinder(unused);
108.1137 -                List<Name> nodes = finder.run(scopeInfo.scope_node);
108.1138 -                unusedNodes.addAll(nodes);
108.1139 -            }
108.1140 -        }
108.1141 -
108.1142 -        if (unusedNodes.size() > 1) {
108.1143 -            Collections.sort(unusedNodes, PythonUtils.NAME_NODE_COMPARATOR);
108.1144 -            //Collections.sort(unusedNodes, PythonUtils.NODE_POS_COMPARATOR);
108.1145 -        }
108.1146 -
108.1147 -        return unusedNodes;
108.1148 -    }
108.1149 -
108.1150 -    private static class NameFinder extends Visitor {
108.1151 -        private Set<String> names;
108.1152 -        private List<Name> nodes = new ArrayList<>();
108.1153 -        private PythonTree acceptDef;
108.1154 -
108.1155 -        private NameFinder(Set<String> names) {
108.1156 -            this.names = names;
108.1157 -        }
108.1158 -
108.1159 -        @Override
108.1160 -        public Object visitClassDef(ClassDef node) throws Exception {
108.1161 -            // Don't look in nested scopes
108.1162 -            if (node != acceptDef) {
108.1163 -                return null;
108.1164 -            }
108.1165 -            return super.visitClassDef(node);
108.1166 -        }
108.1167 -
108.1168 -        @Override
108.1169 -        public Object visitFunctionDef(FunctionDef node) throws Exception {
108.1170 -            // Don't look in nested scopes
108.1171 -            if (node != acceptDef) {
108.1172 -                return null;
108.1173 -            }
108.1174 -            return super.visitFunctionDef(node);
108.1175 -        }
108.1176 -
108.1177 -        @Override
108.1178 -        public Object visitName(Name node) throws Exception {
108.1179 -            String name = node.getInternalId();
108.1180 -            if (names.contains(name)) {
108.1181 -                nodes.add(node);
108.1182 -            }
108.1183 -
108.1184 -            return super.visitName(node);
108.1185 -        }
108.1186 -
108.1187 -        public List<Name> run(PythonTree node) {
108.1188 -            this.acceptDef = node;
108.1189 -            try {
108.1190 -                visit(node);
108.1191 -            } catch (Exception ex) {
108.1192 -                Exceptions.printStackTrace(ex);
108.1193 -            }
108.1194 -
108.1195 -            return nodes;
108.1196 -        }
108.1197 -    }
108.1198 -    private static Set<String> builtinSymbols;
108.1199 -
108.1200 -    private Set<String> getBuiltin(PythonParserResult info) {
108.1201 -        if (builtinSymbols == null) {
108.1202 -            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
108.1203 -            builtinSymbols = index.getBuiltinSymbols();
108.1204 -        }
108.1205 -
108.1206 -        return builtinSymbols;
108.1207 -    }
108.1208 -
108.1209 -    public void error(String msg, boolean err, PythonTree node) throws Exception {
108.1210 -        assert node != null;
108.1211 -        // TODO - record and register with the hints manager?
108.1212 -        OffsetRange range = PythonAstUtils.getRange(node);
108.1213 -
108.1214 -        if (errors == null) {
108.1215 -            errors = new ArrayList<>();
108.1216 -        }
108.1217 -        Error error = new DefaultError(null, msg, null, fileObject, range.getStart(), range.getEnd(), err ? Severity.ERROR : Severity.WARNING);
108.1218 -        errors.add(error);
108.1219 -    }
108.1220 -
108.1221 -    public String getFilename() {
108.1222 -        return FileUtil.getFileDisplayName(fileObject);
108.1223 -    }
108.1224 -
108.1225 -    public Map<PythonTree, ScopeInfo> getScopes() {
108.1226 -        return scopes;
108.1227 -    }
108.1228 -
108.1229 -    public List<Import> getImports() {
108.1230 -        return imports;
108.1231 -    }
108.1232 -
108.1233 -    public List<ImportFrom> getImportsFrom() {
108.1234 -        return importsFrom;
108.1235 -    }
108.1236 -
108.1237 -    public boolean isTopLevel(PythonTree node) {
108.1238 -        return topLevelImports.contains(node);
108.1239 -    }
108.1240 -
108.1241 -    public List<PythonTree> getMainImports() {
108.1242 -        return mainImports;
108.1243 -    }
108.1244 -
108.1245 -    public Set<PythonTree> getTopLevelImports() {
108.1246 -        return topLevelImports;
108.1247 -    }
108.1248 -
108.1249 -    public List<Str> getPublicSymbols() {
108.1250 -        return publicSymbols;
108.1251 -    }
108.1252 -}
   109.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   109.2 +++ b/python.hints/build.xml	Mon Sep 21 13:01:16 2015 +0200
   109.3 @@ -0,0 +1,5 @@
   109.4 +<?xml version="1.0" encoding="UTF-8"?>
   109.5 +<project basedir="." default="netbeans" name="contrib/python.hints">
   109.6 +    <description>Builds, tests, and runs the project org.netbeans.modules.python.hints</description>
   109.7 +    <import file="../../nbbuild/templates/projectized.xml"/>
   109.8 +</project>
   110.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.2 +++ b/python.hints/manifest.mf	Mon Sep 21 13:01:16 2015 +0200
   110.3 @@ -0,0 +1,7 @@
   110.4 +Manifest-Version: 1.0
   110.5 +AutoUpdate-Show-In-Client: true
   110.6 +OpenIDE-Module: org.netbeans.modules.python.hints
   110.7 +OpenIDE-Module-Layer: org/netbeans/modules/python/hints/layer.xml
   110.8 +OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/python/hints/Bundle.properties
   110.9 +OpenIDE-Module-Specification-Version: 1.0
  110.10 +
   111.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.2 +++ b/python.hints/nbproject/project.properties	Mon Sep 21 13:01:16 2015 +0200
   111.3 @@ -0,0 +1,2 @@
   111.4 +javac.source=1.7
   111.5 +javac.compilerargs=-Xlint -Xlint:-serial
   112.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.2 +++ b/python.hints/nbproject/project.xml	Mon Sep 21 13:01:16 2015 +0200
   112.3 @@ -0,0 +1,157 @@
   112.4 +<?xml version="1.0" encoding="UTF-8"?>
   112.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
   112.6 +    <type>org.netbeans.modules.apisupport.project</type>
   112.7 +    <configuration>
   112.8 +        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
   112.9 +            <code-name-base>org.netbeans.modules.python.hints</code-name-base>
  112.10 +            <module-dependencies>
  112.11 +                <dependency>
  112.12 +                    <code-name-base>org.jython</code-name-base>
  112.13 +                    <build-prerequisite/>
  112.14 +                    <compile-dependency/>
  112.15 +                    <run-dependency>
  112.16 +                        <release-version>2</release-version>
  112.17 +                        <specification-version>2.12</specification-version>
  112.18 +                    </run-dependency>
  112.19 +                </dependency>
  112.20 +                <dependency>
  112.21 +                    <code-name-base>org.netbeans.modules.csl.api</code-name-base>
  112.22 +                    <build-prerequisite/>
  112.23 +                    <compile-dependency/>
  112.24 +                    <run-dependency>
  112.25 +                        <release-version>2</release-version>
  112.26 +                        <specification-version>2.51</specification-version>
  112.27 +                    </run-dependency>
  112.28 +                </dependency>
  112.29 +                <dependency>
  112.30 +                    <code-name-base>org.netbeans.modules.editor.codetemplates</code-name-base>
  112.31 +                    <build-prerequisite/>
  112.32 +                    <compile-dependency/>
  112.33 +                    <run-dependency>
  112.34 +                        <release-version>1</release-version>
  112.35 +                        <specification-version>1.41</specification-version>
  112.36 +                    </run-dependency>
  112.37 +                </dependency>
  112.38 +                <dependency>
  112.39 +                    <code-name-base>org.netbeans.modules.editor.document</code-name-base>
  112.40 +                    <build-prerequisite/>
  112.41 +                    <compile-dependency/>
  112.42 +                    <run-dependency>
  112.43 +                        <specification-version>1.5</specification-version>
  112.44 +                    </run-dependency>
  112.45 +                </dependency>
  112.46 +                <dependency>
  112.47 +                    <code-name-base>org.netbeans.modules.editor.indent</code-name-base>
  112.48 +                    <build-prerequisite/>
  112.49 +                    <compile-dependency/>
  112.50 +                    <run-dependency>
  112.51 +                        <release-version>2</release-version>
  112.52 +                        <specification-version>1.42</specification-version>
  112.53 +                    </run-dependency>
  112.54 +                </dependency>
  112.55 +                <dependency>
  112.56 +                    <code-name-base>org.netbeans.modules.editor.lib</code-name-base>
  112.57 +                    <build-prerequisite/>
  112.58 +                    <compile-dependency/>
  112.59 +                    <run-dependency>
  112.60 +                        <release-version>3</release-version>
  112.61 +                        <specification-version>4.3</specification-version>
  112.62 +                    </run-dependency>
  112.63 +                </dependency>
  112.64 +                <dependency>
  112.65 +                    <code-name-base>org.netbeans.modules.lexer</code-name-base>
  112.66 +                    <build-prerequisite/>
  112.67 +                    <compile-dependency/>
  112.68 +                    <run-dependency>
  112.69 +                        <release-version>2</release-version>
  112.70 +                        <specification-version>1.62</specification-version>
  112.71 +                    </run-dependency>
  112.72 +                </dependency>
  112.73 +                <dependency>
  112.74 +                    <code-name-base>org.netbeans.modules.options.api</code-name-base>
  112.75 +                    <build-prerequisite/>
  112.76 +                    <compile-dependency/>
  112.77 +                    <run-dependency>
  112.78 +                        <release-version>1</release-version>
  112.79 +                        <specification-version>1.44</specification-version>
  112.80 +                    </run-dependency>
  112.81 +                </dependency>
  112.82 +                <dependency>
  112.83 +                    <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
  112.84 +                    <build-prerequisite/>
  112.85 +                    <compile-dependency/>
  112.86 +                    <run-dependency>
  112.87 +                        <release-version>1</release-version>
  112.88 +                        <specification-version>9.5</specification-version>
  112.89 +                    </run-dependency>
  112.90 +                </dependency>
  112.91 +                <dependency>
  112.92 +                    <code-name-base>org.netbeans.modules.parsing.indexing</code-name-base>
  112.93 +                    <build-prerequisite/>
  112.94 +                    <compile-dependency/>
  112.95 +                    <run-dependency>
  112.96 +                        <specification-version>9.7</specification-version>
  112.97 +                    </run-dependency>
  112.98 +                </dependency>
  112.99 +                <dependency>
 112.100 +                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
 112.101 +                    <build-prerequisite/>
 112.102 +                    <compile-dependency/>
 112.103 +                    <run-dependency>
 112.104 +                        <release-version>1</release-version>
 112.105 +                        <specification-version>1.65</specification-version>
 112.106 +                    </run-dependency>
 112.107 +                </dependency>
 112.108 +                <dependency>
 112.109 +                    <code-name-base>org.netbeans.modules.python.core</code-name-base>
 112.110 +                    <build-prerequisite/>
 112.111 +                    <compile-dependency/>
 112.112 +                    <run-dependency>
 112.113 +                        <specification-version>1.4</specification-version>
 112.114 +                    </run-dependency>
 112.115 +                </dependency>
 112.116 +                <dependency>
 112.117 +                    <code-name-base>org.netbeans.modules.python.editor</code-name-base>
 112.118 +                    <build-prerequisite/>
 112.119 +                    <compile-dependency/>
 112.120 +                    <run-dependency>
 112.121 +                        <specification-version>1.8.2</specification-version>
 112.122 +                    </run-dependency>
 112.123 +                </dependency>
 112.124 +                <dependency>
 112.125 +                    <code-name-base>org.netbeans.modules.python.source</code-name-base>
 112.126 +                    <build-prerequisite/>
 112.127 +                    <compile-dependency/>
 112.128 +                    <run-dependency>
 112.129 +                        <specification-version>1.1</specification-version>
 112.130 +                    </run-dependency>
 112.131 +                </dependency>
 112.132 +                <dependency>
 112.133 +                    <code-name-base>org.openide.filesystems</code-name-base>
 112.134 +                    <build-prerequisite/>
 112.135 +                    <compile-dependency/>
 112.136 +                    <run-dependency>
 112.137 +                        <specification-version>9.8</specification-version>
 112.138 +                    </run-dependency>
 112.139 +                </dependency>
 112.140 +                <dependency>
 112.141 +                    <code-name-base>org.openide.util</code-name-base>
 112.142 +                    <build-prerequisite/>
 112.143 +                    <compile-dependency/>
 112.144 +                    <run-dependency>
 112.145 +                        <specification-version>9.5</specification-version>
 112.146 +                    </run-dependency>
 112.147 +                </dependency>
 112.148 +                <dependency>
 112.149 +                    <code-name-base>org.openide.util.lookup</code-name-base>
 112.150 +                    <build-prerequisite/>
 112.151 +                    <compile-dependency/>
 112.152 +                    <run-dependency>
 112.153 +                        <specification-version>8.32</specification-version>
 112.154 +                    </run-dependency>
 112.155 +                </dependency>
 112.156 +            </module-dependencies>
 112.157 +            <public-packages/>
 112.158 +        </data>
 112.159 +    </configuration>
 112.160 +</project>
   113.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/AccessToProtected.java	Mon Sep 21 13:01:16 2015 +0200
   113.3 @@ -0,0 +1,150 @@
   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.NameStyle;
  113.61 +import org.openide.util.NbBundle;
  113.62 +import org.python.antlr.ast.Attribute;
  113.63 +import org.python.antlr.ast.Name;
  113.64 +import org.python.antlr.base.expr;
  113.65 +
  113.66 +/**
  113.67 + * Check direct acces to parent protected variables or methods
  113.68 + * @author jean-yves Mengant
  113.69 + */
  113.70 +public class AccessToProtected extends PythonAstRule {
  113.71 +    private final static String ACCESS_PROTECTED_ID = "AccessProtected"; // NOI18N
  113.72 +    private final static String ACCESS_PROTECTED_VARIABLE = "AccessProtectedVariable"; // NOI18N
  113.73 +    private final static String ACCESS_PROTECTED_DESC = "AccessProtectedDesc"; // NOI18N
  113.74 +
  113.75 +    @Override
  113.76 +    public Set<Class> getKinds() {
  113.77 +        return Collections.<Class>singleton(Attribute.class);
  113.78 +    }
  113.79 +
  113.80 +    @Override
  113.81 +    public void run(PythonRuleContext context, List<Hint> result) {
  113.82 +        PythonParserResult info = (PythonParserResult) context.parserResult;
  113.83 +        Attribute cur = (Attribute)context.node;
  113.84 +        String curAttr = cur.getInternalAttr();
  113.85 +        if (curAttr == null) {
  113.86 +            return;
  113.87 +        }
  113.88 +
  113.89 +        if (NameStyle.isProtectedName(curAttr)) {
  113.90 +            expr curValue = cur.getInternalValue();
  113.91 +            if (curValue instanceof Name) {
  113.92 +                Name nam = (Name)curValue;
  113.93 +                String id = nam.getInternalId();
  113.94 +                if (id.equals("self")) { // NOI18N
  113.95 +                    return; // normal access from class instance
  113.96 +                }
  113.97 +                if (PythonAstUtils.getParentClassFromNode(context.path, null, id) != null) {
  113.98 +                    return; // parent access
  113.99 +                }
 113.100 +                // we should warn here : Access to protected Attributes from non child
 113.101 +                // classes
 113.102 +                OffsetRange range = PythonAstUtils.getRange(cur);
 113.103 +                range = PythonLexerUtils.getLexerOffsets(info, range);
 113.104 +                if (range != OffsetRange.NONE) {
 113.105 +                    List<HintFix> fixList = Collections.emptyList();
 113.106 +                    String message = NbBundle.getMessage(NameRule.class, ACCESS_PROTECTED_VARIABLE, curAttr);
 113.107 +                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
 113.108 +                    result.add(desc);
 113.109 +                }
 113.110 +            }
 113.111 +        }
 113.112 +    }
 113.113 +
 113.114 +    @Override
 113.115 +    public String getId() {
 113.116 +        return ACCESS_PROTECTED_ID;
 113.117 +    }
 113.118 +
 113.119 +    @Override
 113.120 +    public String getDescription() {
 113.121 +        return NbBundle.getMessage(RelativeImports.class, ACCESS_PROTECTED_DESC);
 113.122 +    }
 113.123 +
 113.124 +    @Override
 113.125 +    public boolean getDefaultEnabled() {
 113.126 +        return false;
 113.127 +    }
 113.128 +
 113.129 +    @Override
 113.130 +    public JComponent getCustomizer(Preferences node) {
 113.131 +        return null;
 113.132 +    }
 113.133 +
 113.134 +    @Override
 113.135 +    public boolean appliesTo(RuleContext context) {
 113.136 +        return true;
 113.137 +    }
 113.138 +
 113.139 +    @Override
 113.140 +    public String getDisplayName() {
 113.141 +        return NbBundle.getMessage(AccessToProtected.class, ACCESS_PROTECTED_ID);
 113.142 +    }
 113.143 +
 113.144 +    @Override
 113.145 +    public boolean showInTasklist() {
 113.146 +        return true;
 113.147 +    }
 113.148 +
 113.149 +    @Override
 113.150 +    public HintSeverity getDefaultSeverity() {
 113.151 +        return HintSeverity.WARNING;
 113.152 +    }
 113.153 +}
   114.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   114.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/AllAssignExists.java	Mon Sep 21 13:01:16 2015 +0200
   114.3 @@ -0,0 +1,148 @@
   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.Collections;
  114.48 +import java.util.List;
  114.49 +import java.util.Set;
  114.50 +import java.util.prefs.Preferences;
  114.51 +import javax.swing.JComponent;
  114.52 +import org.netbeans.modules.csl.api.Hint;
  114.53 +import org.netbeans.modules.csl.api.HintFix;
  114.54 +import org.netbeans.modules.csl.api.HintSeverity;
  114.55 +import org.netbeans.modules.csl.api.OffsetRange;
  114.56 +import org.netbeans.modules.csl.api.RuleContext;
  114.57 +import org.netbeans.modules.python.source.PythonAstUtils;
  114.58 +import org.netbeans.modules.python.source.PythonParserResult;
  114.59 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  114.60 +import org.netbeans.modules.python.source.scopes.ScopeInfo;
  114.61 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  114.62 +import org.netbeans.modules.python.source.scopes.SymInfo;
  114.63 +import org.openide.util.NbBundle;
  114.64 +import org.python.antlr.ast.Module;
  114.65 +import org.python.antlr.ast.Str;
  114.66 +
  114.67 +/**
  114.68 + *
  114.69 + * @author Tor Norbye
  114.70 + */
  114.71 +public class AllAssignExists extends PythonAstRule {
  114.72 +    @Override
  114.73 +    public Set<Class> getKinds() {
  114.74 +        return Collections.<Class>singleton(Module.class);
  114.75 +    }
  114.76 +
  114.77 +    @Override
  114.78 +    public void run(PythonRuleContext context, List<Hint> result) {
  114.79 +        PythonParserResult ppr = (PythonParserResult)context.parserResult;
  114.80 +        SymbolTable symbolTable = ppr.getSymbolTable();
  114.81 +        List<Str> publicSymbols = symbolTable.getPublicSymbols();
  114.82 +        if (publicSymbols != null) {
  114.83 +            // Check that we actually have all the symbols called for
  114.84 +            // by the all-list
  114.85 +
  114.86 +            ScopeInfo topScope = symbolTable.getScopeInfo(context.node);
  114.87 +            assert topScope != null;
  114.88 +
  114.89 +            // Mark all other symbols private!
  114.90 +            for (Str str : publicSymbols) {
  114.91 +                //String name = PythonAstUtils.getExprName(expr);
  114.92 +                String name = PythonAstUtils.getStrContent(str);
  114.93 +                if (name != null) {
  114.94 +                    SymInfo sym = topScope.tbl.get(name);
  114.95 +                    if (sym == null) {
  114.96 +                        // Uh oh -- missing!
  114.97 +                        PythonParserResult info = (PythonParserResult) context.parserResult;
  114.98 +                        OffsetRange range = PythonAstUtils.getNameRange(info, str);
  114.99 +                        range = PythonLexerUtils.getLexerOffsets(info, range);
 114.100 +                        if (range != OffsetRange.NONE) {
 114.101 +                            List<HintFix> fixList = Collections.emptyList();
 114.102 +                            String message = NbBundle.getMessage(AllAssignExists.class, "AllAssignExistsMsg", name);
 114.103 +                            Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 205);
 114.104 +                            result.add(desc);
 114.105 +                        }
 114.106 +                    }
 114.107 +                }
 114.108 +            }
 114.109 +        }
 114.110 +    }
 114.111 +
 114.112 +    @Override
 114.113 +    public String getId() {
 114.114 +        return "AllAssignExists"; // NOI18N
 114.115 +    }
 114.116 +
 114.117 +    @Override
 114.118 +    public String getDescription() {
 114.119 +        return NbBundle.getMessage(AllAssignExists.class, "AllAssignExistsDesc");
 114.120 +    }
 114.121 +
 114.122 +    @Override
 114.123 +    public boolean getDefaultEnabled() {
 114.124 +        return true;
 114.125 +    }
 114.126 +
 114.127 +    @Override
 114.128 +    public JComponent getCustomizer(Preferences node) {
 114.129 +        return null;
 114.130 +    }
 114.131 +
 114.132 +    @Override
 114.133 +    public boolean appliesTo(RuleContext context) {
 114.134 +        return true;
 114.135 +    }
 114.136 +
 114.137 +    @Override
 114.138 +    public String getDisplayName() {
 114.139 +        return NbBundle.getMessage(AllAssignExists.class, "AllAssignExists");
 114.140 +    }
 114.141 +
 114.142 +    @Override
 114.143 +    public boolean showInTasklist() {
 114.144 +        return true;
 114.145 +    }
 114.146 +
 114.147 +    @Override
 114.148 +    public HintSeverity getDefaultSeverity() {
 114.149 +        return HintSeverity.ERROR;
 114.150 +    }
 114.151 +}
   115.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/AssignToVariable.java	Mon Sep 21 13:01:16 2015 +0200
   115.3 @@ -0,0 +1,245 @@
   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.ArrayList;
  115.48 +import java.util.Collections;
  115.49 +import java.util.List;
  115.50 +import java.util.Set;
  115.51 +import java.util.prefs.Preferences;
  115.52 +import javax.swing.JComponent;
  115.53 +import javax.swing.text.BadLocationException;
  115.54 +import javax.swing.text.JTextComponent;
  115.55 +import javax.swing.text.Position;
  115.56 +import org.netbeans.modules.python.source.PythonAstUtils;
  115.57 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  115.58 +import org.netbeans.editor.BaseDocument;
  115.59 +import org.netbeans.editor.Utilities;
  115.60 +import org.netbeans.modules.csl.api.EditList;
  115.61 +import org.netbeans.modules.csl.api.Hint;
  115.62 +import org.netbeans.modules.csl.api.HintFix;
  115.63 +import org.netbeans.modules.csl.api.HintSeverity;
  115.64 +import org.netbeans.modules.csl.api.OffsetRange;
  115.65 +import org.netbeans.modules.csl.api.PreviewableFix;
  115.66 +import org.netbeans.modules.csl.api.RuleContext;
  115.67 +import org.netbeans.modules.csl.spi.GsfUtilities;
  115.68 +import org.netbeans.modules.python.source.PythonParserResult;
  115.69 +import org.openide.util.Exceptions;
  115.70 +import org.openide.util.NbBundle;
  115.71 +import org.python.antlr.PythonTree;
  115.72 +import org.python.antlr.ast.Call;
  115.73 +import org.python.antlr.ast.Expr;
  115.74 +import org.python.antlr.ast.FunctionDef;
  115.75 +import org.python.antlr.ast.Str;
  115.76 +import org.python.antlr.base.expr;
  115.77 +import org.python.antlr.base.stmt;
  115.78 +
  115.79 +/**
  115.80 + * Assign an expression to a variable
  115.81 + *
  115.82 + * @author Tor Norbye
  115.83 + */
  115.84 +public class AssignToVariable extends PythonAstRule {
  115.85 +    @Override
  115.86 +    public Set<Class> getKinds() {
  115.87 +        return Collections.singleton((Class)Expr.class);
  115.88 +    }
  115.89 +
  115.90 +    @Override
  115.91 +    public void run(PythonRuleContext context, List<Hint> result) {
  115.92 +        PythonTree node = context.node;
  115.93 +        Expr expr = (Expr)node;
  115.94 +        expr exprValue = expr.getInternalValue();
  115.95 +        if (exprValue instanceof Str) {
  115.96 +            // Skip triple-quoted strings (typically doc strings)
  115.97 +            Str str = (Str)exprValue;
  115.98 +            String s = str.getText();
  115.99 +            if (s.startsWith("'''") || s.startsWith("\"\"\"")) { // NOI18N
 115.100 +                return;
 115.101 +            }
 115.102 +            PythonTree grandParent = context.path.leafGrandParent();
 115.103 +            if (grandParent instanceof FunctionDef) {
 115.104 +                FunctionDef def = (FunctionDef)grandParent;
 115.105 +                List<stmt> body = def.getInternalBody();
 115.106 +                if (body != null && body.size() > 0 && body.get(0) == expr) {
 115.107 +                    // First string in a function -- it's a docstring
 115.108 +                    return;
 115.109 +                }
 115.110 +            }
 115.111 +        }
 115.112 +        if (exprValue instanceof Call) {
 115.113 +            // Skip calls - they may have side effects
 115.114 +            // ...unless it looks like a "getter" style Python method
 115.115 +            Call call = (Call)exprValue;
 115.116 +            if (!PythonAstUtils.isGetter(call, false)) {
 115.117 +                return;
 115.118 +            }
 115.119 +        }
 115.120 +        PythonParserResult info = (PythonParserResult) context.parserResult;
 115.121 +        OffsetRange astOffsets = PythonAstUtils.getNameRange(info, node);
 115.122 +        OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
 115.123 +        BaseDocument doc = context.doc;
 115.124 +        try {
 115.125 +            if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
 115.126 +                    (context.caretOffset == -1 ||
 115.127 +                    Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
 115.128 +                List<HintFix> fixList = new ArrayList<>();
 115.129 +                fixList.add(new AssignToVariableFix(context, node));
 115.130 +                String displayName = getDisplayName();
 115.131 +                Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
 115.132 +                result.add(desc);
 115.133 +            }
 115.134 +        } catch (BadLocationException ex) {
 115.135 +            Exceptions.printStackTrace(ex);
 115.136 +        }
 115.137 +    }
 115.138 +
 115.139 +    @Override
 115.140 +    public String getId() {
 115.141 +        return "AssignToVariable"; // NOI18N
 115.142 +    }
 115.143 +
 115.144 +    @Override
 115.145 +    public String getDisplayName() {
 115.146 +        return NbBundle.getMessage(AssignToVariable.class, "AssignToVariable");
 115.147 +    }
 115.148 +
 115.149 +    @Override
 115.150 +    public String getDescription() {
 115.151 +        return NbBundle.getMessage(AssignToVariable.class, "AssignToVariableDesc");
 115.152 +    }
 115.153 +
 115.154 +    @Override
 115.155 +    public boolean getDefaultEnabled() {
 115.156 +        return true;
 115.157 +    }
 115.158 +
 115.159 +    @Override
 115.160 +    public JComponent getCustomizer(Preferences node) {
 115.161 +        return null;
 115.162 +    }
 115.163 +
 115.164 +    @Override
 115.165 +    public boolean appliesTo(RuleContext context) {
 115.166 +        return true;
 115.167 +    }
 115.168 +
 115.169 +    @Override
 115.170 +    public boolean showInTasklist() {
 115.171 +        return false;
 115.172 +    }
 115.173 +
 115.174 +    @Override
 115.175 +    public HintSeverity getDefaultSeverity() {
 115.176 +        return HintSeverity.CURRENT_LINE_WARNING;
 115.177 +    }
 115.178 +
 115.179 +    private static class AssignToVariableFix implements PreviewableFix {
 115.180 +        private final PythonRuleContext context;
 115.181 +        private final PythonTree node;
 115.182 +        private int varOffset;
 115.183 +        private String varName;
 115.184 +
 115.185 +        private AssignToVariableFix(PythonRuleContext context, PythonTree node) {
 115.186 +            this.context = context;
 115.187 +            this.node = node;
 115.188 +        }
 115.189 +
 115.190 +        @Override
 115.191 +        public String getDescription() {
 115.192 +            return NbBundle.getMessage(AssignToVariable.class, "AssignToVariableFix");
 115.193 +        }
 115.194 +
 115.195 +        @Override
 115.196 +        public boolean canPreview() {
 115.197 +            return true;
 115.198 +        }
 115.199 +
 115.200 +        @Override
 115.201 +        public EditList getEditList() throws Exception {
 115.202 +            BaseDocument doc = context.doc;
 115.203 +            EditList edits = new EditList(doc);
 115.204 +
 115.205 +            OffsetRange astRange = PythonAstUtils.getRange(node);
 115.206 +            if (astRange != OffsetRange.NONE) {
 115.207 +                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets((PythonParserResult) context.parserResult, astRange);
 115.208 +                if (lexRange != OffsetRange.NONE) {
 115.209 +                    int offset = lexRange.getStart();
 115.210 +                    StringBuilder sb = new StringBuilder();
 115.211 +                    varName = NbBundle.getMessage(AssignToVariable.class, "VarName");
 115.212 +                    sb.append(varName);
 115.213 +                    sb.append(" = "); // NOI18N
 115.214 +                    varOffset = offset;
 115.215 +                    edits.replace(offset, 0, sb.toString(), false, 0);
 115.216 +                }
 115.217 +            }
 115.218 +
 115.219 +            return edits;
 115.220 +        }
 115.221 +
 115.222 +        @Override
 115.223 +        public void implement() throws Exception {
 115.224 +            EditList edits = getEditList();
 115.225 +
 115.226 +            Position pos = edits.createPosition(varOffset);
 115.227 +            edits.apply();
 115.228 +            if (pos != null && pos.getOffset() != -1) {
 115.229 +                JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
 115.230 +                if (target != null) {
 115.231 +                    int start = pos.getOffset();
 115.232 +                    int end = start + varName.length();
 115.233 +                    target.select(start, end);
 115.234 +                }
 115.235 +            }
 115.236 +        }
 115.237 +
 115.238 +        @Override
 115.239 +        public boolean isSafe() {
 115.240 +            return true;
 115.241 +        }
 115.242 +
 115.243 +        @Override
 115.244 +        public boolean isInteractive() {
 115.245 +            return false;
 115.246 +        }
 115.247 +    }
 115.248 +}
   116.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   116.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/AttributeDefinedOutsideInit.java	Mon Sep 21 13:01:16 2015 +0200
   116.3 @@ -0,0 +1,140 @@
   116.4 +/*
   116.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   116.6 + *
   116.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   116.8 + *
   116.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  116.10 + * Other names may be trademarks of their respective owners.
  116.11 + *
  116.12 + * The contents of this file are subject to the terms of either the GNU
  116.13 + * General Public License Version 2 only ("GPL") or the Common
  116.14 + * Development and Distribution License("CDDL") (collectively, the
  116.15 + * "License"). You may not use this file except in compliance with the
  116.16 + * License. You can obtain a copy of the License at
  116.17 + * http://www.netbeans.org/cddl-gplv2.html
  116.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  116.19 + * specific language governing permissions and limitations under the
  116.20 + * License.  When distributing the software, include this License Header
  116.21 + * Notice in each file and include the License file at
  116.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  116.23 + * particular file as subject to the "Classpath" exception as provided
  116.24 + * by Oracle in the GPL Version 2 section of the License file that
  116.25 + * accompanied this code. If applicable, add the following below the
  116.26 + * License Header, with the fields enclosed by brackets [] replaced by
  116.27 + * your own identifying information:
  116.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  116.29 + *
  116.30 + * If you wish your version of this file to be governed by only the CDDL
  116.31 + * or only the GPL Version 2, indicate your decision by adding
  116.32 + * "[Contributor] elects to include this software in this distribution
  116.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  116.34 + * single choice of license, a recipient has the option to distribute
  116.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  116.36 + * to extend the choice of license to its licensees as provided above.
  116.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  116.38 + * Version 2 license, then the option applies only if the new code is
  116.39 + * made subject to such option by the copyright holder.
  116.40 + *
  116.41 + * Contributor(s):
  116.42 + *
  116.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  116.44 + */
  116.45 +package org.netbeans.modules.python.hints;
  116.46 +
  116.47 +import java.util.Collections;
  116.48 +import java.util.List;
  116.49 +import java.util.Set;
  116.50 +import java.util.prefs.Preferences;
  116.51 +import javax.swing.JComponent;
  116.52 +import org.netbeans.modules.csl.api.Hint;
  116.53 +import org.netbeans.modules.csl.api.HintFix;
  116.54 +import org.netbeans.modules.csl.api.HintSeverity;
  116.55 +import org.netbeans.modules.csl.api.OffsetRange;
  116.56 +import org.netbeans.modules.csl.api.RuleContext;
  116.57 +import org.netbeans.modules.python.source.PythonAstUtils;
  116.58 +import org.netbeans.modules.python.source.PythonParserResult;
  116.59 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  116.60 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  116.61 +import org.openide.util.NbBundle;
  116.62 +import org.python.antlr.ast.Attribute;
  116.63 +import org.python.antlr.ast.Module;
  116.64 +
  116.65 +/**
  116.66 + *
  116.67 + * @author Jean-Yves Mengant
  116.68 + */
  116.69 +public class AttributeDefinedOutsideInit extends PythonAstRule {
  116.70 +    private final static String ATTRIBUTE_DEFINED_OUTSIDE_INIT = "AttributeDefinedOutsideInit";
  116.71 +    private final static String ATTRIBUTE_DEFINED_OUTSITE_INIT_VAR = "AttributeDefinedOutsideInitVariable";
  116.72 +    private final static String ATTRIBUTE_DEFINED_OUTSIDE_INIT_DESC = "AttributeDefinedOutsideInitDesc";
  116.73 +
  116.74 +    @Override
  116.75 +    public Set<Class> getKinds() {
  116.76 +        return Collections.<Class>singleton(Module.class);
  116.77 +    }
  116.78 +
  116.79 +    @Override
  116.80 +    public void run(PythonRuleContext context, List<Hint> result) {
  116.81 +        PythonParserResult info = (PythonParserResult) context.parserResult;
  116.82 +        PythonParserResult pr = PythonAstUtils.getParseResult(info);
  116.83 +        SymbolTable symbolTable = pr.getSymbolTable();
  116.84 +
  116.85 +
  116.86 +        List<Attribute> notInIntBound = symbolTable.getNotInInitAttributes(info);
  116.87 +        if (notInIntBound.size() > 0) {
  116.88 +            for (Attribute cur : notInIntBound) {
  116.89 +                OffsetRange range = PythonAstUtils.getRange(cur);
  116.90 +                range = PythonLexerUtils.getLexerOffsets(info, range);
  116.91 +                if (range != OffsetRange.NONE) {
  116.92 +                    List<HintFix> fixList = Collections.emptyList();
  116.93 +                    String message = NbBundle.getMessage(NameRule.class,
  116.94 +                            ATTRIBUTE_DEFINED_OUTSITE_INIT_VAR,
  116.95 +                            cur.getInternalAttr());
  116.96 +                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
  116.97 +                    result.add(desc);
  116.98 +                }
  116.99 +            }
 116.100 +        }
 116.101 +
 116.102 +    }
 116.103 +
 116.104 +    @Override
 116.105 +    public String getId() {
 116.106 +        return ATTRIBUTE_DEFINED_OUTSIDE_INIT;
 116.107 +    }
 116.108 +
 116.109 +    @Override
 116.110 +    public String getDescription() {
 116.111 +        return NbBundle.getMessage(RelativeImports.class, ATTRIBUTE_DEFINED_OUTSIDE_INIT_DESC);
 116.112 +    }
 116.113 +
 116.114 +    @Override
 116.115 +    public boolean getDefaultEnabled() {
 116.116 +        return false;
 116.117 +    }
 116.118 +
 116.119 +    @Override
 116.120 +    public JComponent getCustomizer(Preferences node) {
 116.121 +        return null;
 116.122 +    }
 116.123 +
 116.124 +    @Override
 116.125 +    public boolean appliesTo(RuleContext context) {
 116.126 +        return true;
 116.127 +    }
 116.128 +
 116.129 +    @Override
 116.130 +    public String getDisplayName() {
 116.131 +        return NbBundle.getMessage(AccessToProtected.class, ATTRIBUTE_DEFINED_OUTSIDE_INIT);
 116.132 +    }
 116.133 +
 116.134 +    @Override
 116.135 +    public boolean showInTasklist() {
 116.136 +        return true;
 116.137 +    }
 116.138 +
 116.139 +    @Override
 116.140 +    public HintSeverity getDefaultSeverity() {
 116.141 +        return HintSeverity.WARNING;
 116.142 +    }
 116.143 +}
   117.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   117.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/Bundle.properties	Mon Sep 21 13:01:16 2015 +0200
   117.3 @@ -0,0 +1,147 @@
   117.4 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   117.5 +#
   117.6 +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   117.7 +#
   117.8 +# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   117.9 +# Other names may be trademarks of their respective owners.
  117.10 +#
  117.11 +# The contents of this file are subject to the terms of either the GNU
  117.12 +# General Public License Version 2 only ("GPL") or the Common
  117.13 +# Development and Distribution License("CDDL") (collectively, the
  117.14 +# "License"). You may not use this file except in compliance with the
  117.15 +# License. You can obtain a copy of the License at
  117.16 +# http://www.netbeans.org/cddl-gplv2.html
  117.17 +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  117.18 +# specific language governing permissions and limitations under the
  117.19 +# License.  When distributing the software, include this License Header
  117.20 +# Notice in each file and include the License file at
  117.21 +# nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  117.22 +# particular file as subject to the "Classpath" exception as provided
  117.23 +# by Oracle in the GPL Version 2 section of the License file that
  117.24 +# accompanied this code. If applicable, add the following below the
  117.25 +# License Header, with the fields enclosed by brackets [] replaced by
  117.26 +# your own identifying information:
  117.27 +# "Portions Copyrighted [year] [name of copyright owner]"
  117.28 +#
  117.29 +# Contributor(s):
  117.30 +#
  117.31 +# The Original Software is NetBeans. The Initial Developer of the Original
  117.32 +# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  117.33 +# Microsystems, Inc. All Rights Reserved.
  117.34 +#
  117.35 +# If you wish your version of this file to be governed by only the CDDL
  117.36 +# or only the GPL Version 2, indicate your decision by adding
  117.37 +# "[Contributor] elects to include this software in this distribution
  117.38 +# under the [CDDL or GPL Version 2] license." If you do not indicate a
  117.39 +# single choice of license, a recipient has the option to distribute
  117.40 +# your version of this file under either the CDDL, the GPL Version 2 or
  117.41 +# to extend the choice of license to its licensees as provided above.
  117.42 +# However, if you add GPL Version 2 code and therefore, elected the GPL
  117.43 +# Version 2 license, then the option applies only if the new code is
  117.44 +# made subject to such option by the copyright holder.
  117.45 +
  117.46 +# Category descriptions in the Options Panel
  117.47 +gsf-hints/text/x-python/hints/general=General
  117.48 +
  117.49 +# NameRule
  117.50 +NameRule=Naming Conventions
  117.51 +NameRuleDesc=Check class, function and variable names for style guide compliance (see http://www.python.org/dev/peps/pep-0008/ for rules)
  117.52 +NameRuleWrongNoArg=First argument should be 'self' or 'cls'
  117.53 +NameRuleWrongArg=First argument ({0}) should be 'self' or 'cls'
  117.54 +WrongStyle=Name "{0}" is not a valid {1} name according to your code style ({2})
  117.55 +Module=module
  117.56 +Function=function
  117.57 +Class=class
  117.58 +Variable=variable
  117.59 +ChangeStyle=Change preferred {0} name style to {1}
  117.60 +ChangeNoStyle=Turn off {0} name style checks
  117.61 +IgnoreWord=Ignore name violations for "{0}"
  117.62 +NameRulePrefs.selfCb.text=First method params should be "self" or "cls"
  117.63 +NameRulePrefs.moduleLabel.text=Modules:
  117.64 +NameRulePrefs.classLabel.text=Classes:
  117.65 +NameRulePrefs.functionLabel.text=Functions:
  117.66 +NameRulePrefs.parameterLabel.text=Parameters:
  117.67 +NameRulePrefs.variableLabel.text=Variables:
  117.68 +NameRulePrefs.ignoreLabel.text=Ignored:
  117.69 +
  117.70 +CreateDocString=Create document comment
  117.71 +CreateDocStringDesc=Offer to create a documentation comment for the current function, class or module
  117.72 +CreateDocStringFix=Add a one-liner docstring
  117.73 +CreateDocStringFixMulti=Add a multi-line docstring
  117.74 +
  117.75 +AssignToVariable=Assign expression to a variable
  117.76 +AssignToVariableDesc=Assign expression under the caret to a variable
  117.77 +AssignToVariableFix=Assign expression to a variable
  117.78 +VarName=name
  117.79 +
  117.80 +SplitImports=Multiple imports per import statement is discouraged
  117.81 +SplitImportsDesc=Split an import which imports multiple modules into individual import statements as recommended by the Python styleguide
  117.82 +SplitImportsFix=Split import into individual import statements
  117.83 +
  117.84 +RelativeImports=Relative imports for intra-package imports are actively discouraged (as per PEP-008)
  117.85 +RelativeImportsDesc=Relative imports for intra-package imports are actively discouraged (as per PEP-008) and this rule warns about usages of relative imports
  117.86 +RelativeImportsFix=Replace with absolute import
  117.87 +
  117.88 +Deprecations=Deprecated
  117.89 +DeprecationsMsg={0} is deprecated
  117.90 +DeprecationsMsgDetail={0} is deprecated. {1}
  117.91 +DeprecationsDesc=Check for deprecated modules
  117.92 +
  117.93 +SurroundWith=Surround With...
  117.94 +#SurroundWithDesc=Offer to surround selected code with try/catch, etc
  117.95 +SurroundWithTE=Surround With Try/Except
  117.96 +SurroundWithTEF=Surround With Try/Except/Finally
  117.97 +SurroundWithTF=Surround With Try/Finally
  117.98 +InsertSelf=Insert a new first parameter "self"
  117.99 +RenameSelf=Rename first parameter "{0}" to self
 117.100 +
 117.101 +ExtractCode=Extract Code
 117.102 +IntroduceMethod=Extract Method
 117.103 +IntroduceVariable=Introduce Variable
 117.104 +IntroduceConstant=Introduce Constant
 117.105 +IntroduceField=Introduce Field
 117.106 +
 117.107 +UnusedImport=Unused Import
 117.108 +UnusedImportSymbols=Some symbols are unused ({0})
 117.109 +UnusedImports=Find Unused Imports
 117.110 +UnusedImportsDesc=Find imports that aren't used in this module and can be removed
 117.111 +UnusedFix=Remove Unused Import
 117.112 +UnusedFixSymbols=Remove {0} from import
 117.113 +OrganizeImports=Clean up and Organize Imports
 117.114 +DeleteAllUnused=Remove All Unused Imports
 117.115 +
 117.116 +Unused=Find Unused Variables
 117.117 +UnusedDesc=Find variables that are defined but never used
 117.118 +UnusedVariable=Unused Variable {0}
 117.119 +
 117.120 +Unresolved=Find Undefined Names
 117.121 +UnresolvedDesc=Find names that are used but have not been bound
 117.122 +UnresolvedVariable=Undefined name "{0}"
 117.123 +UnresolvedVariableMaybe=Undefined name "{0}" - did you mean "{1}" ?
 117.124 +FixImport=Import {0}
 117.125 +
 117.126 +UnresolvedAttributes=Find Unresolved classes attributes and parentages
 117.127 +UnresolvedAttributesDesc=Find class attributes that are used but have not been bound and undefined inherited classes
 117.128 +UnresolvedAttributesVariable=Undefined attribute "{0}"
 117.129 +UnresolvedInheritanceVariable=Inheriting from undefined parent class "{0}"
 117.130 +
 117.131 +AccessProtected=Access Protected Attributes
 117.132 +AccessProtectedDesc=Find access to protected variables/methods of non parent classes
 117.133 +AccessProtectedVariable=Access to protected variable "{0}"
 117.134 +
 117.135 +AttributeDefinedOutsideInit=Attribute Defined Outside __init__
 117.136 +AttributeDefinedOutsideInitDesc=Class Attribute defined outside __init__ constructor
 117.137 +AttributeDefinedOutsideInitVariable=Attribute Defined Outside __init__ "{0}"
 117.138 +
 117.139 +ClassCircularRedundancy=Parent Child circular redundancy
 117.140 +ClassCircularRedundancyDesc=Parent Child circular redundancy = A inherits B and B inherits A
 117.141 +ClassCircularRedundancyVariable=Parent/child {0} inheritance circular redundancy
 117.142 +
 117.143 +AllAssignExists=Symbol defined in __all__ does not exist
 117.144 +AllAssignExistsDesc=Checks that all symbols listed in __all__ actually exist
 117.145 +AllAssignExistsMsg="{0}" defined in __all__ does not exist!
 117.146 +UnusedDetectorPrefs.skipParams.text=Ignore unused function parameters
 117.147 +UnusedDetectorPrefs.ignoredLabel.text=Ignored names:
 117.148 +UnusedDetectorPrefs.skipTupleAssignments.text=Ignore unused variables in tuple-assignments
 117.149 +
 117.150 +OpenIDE-Module-Name=Python Hints
   118.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   118.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/ClassCircularRedundancy.java	Mon Sep 21 13:01:16 2015 +0200
   118.3 @@ -0,0 +1,140 @@
   118.4 +/*
   118.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   118.6 + *
   118.7 + * Copyright 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 + * If you wish your version of this file to be governed by only the CDDL
  118.31 + * or only the GPL Version 2, indicate your decision by adding
  118.32 + * "[Contributor] elects to include this software in this distribution
  118.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  118.34 + * single choice of license, a recipient has the option to distribute
  118.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  118.36 + * to extend the choice of license to its licensees as provided above.
  118.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  118.38 + * Version 2 license, then the option applies only if the new code is
  118.39 + * made subject to such option by the copyright holder.
  118.40 + *
  118.41 + * Contributor(s):
  118.42 + *
  118.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  118.44 + */
  118.45 +package org.netbeans.modules.python.hints;
  118.46 +
  118.47 +import java.util.Collections;
  118.48 +import java.util.HashMap;
  118.49 +import java.util.List;
  118.50 +import java.util.Map.Entry;
  118.51 +import java.util.Set;
  118.52 +import java.util.prefs.Preferences;
  118.53 +import javax.swing.JComponent;
  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.RuleContext;
  118.59 +import org.netbeans.modules.python.source.PythonAstUtils;
  118.60 +import org.netbeans.modules.python.source.PythonParserResult;
  118.61 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  118.62 +import org.openide.util.NbBundle;
  118.63 +import org.python.antlr.ast.ClassDef;
  118.64 +import org.python.antlr.ast.Module;
  118.65 +
  118.66 +/**
  118.67 + * check for redundancy cycling in parent child
  118.68 + * @author Jean-Yves Mengant
  118.69 + */
  118.70 +public class ClassCircularRedundancy extends PythonAstRule {
  118.71 +    private final static String CLASS_CIRCULAR_REDUNDANCY = "ClassCircularRedundancy";
  118.72 +    private final static String CLASS_CIRCULAR_REDUNDANCY_VAR = "ClassCircularRedundancyVariable";
  118.73 +    private final static String CLASS_CIRCULAR_REDUNDANCY_DESC = "ClassCircularRedundancyDesc";
  118.74 +
  118.75 +    @Override
  118.76 +    public Set<Class> getKinds() {
  118.77 +        return Collections.<Class>singleton(Module.class);
  118.78 +    }
  118.79 +
  118.80 +    @Override
  118.81 +    public void run(PythonRuleContext context, List<Hint> result) {
  118.82 +        PythonParserResult info = (PythonParserResult) context.parserResult;
  118.83 +        SymbolTable symbolTable = info.getSymbolTable();
  118.84 +
  118.85 +
  118.86 +        HashMap<ClassDef, String> cyclingRedundancies = symbolTable.getClassesCyclingRedundancies(info);
  118.87 +        if (cyclingRedundancies.size() > 0) {
  118.88 +            Set<Entry<ClassDef, String>> wk = cyclingRedundancies.entrySet();
  118.89 +            for (Entry<ClassDef, String> cur : wk) {
  118.90 +                ClassDef curClass = cur.getKey();
  118.91 +                String curCyclingMsg = curClass.getInternalName() + "/" + cur.getValue(); // NOI18N
  118.92 +                OffsetRange range = PythonAstUtils.getNameRange(info, curClass);
  118.93 +                // range = PythonLexerUtils.getLexerOffsets(info, range);
  118.94 +                if (range != OffsetRange.NONE) {
  118.95 +                    List<HintFix> fixList = Collections.emptyList();
  118.96 +                    String message = NbBundle.getMessage(NameRule.class, CLASS_CIRCULAR_REDUNDANCY_VAR, curCyclingMsg);
  118.97 +                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
  118.98 +                    result.add(desc);
  118.99 +                }
 118.100 +            }
 118.101 +        }
 118.102 +    }
 118.103 +
 118.104 +    @Override
 118.105 +    public String getId() {
 118.106 +        return CLASS_CIRCULAR_REDUNDANCY;
 118.107 +    }
 118.108 +
 118.109 +    @Override
 118.110 +    public String getDescription() {
 118.111 +        return NbBundle.getMessage(RelativeImports.class, CLASS_CIRCULAR_REDUNDANCY_DESC);
 118.112 +    }
 118.113 +
 118.114 +    @Override
 118.115 +    public boolean getDefaultEnabled() {
 118.116 +        return false;
 118.117 +    }
 118.118 +
 118.119 +    @Override
 118.120 +    public JComponent getCustomizer(Preferences node) {
 118.121 +        return null;
 118.122 +    }
 118.123 +
 118.124 +    @Override
 118.125 +    public boolean appliesTo(RuleContext context) {
 118.126 +        return true;
 118.127 +    }
 118.128 +
 118.129 +    @Override
 118.130 +    public String getDisplayName() {
 118.131 +        return NbBundle.getMessage(AccessToProtected.class, CLASS_CIRCULAR_REDUNDANCY);
 118.132 +    }
 118.133 +
 118.134 +    @Override
 118.135 +    public boolean showInTasklist() {
 118.136 +        return true;
 118.137 +    }
 118.138 +
 118.139 +    @Override
 118.140 +    public HintSeverity getDefaultSeverity() {
 118.141 +        return HintSeverity.ERROR;
 118.142 +    }
 118.143 +}
   119.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   119.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/CreateDocString.java	Mon Sep 21 13:01:16 2015 +0200
   119.3 @@ -0,0 +1,241 @@
   119.4 +/*
   119.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   119.6 + *
   119.7 + * Copyright 1997-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 + * Contributor(s):
  119.31 + *
  119.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  119.33 + */
  119.34 +package org.netbeans.modules.python.hints;
  119.35 +
  119.36 +import java.util.ArrayList;
  119.37 +import java.util.Collections;
  119.38 +import java.util.HashSet;
  119.39 +import java.util.List;
  119.40 +import java.util.Set;
  119.41 +import java.util.prefs.Preferences;
  119.42 +import javax.swing.JComponent;
  119.43 +import javax.swing.text.BadLocationException;
  119.44 +import javax.swing.text.JTextComponent;
  119.45 +import javax.swing.text.Position;
  119.46 +import org.netbeans.modules.python.source.PythonAstUtils;
  119.47 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  119.48 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
  119.49 +import org.netbeans.api.lexer.Token;
  119.50 +import org.netbeans.api.lexer.TokenSequence;
  119.51 +import org.netbeans.editor.BaseDocument;
  119.52 +import org.netbeans.editor.Utilities;
  119.53 +import org.netbeans.modules.csl.api.EditList;
  119.54 +import org.netbeans.modules.csl.api.Hint;
  119.55 +import org.netbeans.modules.csl.api.HintFix;
  119.56 +import org.netbeans.modules.csl.api.HintSeverity;
  119.57 +import org.netbeans.modules.csl.api.OffsetRange;
  119.58 +import org.netbeans.modules.csl.api.PreviewableFix;
  119.59 +import org.netbeans.modules.csl.api.RuleContext;
  119.60 +import org.netbeans.modules.csl.spi.GsfUtilities;
  119.61 +import org.netbeans.modules.editor.indent.api.IndentUtils;
  119.62 +import org.netbeans.modules.python.source.PythonParserResult;
  119.63 +import org.openide.util.Exceptions;
  119.64 +import org.openide.util.NbBundle;
  119.65 +import org.python.antlr.PythonTree;
  119.66 +import org.python.antlr.ast.ClassDef;
  119.67 +import org.python.antlr.ast.FunctionDef;
  119.68 +
  119.69 +/**
  119.70 + * Offer to create docstrings.
  119.71 + * @todo Handle modules?
  119.72 + * @todo Handle parameter tags (for epydoc etc)
  119.73 + *
  119.74 + * @author Tor Norbye
  119.75 + */
  119.76 +public class CreateDocString extends PythonAstRule {
  119.77 +    @Override
  119.78 +    public Set<Class> getKinds() {
  119.79 +        Set<Class> classes = new HashSet<>();
  119.80 +        classes.add(FunctionDef.class);
  119.81 +        classes.add(ClassDef.class);
  119.82 +
  119.83 +        return classes;
  119.84 +    }
  119.85 +
  119.86 +    @Override
  119.87 +    public void run(PythonRuleContext context, List<Hint> result) {
  119.88 +
  119.89 +        PythonTree node = context.node;
  119.90 +        if (PythonAstUtils.getDocumentationNode(node) != null) {
  119.91 +            return;
  119.92 +        }
  119.93 +
  119.94 +        // Create new fix
  119.95 +        PythonParserResult info = (PythonParserResult) context.parserResult;
  119.96 +        OffsetRange astOffsets = PythonAstUtils.getNameRange(info, node);
  119.97 +        OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
  119.98 +        BaseDocument doc = context.doc;
  119.99 +        try {
 119.100 +            if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
 119.101 +                    (context.caretOffset == -1 ||
 119.102 +                    Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
 119.103 +                List<HintFix> fixList = new ArrayList<>();
 119.104 +                boolean singleIsDefault = node.getClass() == FunctionDef.class;
 119.105 +                fixList.add(new CreateDocStringFix(context, node, !singleIsDefault));
 119.106 +                fixList.add(new CreateDocStringFix(context, node, singleIsDefault));
 119.107 +                String displayName = getDisplayName();
 119.108 +                Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
 119.109 +                result.add(desc);
 119.110 +            }
 119.111 +        } catch (BadLocationException ex) {
 119.112 +            Exceptions.printStackTrace(ex);
 119.113 +        }
 119.114 +    }
 119.115 +
 119.116 +    @Override
 119.117 +    public String getId() {
 119.118 +        return "CreateDocString"; // NOI18N
 119.119 +    }
 119.120 +
 119.121 +    @Override
 119.122 +    public String getDisplayName() {
 119.123 +        return NbBundle.getMessage(CreateDocString.class, "CreateDocString");
 119.124 +    }
 119.125 +
 119.126 +    @Override
 119.127 +    public String getDescription() {
 119.128 +        return NbBundle.getMessage(CreateDocString.class, "CreateDocStringDesc");
 119.129 +    }
 119.130 +
 119.131 +    @Override
 119.132 +    public boolean getDefaultEnabled() {
 119.133 +        return true;
 119.134 +    }
 119.135 +
 119.136 +    @Override
 119.137 +    public JComponent getCustomizer(Preferences node) {
 119.138 +        return null;
 119.139 +    }
 119.140 +
 119.141 +    @Override
 119.142 +    public boolean appliesTo(RuleContext context) {
 119.143 +        return true;
 119.144 +    }
 119.145 +
 119.146 +    @Override
 119.147 +    public boolean showInTasklist() {
 119.148 +        return false;
 119.149 +    }
 119.150 +
 119.151 +    @Override
 119.152 +    public HintSeverity getDefaultSeverity() {
 119.153 +        return HintSeverity.CURRENT_LINE_WARNING;
 119.154 +    }
 119.155 +
 119.156 +    private static class CreateDocStringFix implements PreviewableFix {
 119.157 +        private final PythonRuleContext context;
 119.158 +        private final PythonTree node;
 119.159 +        private final boolean multiLine;
 119.160 +        private int editListPosition;
 119.161 +
 119.162 +        private CreateDocStringFix(PythonRuleContext context, PythonTree node, boolean multiLine) {
 119.163 +            this.context = context;
 119.164 +            this.node = node;
 119.165 +            this.multiLine = multiLine;
 119.166 +        }
 119.167 +
 119.168 +        @Override
 119.169 +        public String getDescription() {
 119.170 +            return multiLine ? NbBundle.getMessage(CreateDocString.class, "CreateDocStringFixMulti") : NbBundle.getMessage(CreateDocString.class, "CreateDocStringFix");
 119.171 +        }
 119.172 +
 119.173 +        @Override
 119.174 +        public boolean canPreview() {
 119.175 +            return true;
 119.176 +        }
 119.177 +
 119.178 +        @Override
 119.179 +        public EditList getEditList() throws Exception {
 119.180 +            BaseDocument doc = context.doc;
 119.181 +            EditList edits = new EditList(doc);
 119.182 +
 119.183 +            OffsetRange astRange = PythonAstUtils.getRange(node);
 119.184 +            if (astRange != OffsetRange.NONE) {
 119.185 +                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets((PythonParserResult) context.parserResult, astRange);
 119.186 +                if (lexRange != OffsetRange.NONE) {
 119.187 +                    // Find the colon
 119.188 +                    TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPositionedSequence(doc, lexRange.getStart());
 119.189 +                    if (ts != null) {
 119.190 +                        Token<? extends PythonTokenId> token = PythonLexerUtils.findNextIncluding(ts, Collections.singletonList(PythonTokenId.COLON));
 119.191 +                        if (token != null) {
 119.192 +                            int offset = ts.offset();
 119.193 +                            if (offset < lexRange.getEnd()) {
 119.194 +                                int indent = GsfUtilities.getLineIndent(doc, lexRange.getStart()) +
 119.195 +                                        IndentUtils.indentLevelSize(doc);
 119.196 +                                StringBuilder sb = new StringBuilder();
 119.197 +                                sb.append(IndentUtils.createIndentString(doc, indent));
 119.198 +                                int rowEnd = Utilities.getRowEnd(doc, offset) + 1;
 119.199 +                                sb.append("\"\"\""); // NOI18N
 119.200 +                                if (multiLine) {
 119.201 +                                    sb.append("\n"); // NOI18N
 119.202 +                                    sb.append(IndentUtils.createIndentString(doc, indent));
 119.203 +                                }
 119.204 +                                editListPosition = rowEnd + sb.length();
 119.205 +                                if (multiLine) {
 119.206 +                                    sb.append("\n"); // NOI18N
 119.207 +                                    sb.append(IndentUtils.createIndentString(doc, indent));
 119.208 +                                }
 119.209 +                                sb.append("\"\"\"\n"); // NOI18N
 119.210 +                                edits.replace(rowEnd, 0, sb.toString(), false, 0);
 119.211 +                            }
 119.212 +                        }
 119.213 +                    }
 119.214 +                }
 119.215 +            }
 119.216 +
 119.217 +            return edits;
 119.218 +        }
 119.219 +
 119.220 +        @Override
 119.221 +        public void implement() throws Exception {
 119.222 +            EditList edits = getEditList();
 119.223 +
 119.224 +            Position pos = edits.createPosition(editListPosition);
 119.225 +            edits.apply();
 119.226 +            if (pos != null && pos.getOffset() != -1) {
 119.227 +                JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
 119.228 +                if (target != null) {
 119.229 +                    target.setCaretPosition(pos.getOffset());
 119.230 +                }
 119.231 +            }
 119.232 +        }
 119.233 +
 119.234 +        @Override
 119.235 +        public boolean isSafe() {
 119.236 +            return true;
 119.237 +        }
 119.238 +
 119.239 +        @Override
 119.240 +        public boolean isInteractive() {
 119.241 +            return false;
 119.242 +        }
 119.243 +    }
 119.244 +}
   120.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   120.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/Deprecations.java	Mon Sep 21 13:01:16 2015 +0200
   120.3 @@ -0,0 +1,184 @@
   120.4 +/*
   120.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   120.6 + *
   120.7 + * Copyright 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 + * If you wish your version of this file to be governed by only the CDDL
  120.31 + * or only the GPL Version 2, indicate your decision by adding
  120.32 + * "[Contributor] elects to include this software in this distribution
  120.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  120.34 + * single choice of license, a recipient has the option to distribute
  120.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  120.36 + * to extend the choice of license to its licensees as provided above.
  120.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  120.38 + * Version 2 license, then the option applies only if the new code is
  120.39 + * made subject to such option by the copyright holder.
  120.40 + *
  120.41 + * Contributor(s):
  120.42 + *
  120.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  120.44 + */
  120.45 +package org.netbeans.modules.python.hints;
  120.46 +
  120.47 +import java.util.Collections;
  120.48 +import java.util.HashMap;
  120.49 +import java.util.HashSet;
  120.50 +import java.util.List;
  120.51 +import java.util.Map;
  120.52 +import java.util.Set;
  120.53 +import java.util.prefs.Preferences;
  120.54 +import javax.swing.JComponent;
  120.55 +import javax.swing.text.BadLocationException;
  120.56 +import org.netbeans.modules.python.source.PythonAstUtils;
  120.57 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  120.58 +import org.netbeans.editor.BaseDocument;
  120.59 +import org.netbeans.editor.Utilities;
  120.60 +import org.netbeans.modules.csl.api.Hint;
  120.61 +import org.netbeans.modules.csl.api.HintFix;
  120.62 +import org.netbeans.modules.csl.api.HintSeverity;
  120.63 +import org.netbeans.modules.csl.api.OffsetRange;
  120.64 +import org.netbeans.modules.csl.api.RuleContext;
  120.65 +import org.netbeans.modules.python.source.PythonParserResult;
  120.66 +import org.netbeans.modules.python.source.queries.DeprecationQuery;
  120.67 +import org.openide.util.Exceptions;
  120.68 +import org.openide.util.NbBundle;
  120.69 +import org.python.antlr.PythonTree;
  120.70 +import org.python.antlr.ast.Import;
  120.71 +import org.python.antlr.ast.ImportFrom;
  120.72 +import org.python.antlr.ast.alias;
  120.73 +
  120.74 +/**
  120.75 + * Handle deprecaton warnings, for modules listed as obsolete or
  120.76 + * deprecated in PEP4:
  120.77 + *   http://www.python.org/dev/peps/pep-0004/
  120.78 + *
  120.79 + * Todo: Add a hint to enforce this from PEP8:
  120.80 +- Comparisons to singletons like None should always be done with
  120.81 +'is' or 'is not', never the equality operators.
  120.82 + *  In general, see the "Programming Recommendations" list from
  120.83 + *    http://www.python.org/dev/peps/pep-0008/ - there are lots
  120.84 + *    of thins to check from there.  Check the PyLint list as well.
  120.85 + *
  120.86 + *
  120.87 + * @author Tor Norbye
  120.88 + */
  120.89 +public class Deprecations extends PythonAstRule {
  120.90 +
  120.91 +    @Override
  120.92 +    public Set<Class> getKinds() {
  120.93 +        HashSet<Class> kinds = new HashSet<>();
  120.94 +        kinds.add(Import.class);
  120.95 +        kinds.add(ImportFrom.class);
  120.96 +
  120.97 +        return kinds;
  120.98 +    }
  120.99 +
 120.100 +    @Override
 120.101 +    public void run(PythonRuleContext context, List<Hint> result) {
 120.102 +        PythonTree node = context.node;
 120.103 +        if (node instanceof Import) {
 120.104 +            Import imp = (Import)node;
 120.105 +            List<alias> names = imp.getInternalNames();
 120.106 +            if (names != null) {
 120.107 +                for (alias alias : names) {
 120.108 +                    String name = alias.getInternalName();
 120.109 +                    if (DeprecationQuery.isDeprecatedModule(name)) {
 120.110 +                        addDeprecation(name, DeprecationQuery.getDeprecatedModuleDescription(name), context, result);
 120.111 +                    }
 120.112 +                }
 120.113 +            }
 120.114 +        } else {
 120.115 +            assert node instanceof ImportFrom;
 120.116 +            ImportFrom imp = (ImportFrom)node;
 120.117 +            String name = imp.getInternalModule();
 120.118 +            if (DeprecationQuery.isDeprecatedModule(name)) {
 120.119 +                addDeprecation(name, DeprecationQuery.getDeprecatedModuleDescription(name), context, result);
 120.120 +            }
 120.121 +        }
 120.122 +    }
 120.123 +
 120.124 +    private void addDeprecation(String module, String rationale, PythonRuleContext context, List<Hint> result) {
 120.125 +        PythonParserResult info = (PythonParserResult) context.parserResult;
 120.126 +        OffsetRange astOffsets = PythonAstUtils.getNameRange(info, context.node);
 120.127 +        OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
 120.128 +        BaseDocument doc = context.doc;
 120.129 +        try {
 120.130 +            if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
 120.131 +                    (context.caretOffset == -1 ||
 120.132 +                    Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
 120.133 +                List<HintFix> fixList = Collections.emptyList();
 120.134 +                String displayName;
 120.135 +                if (rationale.length() > 0) {
 120.136 +                    displayName = NbBundle.getMessage(Deprecations.class, "DeprecationsMsgDetail", module, rationale);
 120.137 +                } else {
 120.138 +                    displayName = NbBundle.getMessage(Deprecations.class, "DeprecationsMsg", module);
 120.139 +                }
 120.140 +                Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
 120.141 +                result.add(desc);
 120.142 +            }
 120.143 +        } catch (BadLocationException ex) {
 120.144 +            Exceptions.printStackTrace(ex);
 120.145 +        }
 120.146 +    }
 120.147 +
 120.148 +    @Override
 120.149 +    public String getId() {
 120.150 +        return "Deprecations"; // NOI18N
 120.151 +    }
 120.152 +
 120.153 +    @Override
 120.154 +    public String getDisplayName() {
 120.155 +        return NbBundle.getMessage(Deprecations.class, "Deprecations");
 120.156 +    }
 120.157 +
 120.158 +    @Override
 120.159 +    public String getDescription() {
 120.160 +        return NbBundle.getMessage(Deprecations.class, "DeprecationsDesc");
 120.161 +    }
 120.162 +
 120.163 +    @Override
 120.164 +    public boolean getDefaultEnabled() {
 120.165 +        return true;
 120.166 +    }
 120.167 +
 120.168 +    @Override
 120.169 +    public JComponent getCustomizer(Preferences node) {
 120.170 +        return null;
 120.171 +    }
 120.172 +
 120.173 +    @Override
 120.174 +    public boolean appliesTo(RuleContext context) {
 120.175 +        return true;
 120.176 +    }
 120.177 +
 120.178 +    @Override
 120.179 +    public boolean showInTasklist() {
 120.180 +        return true;
 120.181 +    }
 120.182 +
 120.183 +    @Override
 120.184 +    public HintSeverity getDefaultSeverity() {
 120.185 +        return HintSeverity.WARNING;
 120.186 +    }
 120.187 +}
   121.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   121.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/ExtractCode.java	Mon Sep 21 13:01:16 2015 +0200
   121.3 @@ -0,0 +1,759 @@
   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 + * Contributor(s):
  121.31 + *
  121.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  121.33 + */
  121.34 +package org.netbeans.modules.python.hints;
  121.35 +
  121.36 +import java.util.ArrayList;
  121.37 +import java.util.Collections;
  121.38 +import java.util.HashSet;
  121.39 +import java.util.List;
  121.40 +import java.util.Set;
  121.41 +import java.util.prefs.Preferences;
  121.42 +import javax.swing.JComponent;
  121.43 +import javax.swing.text.JTextComponent;
  121.44 +import org.netbeans.editor.BaseDocument;
  121.45 +import org.netbeans.editor.Utilities;
  121.46 +import org.netbeans.modules.csl.api.EditList;
  121.47 +import org.netbeans.modules.csl.api.EditRegions;
  121.48 +import org.netbeans.modules.csl.api.Hint;
  121.49 +import org.netbeans.modules.csl.api.HintFix;
  121.50 +import org.netbeans.modules.csl.api.HintSeverity;
  121.51 +import org.netbeans.modules.csl.api.OffsetRange;
  121.52 +import org.netbeans.modules.csl.api.PreviewableFix;
  121.53 +import org.netbeans.modules.csl.api.RuleContext;
  121.54 +import org.netbeans.modules.csl.spi.GsfUtilities;
  121.55 +import org.netbeans.modules.editor.indent.api.IndentUtils;
  121.56 +import org.netbeans.modules.python.source.AstPath;
  121.57 +import org.netbeans.modules.python.source.PythonAstUtils;
  121.58 +import org.netbeans.modules.python.source.PythonParserResult;
  121.59 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  121.60 +import org.openide.util.Exceptions;
  121.61 +import org.openide.util.NbBundle;
  121.62 +import org.python.antlr.PythonTree;
  121.63 +import org.python.antlr.Visitor;
  121.64 +import org.python.antlr.ast.Assert;
  121.65 +import org.python.antlr.ast.Assign;
  121.66 +import org.python.antlr.ast.AugAssign;
  121.67 +import org.python.antlr.ast.Break;
  121.68 +import org.python.antlr.ast.Call;
  121.69 +import org.python.antlr.ast.ClassDef;
  121.70 +import org.python.antlr.ast.Continue;
  121.71 +import org.python.antlr.ast.Delete;
  121.72 +import org.python.antlr.ast.For;
  121.73 +import org.python.antlr.ast.FunctionDef;
  121.74 +import org.python.antlr.ast.Global;
  121.75 +import org.python.antlr.ast.If;
  121.76 +import org.python.antlr.ast.IfExp;
  121.77 +import org.python.antlr.ast.Import;
  121.78 +import org.python.antlr.ast.ImportFrom;
  121.79 +import org.python.antlr.ast.Module;
  121.80 +import org.python.antlr.ast.Name;
  121.81 +import org.python.antlr.ast.Num;
  121.82 +import org.python.antlr.ast.Pass;
  121.83 +import org.python.antlr.ast.Print;
  121.84 +import org.python.antlr.ast.Raise;
  121.85 +import org.python.antlr.ast.Return;
  121.86 +import org.python.antlr.ast.Str;
  121.87 +import org.python.antlr.ast.Suite;
  121.88 +import org.python.antlr.ast.TryExcept;
  121.89 +import org.python.antlr.ast.TryFinally;
  121.90 +import org.python.antlr.ast.Tuple;
  121.91 +import org.python.antlr.ast.While;
  121.92 +import org.python.antlr.ast.With;
  121.93 +import org.python.antlr.ast.Yield;
  121.94 +
  121.95 +/**
  121.96 + * Offer to introduce method/variable/constant
  121.97 + * @todo There is no need to pass in class or top level constants to code fragments
  121.98 + * @todo Handle flow control: If a code fragment contains an early return, figure out
  121.99 + *   how to pass that information back to the method callsite and do something clever,
 121.100 + *   for example pass back a to-return flag which returns the same value
 121.101 + * @todo Unit tests must check instant rename as well!
 121.102 + *
 121.103 + * @author Tor Norbye
 121.104 + */
 121.105 +public class ExtractCode extends PythonSelectionRule {
 121.106 +    //private static final int NOT_APPLICABLE = 0;
 121.107 +    private static final int INTRODUCE_METHOD = 1;
 121.108 +    private static final int INTRODUCE_VARIABLE = 2;
 121.109 +    private static final int INTRODUCE_CONSTANT = 4;
 121.110 +    private static final int INTRODUCE_FIELD = 8;
 121.111 +    private static final int NON_EXPRESSIONS = INTRODUCE_VARIABLE | INTRODUCE_FIELD | INTRODUCE_CONSTANT;
 121.112 +    private static final int ALL = ~0;
 121.113 +
 121.114 +    @Override
 121.115 +    protected int getApplicability(PythonRuleContext context, PythonTree root, OffsetRange astRange) {
 121.116 +        return ApplicabilityVisitor.getType(root, astRange);
 121.117 +    }
 121.118 +
 121.119 +    @Override
 121.120 +    public void run(PythonRuleContext context, List<Hint> result, OffsetRange range, int applicability) {
 121.121 +        int start = range.getStart();
 121.122 +        int end = range.getEnd();
 121.123 +
 121.124 +// HACK: Only extract method works at this point
 121.125 +        applicability = applicability & INTRODUCE_METHOD;
 121.126 +
 121.127 +
 121.128 +        // Adjust the fix range to be right around the dot so that the light bulb ends up
 121.129 +        // on the same line as the caret and alt-enter works
 121.130 +        JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
 121.131 +        if (target != null) {
 121.132 +            int dot = target.getCaret().getDot();
 121.133 +            range = new OffsetRange(dot, dot);
 121.134 +        }
 121.135 +
 121.136 +        List<HintFix> fixList = new ArrayList<>(3);
 121.137 +        if ((applicability & INTRODUCE_METHOD) != 0) {
 121.138 +            fixList.add(new ExtractCodeFix(context, start, end, INTRODUCE_METHOD));
 121.139 +        }
 121.140 +        if ((applicability & INTRODUCE_VARIABLE) != 0) {
 121.141 +            fixList.add(new ExtractCodeFix(context, start, end, INTRODUCE_VARIABLE));
 121.142 +        }
 121.143 +        if ((applicability & INTRODUCE_CONSTANT) != 0) {
 121.144 +            fixList.add(new ExtractCodeFix(context, start, end, INTRODUCE_CONSTANT));
 121.145 +        }
 121.146 +        if ((applicability & INTRODUCE_FIELD) != 0) {
 121.147 +            fixList.add(new ExtractCodeFix(context, start, end, INTRODUCE_FIELD));
 121.148 +        }
 121.149 +        if (fixList.size() > 0) {
 121.150 +            String displayName = getDisplayName();
 121.151 +            Hint desc = new Hint(this, displayName, context.parserResult.getSnapshot().getSource().getFileObject(),
 121.152 +                    range, fixList, 490);
 121.153 +            result.add(desc);
 121.154 +        }
 121.155 +    }
 121.156 +
 121.157 +    @Override
 121.158 +    public boolean appliesTo(RuleContext context) {
 121.159 +        return true;
 121.160 +    }
 121.161 +
 121.162 +    @Override
 121.163 +    public String getDisplayName() {
 121.164 +        return NbBundle.getMessage(ExtractCode.class, "ExtractCode");
 121.165 +    }
 121.166 +
 121.167 +    @Override
 121.168 +    public String getId() {
 121.169 +        return "ExtractCode"; // NOI18N
 121.170 +    }
 121.171 +
 121.172 +    @Override
 121.173 +    public String getDescription() {
 121.174 +        return "";
 121.175 +    }
 121.176 +
 121.177 +    @Override
 121.178 +    public boolean getDefaultEnabled() {
 121.179 +        return true;
 121.180 +    }
 121.181 +
 121.182 +    @Override
 121.183 +    public JComponent getCustomizer(Preferences node) {
 121.184 +        return null;
 121.185 +    }
 121.186 +
 121.187 +    @Override
 121.188 +    public boolean showInTasklist() {
 121.189 +        return false;
 121.190 +    }
 121.191 +
 121.192 +    @Override
 121.193 +    public HintSeverity getDefaultSeverity() {
 121.194 +        return HintSeverity.CURRENT_LINE_WARNING;
 121.195 +    }
 121.196 +
 121.197 +    private static class ExtractCodeFix implements PreviewableFix {
 121.198 +        private final PythonRuleContext context;
 121.199 +        //private Position callSitePos;
 121.200 +        //private Position extractedPos;
 121.201 +        private int finalCallSiteOffset;
 121.202 +        private int finalExtractedSiteOffset;
 121.203 +        ;
 121.204 +        private final int type;
 121.205 +        private final int start;
 121.206 +        private final int end;
 121.207 +        private String newName;
 121.208 +
 121.209 +        private ExtractCodeFix(PythonRuleContext context,
 121.210 +                int start, int end, int type) {
 121.211 +            this.context = context;
 121.212 +
 121.213 +            OffsetRange range = PythonLexerUtils.narrow(context.doc, new OffsetRange(start, end), false);
 121.214 +            this.start = range.getStart();
 121.215 +            this.end = range.getEnd();
 121.216 +
 121.217 +            this.type = type;
 121.218 +        }
 121.219 +
 121.220 +        @Override
 121.221 +        public String getDescription() {
 121.222 +            switch (type) {
 121.223 +            case INTRODUCE_VARIABLE:
 121.224 +                return NbBundle.getMessage(CreateDocString.class, "IntroduceVariable");
 121.225 +            case INTRODUCE_CONSTANT:
 121.226 +                return NbBundle.getMessage(CreateDocString.class, "IntroduceConstant");
 121.227 +            case INTRODUCE_METHOD:
 121.228 +                return NbBundle.getMessage(CreateDocString.class, "IntroduceMethod");
 121.229 +            case INTRODUCE_FIELD:
 121.230 +                return NbBundle.getMessage(CreateDocString.class, "IntroduceField");
 121.231 +            default:
 121.232 +                throw new IllegalArgumentException();
 121.233 +            }
 121.234 +        }
 121.235 +
 121.236 +        @Override
 121.237 +        public boolean canPreview() {
 121.238 +            return true;
 121.239 +        }
 121.240 +
 121.241 +        @Override
 121.242 +        public EditList getEditList() throws Exception {
 121.243 +            BaseDocument doc = context.doc;
 121.244 +            PythonParserResult info = (PythonParserResult) context.parserResult;
 121.245 +            EditList edits = new EditList(doc);
 121.246 +
 121.247 +            int extractedOffset = doc.getLength();
 121.248 +            int prevFunctionOffset = 0;
 121.249 +            PythonTree root = PythonAstUtils.getRoot(info);
 121.250 +
 121.251 +            OffsetRange narrowed = PythonLexerUtils.narrow(doc, new OffsetRange(start, end), true);
 121.252 +
 121.253 +            int astStart = PythonAstUtils.getAstOffset(info, narrowed != OffsetRange.NONE ? narrowed.getStart() : start);
 121.254 +            int astEnd = PythonAstUtils.getAstOffset(info, narrowed != OffsetRange.NONE ? narrowed.getEnd() : end);
 121.255 +            if (astStart == -1 || astEnd == -1) {
 121.256 +                return edits;
 121.257 +            }
 121.258 +            AstPath startPath = AstPath.get(root, astStart);
 121.259 +            AstPath endPath = AstPath.get(root, astEnd);
 121.260 +            PythonTree localScope = PythonAstUtils.getLocalScope(startPath);
 121.261 +            if (localScope != null) {
 121.262 +                OffsetRange astRange = PythonAstUtils.getRange(localScope);
 121.263 +                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 121.264 +                if (lexRange != OffsetRange.NONE) {
 121.265 +                    extractedOffset = lexRange.getEnd();
 121.266 +
 121.267 +                    // Function end offsets are a bit sloppy so try to deal with that
 121.268 +                    int firstNonWhite = Utilities.getRowFirstNonWhite(doc, Math.min(extractedOffset, doc.getLength()));
 121.269 +                    if (firstNonWhite == -1 || extractedOffset <= firstNonWhite) {
 121.270 +                        extractedOffset = Utilities.getRowStart(doc, extractedOffset);
 121.271 +                    }
 121.272 +
 121.273 +                    prevFunctionOffset = lexRange.getStart();
 121.274 +                    if (extractedOffset > doc.getLength()) {
 121.275 +                        extractedOffset = doc.getLength();
 121.276 +                    }
 121.277 +                }
 121.278 +            }
 121.279 +            int callSiteOffset = start;
 121.280 +            int callSiteReplaceLength = end - start;
 121.281 +
 121.282 +            int indentSize = IndentUtils.indentLevelSize(doc);
 121.283 +            int lineStart = Utilities.getRowStart(doc, prevFunctionOffset);
 121.284 +            int initialIndent = IndentUtils.lineIndent(doc, lineStart);
 121.285 +            String initialIndentStr = IndentUtils.createIndentString(doc, initialIndent);
 121.286 +
 121.287 +            newName = "new_name"; // TODO - localize!
 121.288 +
 121.289 +            // Compute input/output arguments
 121.290 +            PythonTree startNode = startPath.leaf();
 121.291 +            PythonTree endNode = endPath.leaf();
 121.292 +
 121.293 +            InputOutputFinder finder = new InputOutputFinder(startNode, endNode, Collections.<PythonTree>emptyList());
 121.294 +            finder.traverse(localScope);
 121.295 +            List<String> inParams = new ArrayList<>(finder.getInputVars());
 121.296 +            List<String> outParams = new ArrayList<>(finder.getOutputVars());
 121.297 +            Collections.sort(inParams);
 121.298 +            Collections.sort(outParams);
 121.299 +
 121.300 +            ClassDef cls = PythonAstUtils.getClassDef(startPath);
 121.301 +
 121.302 +            // Adjust the insert location in case we are at the top level
 121.303 +            if (cls == null && PythonAstUtils.getFuncDef(startPath) == null) {
 121.304 +                extractedOffset = -1;
 121.305 +                PythonTree top = startPath.topModuleLevel();
 121.306 +                if (top != null) {
 121.307 +                    OffsetRange astRange = PythonAstUtils.getRange(top);
 121.308 +                    extractedOffset = PythonLexerUtils.getLexerOffset(info, astRange.getStart());
 121.309 +                }
 121.310 +
 121.311 +                // We're at the top level - I can't insert the function -after- the current function
 121.312 +                // because that will result in a runtime error
 121.313 +                if (extractedOffset == -1) {
 121.314 +                    extractedOffset = Utilities.getRowStart(doc, Math.min(doc.getLength(), start));
 121.315 +                }
 121.316 +            }
 121.317 +
 121.318 +            String extractedCode = null;
 121.319 +            int extractedSiteDelta = 0;
 121.320 +            if (type == INTRODUCE_METHOD) {
 121.321 +                StringBuilder sb = new StringBuilder();
 121.322 +                if (Utilities.getRowStart(doc, Math.min(extractedOffset, doc.getLength())) < extractedOffset) {
 121.323 +                    sb.append("\n"); // NOI18N
 121.324 +                }
 121.325 +                sb.append("\n"); // NOI18N
 121.326 +                sb.append(initialIndentStr);
 121.327 +                sb.append("def "); // NOI18N
 121.328 +                extractedSiteDelta = sb.length();
 121.329 +                sb.append(newName);
 121.330 +                sb.append("("); // NOI18N
 121.331 +                if (cls != null) {
 121.332 +                    sb.append("self"); // NOI18N
 121.333 +                    if (inParams.size() > 0) {
 121.334 +                        sb.append(", "); // NOI18N
 121.335 +                    }
 121.336 +                }
 121.337 +                boolean first = true;
 121.338 +                for (String param : inParams) {
 121.339 +                    if (first) {
 121.340 +                        first = false;
 121.341 +                    } else {
 121.342 +                        sb.append(", "); // NOI18N
 121.343 +                    }
 121.344 +                    sb.append(param);
 121.345 +                }
 121.346 +                sb.append("):\n"); // NOI18N
 121.347 +
 121.348 +                // Copy in the extracted code
 121.349 +                int firstIndent = IndentUtils.lineIndent(doc, Utilities.getRowStart(doc, start));
 121.350 +                for (int offset = start; offset < end; offset = Utilities.getRowEnd(doc, offset) + 1) {
 121.351 +                    // TODO - handle multiline literal strings correctly!!!
 121.352 +                    if (!(Utilities.isRowEmpty(doc, offset) || Utilities.isRowWhite(doc, offset))) {
 121.353 +                        int lineIndent = IndentUtils.lineIndent(doc, Utilities.getRowStart(doc, offset));
 121.354 +                        int newIndent = (lineIndent - firstIndent) + initialIndent + indentSize;
 121.355 +                        if (newIndent > 0) {
 121.356 +                            sb.append(IndentUtils.createIndentString(doc, newIndent));
 121.357 +                        }
 121.358 +                        int rowFirstNonWhite = Utilities.getRowFirstNonWhite(doc, offset);
 121.359 +                        int rowLastNonWhite = Utilities.getRowLastNonWhite(doc, offset) + 1; // +1: doesn't include last char
 121.360 +                        sb.append(doc.getText(rowFirstNonWhite, rowLastNonWhite - rowFirstNonWhite));
 121.361 +                    }
 121.362 +                    sb.append("\n"); // NOI18N
 121.363 +                }
 121.364 +                sb.append("\n");
 121.365 +
 121.366 +                if (outParams.size() > 0) {
 121.367 +                    sb.append(IndentUtils.createIndentString(doc, initialIndent + indentSize));
 121.368 +                    sb.append("return "); // NOI18N
 121.369 +                    first = true;
 121.370 +                    for (String param : outParams) {
 121.371 +                        if (first) {
 121.372 +                            first = false;
 121.373 +                        } else {
 121.374 +                            // No spaces in the comma list for return tuples
 121.375 +                            sb.append(","); // NOI18N
 121.376 +                        }
 121.377 +                        sb.append(param);
 121.378 +                    }
 121.379 +                    sb.append("\n\n"); // NOI18N
 121.380 +                }
 121.381 +
 121.382 +                // Insert the extracted code at the end
 121.383 +                extractedCode = sb.toString();
 121.384 +            } else {
 121.385 +                assert (type == INTRODUCE_FIELD || type == INTRODUCE_CONSTANT || type == INTRODUCE_VARIABLE);
 121.386 +                throw new RuntimeException("Not yet implemented");
 121.387 +            }
 121.388 +
 121.389 +            // Replace the code at the extract site with just the call
 121.390 +            StringBuilder sb = new StringBuilder();
 121.391 +            if (type == INTRODUCE_METHOD) {
 121.392 +                // Assign to the output variables if any
 121.393 +                if (outParams.size() > 0) {
 121.394 +                    boolean first = true;
 121.395 +                    for (String param : outParams) {
 121.396 +                        if (first) {
 121.397 +                            first = false;
 121.398 +                        } else {
 121.399 +                            // No spaces in the comma list for return tuples
 121.400 +                            sb.append(","); // NOI18N
 121.401 +                        }
 121.402 +                        sb.append(param);
 121.403 +                    }
 121.404 +
 121.405 +                    sb.append(" = ");
 121.406 +                }
 121.407 +            } else {
 121.408 +                assert (type == INTRODUCE_FIELD || type == INTRODUCE_CONSTANT || type == INTRODUCE_VARIABLE);
 121.409 +            }
 121.410 +
 121.411 +            int callSiteDelta = sb.length();
 121.412 +            sb.append(newName);
 121.413 +            if (type == INTRODUCE_METHOD) {
 121.414 +                sb.append('(');
 121.415 +                if (cls != null) {
 121.416 +                    sb.append("self"); // NOI18N
 121.417 +                    if (inParams.size() > 0) {
 121.418 +                        sb.append(", "); // NOI18N
 121.419 +                    }
 121.420 +                }
 121.421 +                boolean first = true;
 121.422 +                for (String param : inParams) {
 121.423 +                    if (first) {
 121.424 +                        first = false;
 121.425 +                    } else {
 121.426 +                        sb.append(", "); // NOI18N
 121.427 +                    }
 121.428 +                    sb.append(param);
 121.429 +                }
 121.430 +                sb.append(')');
 121.431 +            }
 121.432 +            String callSiteCode = sb.toString();
 121.433 +
 121.434 +
 121.435 +            // Apply changes
 121.436 +            if (extractedOffset >= callSiteOffset && extractedOffset <= callSiteOffset + callSiteReplaceLength) {
 121.437 +                if (extractedOffset > callSiteOffset) {
 121.438 +                    // We're trying to insert the extracted code segment after the call - that must mean we're
 121.439 +                    // in something like a function
 121.440 +                    edits.replace(callSiteOffset, callSiteReplaceLength, callSiteCode + extractedCode, false, 0);
 121.441 +
 121.442 +                    // Work around bug in Document.Position
 121.443 +                    //extractedPos = edits.createPosition(callSiteOffset+callSiteCode.length()+extractedSiteDelta, Bias.Forward);
 121.444 +                    //callSitePos = edits.createPosition(callSiteOffset+callSiteDelta, Bias.Forward);
 121.445 +                    finalCallSiteOffset = callSiteOffset + callSiteDelta;
 121.446 +                    finalExtractedSiteOffset = callSiteOffset + callSiteCode.length() + extractedSiteDelta;
 121.447 +                } else {
 121.448 +                    edits.replace(callSiteOffset, callSiteReplaceLength, extractedCode + callSiteCode, false, 0);
 121.449 +
 121.450 +                    // Work around bug in Document.Position
 121.451 +                    //extractedPos = edits.createPosition(callSiteOffset+extractedSiteDelta, Bias.Forward);
 121.452 +                    //callSitePos = edits.createPosition(callSiteOffset+extractedCode.length()+callSiteDelta, Bias.Forward);
 121.453 +                    finalCallSiteOffset = callSiteOffset + extractedCode.length() + callSiteDelta;
 121.454 +                    finalExtractedSiteOffset = callSiteOffset + extractedSiteDelta;
 121.455 +                }
 121.456 +            } else {
 121.457 +                edits.replace(extractedOffset, 0, extractedCode, false, 1);
 121.458 +                edits.replace(callSiteOffset, callSiteReplaceLength, callSiteCode, false, 0);
 121.459 +
 121.460 +                // There's a bug document/editlist position code - the offsets aren't updated on my
 121.461 +                // edits! For now just compute the offsets directly since we know the exact edits applied
 121.462 +                //extractedPos = edits.createPosition(extractedOffset+extractedSiteDelta, Bias.Backward);
 121.463 +                //callSitePos = edits.createPosition(callSiteOffset+callSiteDelta, Bias.Backward);
 121.464 +                if (extractedOffset < callSiteOffset) {
 121.465 +                    finalCallSiteOffset = callSiteOffset + callSiteDelta + extractedCode.length();
 121.466 +                    finalExtractedSiteOffset = extractedOffset + extractedSiteDelta;
 121.467 +                } else {
 121.468 +                    finalCallSiteOffset = callSiteOffset + callSiteDelta;
 121.469 +                    finalExtractedSiteOffset = extractedOffset + extractedSiteDelta + callSiteCode.length() - callSiteReplaceLength;
 121.470 +                }
 121.471 +            }
 121.472 +
 121.473 +            return edits;
 121.474 +        }
 121.475 +
 121.476 +        @Override
 121.477 +        public void implement() throws Exception {
 121.478 +            EditList edits = getEditList();
 121.479 +
 121.480 +            edits.apply();
 121.481 +
 121.482 +            // Refactoring isn't necessary here since local variables and block
 121.483 +            // variables are limited to the local scope, so we can accurately just
 121.484 +            // find their positions using the AST and let the user edit them synchronously.
 121.485 +            Set<OffsetRange> ranges = new HashSet<>();
 121.486 +            int length = newName.length();
 121.487 +            ranges.add(new OffsetRange(finalCallSiteOffset, finalCallSiteOffset + length));
 121.488 +            ranges.add(new OffsetRange(finalExtractedSiteOffset, finalExtractedSiteOffset + length));
 121.489 +
 121.490 +            // Initiate synchronous editing:
 121.491 +            EditRegions.getInstance().edit(context.parserResult.getSnapshot().getSource().getFileObject(), ranges, finalExtractedSiteOffset);
 121.492 +        }
 121.493 +
 121.494 +        @Override
 121.495 +        public boolean isSafe() {
 121.496 +            return true;
 121.497 +        }
 121.498 +
 121.499 +        @Override
 121.500 +        public boolean isInteractive() {
 121.501 +            return false;
 121.502 +        }
 121.503 +    }
 121.504 +
 121.505 +    /** @todo Prune search in traverse, ala AstPath.
 121.506 +     *  @todo Build up start and end AstPaths.
 121.507 +     */
 121.508 +    private static class ApplicabilityVisitor extends Visitor {
 121.509 +        private boolean applies = true;
 121.510 +        private int disabled;
 121.511 +        private int enabled;
 121.512 +        private final int start;
 121.513 +        private final int end;
 121.514 +
 121.515 +        static int getType(PythonTree root, OffsetRange astRange) {
 121.516 +            ApplicabilityVisitor visitor = new ApplicabilityVisitor(astRange);
 121.517 +            try {
 121.518 +                visitor.visit(root);
 121.519 +            } catch (Exception ex) {
 121.520 +                Exceptions.printStackTrace(ex);
 121.521 +                return 0;
 121.522 +            }
 121.523 +            return visitor.getType();
 121.524 +        }
 121.525 +
 121.526 +        ApplicabilityVisitor(OffsetRange astRange) {
 121.527 +            this.start = astRange.getStart();
 121.528 +            this.end = astRange.getEnd();
 121.529 +        }
 121.530 +
 121.531 +        private void enable(PythonTree node, int mask) {
 121.532 +            if (node.getCharStartIndex() >= start && node.getCharStopIndex() <= end) {
 121.533 +                enabled |= mask;
 121.534 +            }
 121.535 +        }
 121.536 +
 121.537 +        private void disable(PythonTree node, int mask) {
 121.538 +            if (node.getCharStartIndex() >= start && node.getCharStopIndex() <= end) {
 121.539 +                disabled |= mask;
 121.540 +            }
 121.541 +        }
 121.542 +
 121.543 +        public int getType() {
 121.544 +            return enabled & ~disabled;
 121.545 +        }
 121.546 +
 121.547 +        private void maybeBail(PythonTree node) {
 121.548 +            int nodeStart = node.getCharStartIndex();
 121.549 +            int nodeEnd = node.getCharStopIndex();
 121.550 +            if (nodeStart >= start && nodeStart < end) {
 121.551 +                applies = false;
 121.552 +                disable(node, ALL);
 121.553 +            }
 121.554 +            if (nodeEnd > start && nodeEnd < end) {
 121.555 +                applies = false;
 121.556 +                disable(node, ALL);
 121.557 +            }
 121.558 +        }
 121.559 +
 121.560 +        @Override
 121.561 +        public void traverse(PythonTree node) throws Exception {
 121.562 +            if (!applies) {
 121.563 +                return;
 121.564 +            }
 121.565 +
 121.566 +            int nodeStart = node.getCharStartIndex();
 121.567 +            int nodeStop = node.getCharStopIndex();
 121.568 +            //if (!(nodeStop < start || nodeStart > end)) {
 121.569 +            if (nodeStop >= start && nodeStart <= end) {
 121.570 +                super.traverse(node);
 121.571 +            }
 121.572 +        }
 121.573 +
 121.574 +        @Override
 121.575 +        public Object visitClassDef(ClassDef node) throws Exception {
 121.576 +            maybeBail(node);
 121.577 +            return super.visitClassDef(node);
 121.578 +        }
 121.579 +
 121.580 +        @Override
 121.581 +        public Object visitFunctionDef(FunctionDef node) throws Exception {
 121.582 +            maybeBail(node);
 121.583 +            return super.visitFunctionDef(node);
 121.584 +        }
 121.585 +
 121.586 +        @Override
 121.587 +        public Object visitImport(Import node) throws Exception {
 121.588 +            disable(node, ALL);
 121.589 +            return super.visitImport(node);
 121.590 +        }
 121.591 +
 121.592 +        @Override
 121.593 +        public Object visitImportFrom(ImportFrom node) throws Exception {
 121.594 +            disable(node, ALL);
 121.595 +            return super.visitImportFrom(node);
 121.596 +        }
 121.597 +
 121.598 +        @Override
 121.599 +        public Object visitAssign(Assign node) throws Exception {
 121.600 +            disable(node, NON_EXPRESSIONS);
 121.601 +            disable(node, NON_EXPRESSIONS);
 121.602 +            return super.visitAssign(node);
 121.603 +        }
 121.604 +
 121.605 +        @Override
 121.606 +        public Object visitCall(Call node) throws Exception {
 121.607 +            enable(node, ALL);
 121.608 +            disable(node, INTRODUCE_CONSTANT);
 121.609 +            return super.visitCall(node);
 121.610 +        }
 121.611 +
 121.612 +        @Override
 121.613 +        public Object visitAugAssign(AugAssign node) throws Exception {
 121.614 +            disable(node, NON_EXPRESSIONS);
 121.615 +            return super.visitAugAssign(node);
 121.616 +        }
 121.617 +
 121.618 +        @Override
 121.619 +        public Object visitBreak(Break node) throws Exception {
 121.620 +            disable(node, NON_EXPRESSIONS);
 121.621 +            return super.visitBreak(node);
 121.622 +        }
 121.623 +
 121.624 +        @Override
 121.625 +        public Object visitContinue(Continue node) throws Exception {
 121.626 +            disable(node, NON_EXPRESSIONS);
 121.627 +            return super.visitContinue(node);
 121.628 +        }
 121.629 +
 121.630 +        @Override
 121.631 +        public Object visitDelete(Delete node) throws Exception {
 121.632 +            disable(node, NON_EXPRESSIONS);
 121.633 +            return super.visitDelete(node);
 121.634 +        }
 121.635 +
 121.636 +        @Override
 121.637 +        public Object visitFor(For node) throws Exception {
 121.638 +            disable(node, NON_EXPRESSIONS);
 121.639 +            return super.visitFor(node);
 121.640 +        }
 121.641 +
 121.642 +        @Override
 121.643 +        public Object visitIf(If node) throws Exception {
 121.644 +            disable(node, NON_EXPRESSIONS);
 121.645 +            return super.visitIf(node);
 121.646 +        }
 121.647 +
 121.648 +        @Override
 121.649 +        public Object visitIfExp(IfExp node) throws Exception {
 121.650 +            disable(node, NON_EXPRESSIONS);
 121.651 +            return super.visitIfExp(node);
 121.652 +        }
 121.653 +
 121.654 +        @Override
 121.655 +        public Object visitPrint(Print node) throws Exception {
 121.656 +            disable(node, NON_EXPRESSIONS);
 121.657 +            return super.visitPrint(node);
 121.658 +        }
 121.659 +
 121.660 +        @Override
 121.661 +        public Object visitYield(Yield node) throws Exception {
 121.662 +            disable(node, NON_EXPRESSIONS);
 121.663 +            return super.visitYield(node);
 121.664 +        }
 121.665 +
 121.666 +        @Override
 121.667 +        public Object visitWith(With node) throws Exception {
 121.668 +            disable(node, NON_EXPRESSIONS);
 121.669 +            return super.visitWith(node);
 121.670 +        }
 121.671 +
 121.672 +        @Override
 121.673 +        public Object visitWhile(While node) throws Exception {
 121.674 +            disable(node, NON_EXPRESSIONS);
 121.675 +            return super.visitWhile(node);
 121.676 +        }
 121.677 +
 121.678 +        @Override
 121.679 +        public Object visitTryFinally(TryFinally node) throws Exception {
 121.680 +            disable(node, NON_EXPRESSIONS);
 121.681 +            return super.visitTryFinally(node);
 121.682 +        }
 121.683 +
 121.684 +        @Override
 121.685 +        public Object visitTryExcept(TryExcept node) throws Exception {
 121.686 +            disable(node, NON_EXPRESSIONS);
 121.687 +            return super.visitTryExcept(node);
 121.688 +        }
 121.689 +
 121.690 +        @Override
 121.691 +        public Object visitSuite(Suite node) throws Exception {
 121.692 +            disable(node, NON_EXPRESSIONS);
 121.693 +            return super.visitSuite(node);
 121.694 +        }
 121.695 +
 121.696 +        @Override
 121.697 +        public Object visitReturn(Return node) throws Exception {
 121.698 +//            disable(node, NON_EXPRESSIONS);
 121.699 +            // TODO - handle flow control!!
 121.700 +            disable(node, ALL);
 121.701 +            return super.visitReturn(node);
 121.702 +        }
 121.703 +
 121.704 +        @Override
 121.705 +        public Object visitModule(Module node) throws Exception {
 121.706 +            if (node.getCharStartIndex() > start && node.getCharStopIndex() < end) {
 121.707 +//                disable(node, NON_EXPRESSIONS);
 121.708 +                disable(node, ALL);
 121.709 +            }
 121.710 +            return super.visitModule(node);
 121.711 +        }
 121.712 +
 121.713 +        @Override
 121.714 +        public Object visitPass(Pass node) throws Exception {
 121.715 +            disable(node, NON_EXPRESSIONS);
 121.716 +            return super.visitPass(node);
 121.717 +        }
 121.718 +
 121.719 +        @Override
 121.720 +        public Object visitRaise(Raise node) throws Exception {
 121.721 +            disable(node, NON_EXPRESSIONS);
 121.722 +            return super.visitRaise(node);
 121.723 +        }
 121.724 +
 121.725 +        @Override
 121.726 +        public Object visitAssert(Assert node) throws Exception {
 121.727 +            disable(node, NON_EXPRESSIONS);
 121.728 +            return super.visitAssert(node);
 121.729 +        }
 121.730 +
 121.731 +        @Override
 121.732 +        public Object visitNum(Num node) throws Exception {
 121.733 +            enable(node, ALL);
 121.734 +            return super.visitNum(node);
 121.735 +        }
 121.736 +
 121.737 +        @Override
 121.738 +        public Object visitName(Name node) throws Exception {
 121.739 +            enable(node, ALL);
 121.740 +            return super.visitName(node);
 121.741 +        }
 121.742 +
 121.743 +        @Override
 121.744 +        public Object visitGlobal(Global node) throws Exception {
 121.745 +            enable(node, ALL);
 121.746 +            disable(node, INTRODUCE_CONSTANT);
 121.747 +            return super.visitGlobal(node);
 121.748 +        }
 121.749 +
 121.750 +        @Override
 121.751 +        public Object visitTuple(Tuple node) throws Exception {
 121.752 +            enable(node, ALL);
 121.753 +            return super.visitTuple(node);
 121.754 +        }
 121.755 +
 121.756 +        @Override
 121.757 +        public Object visitStr(Str node) throws Exception {
 121.758 +            enable(node, ALL);
 121.759 +            return super.visitStr(node);
 121.760 +        }
 121.761 +    }
 121.762 +}
   122.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   122.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/InputOutputFinder.java	Mon Sep 21 13:01:16 2015 +0200
   122.3 @@ -0,0 +1,304 @@
   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 + * If you wish your version of this file to be governed by only the CDDL
  122.31 + * or only the GPL Version 2, indicate your decision by adding
  122.32 + * "[Contributor] elects to include this software in this distribution
  122.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  122.34 + * single choice of license, a recipient has the option to distribute
  122.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  122.36 + * to extend the choice of license to its licensees as provided above.
  122.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  122.38 + * Version 2 license, then the option applies only if the new code is
  122.39 + * made subject to such option by the copyright holder.
  122.40 + * 
  122.41 + * Contributor(s):
  122.42 + * 
  122.43 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  122.44 + */
  122.45 +package org.netbeans.modules.python.hints;
  122.46 +
  122.47 +import java.util.HashMap;
  122.48 +import java.util.HashSet;
  122.49 +import java.util.List;
  122.50 +import java.util.Map;
  122.51 +import java.util.Set;
  122.52 +import org.netbeans.modules.python.source.PythonAstUtils;
  122.53 +import org.python.antlr.PythonTree;
  122.54 +import org.python.antlr.Visitor;
  122.55 +import org.python.antlr.ast.Assign;
  122.56 +import org.python.antlr.ast.Call;
  122.57 +import org.python.antlr.ast.FunctionDef;
  122.58 +import org.python.antlr.ast.Name;
  122.59 +import org.python.antlr.base.expr;
  122.60 +
  122.61 +/** 
  122.62 + * This visitor computes the set of input and output variables required by
  122.63 + * a code block for extract method.
  122.64 + * In particular, it tracks the local variable assignments inside the method,
  122.65 + * and checks which are used outside of the method (which would make it an
  122.66 + * output variable) and similarly, which variables are used inside the method
  122.67 + * before getting assigned (which would make it an input variable).
  122.68 + * 
  122.69 + * @author Tor Norbye
  122.70 + */
  122.71 +class InputOutputFinder extends Visitor {
  122.72 +    //private enum When { BEFORE, DURING, AFTER };
  122.73 +    private static final int WHEN_BEFORE = 0;
  122.74 +    private static final int WHEN_DURING = 1;
  122.75 +    private static final int WHEN_AFTER = 2;
  122.76 +    private final PythonTree startNode;
  122.77 +    private final PythonTree endNode;
  122.78 +    private final int startPos;
  122.79 +    private final int endPos;
  122.80 +    private final List<PythonTree> applicableBlocks;
  122.81 +    private int when = WHEN_BEFORE;
  122.82 +    private int ifs;
  122.83 +    //private PythonTree currentBlock;
  122.84 +    //private final List<PythonTree> blockStack = new ArrayList<PythonTree>(); // JDK16: Use Deque
  122.85 +    private Map<PythonTree, UsageScope> blockScopes = new HashMap<>();
  122.86 +    private UsageScope methodScope = new UsageScope(null);
  122.87 +    //private UsageScope blockScope;
  122.88 +    private PythonTree parent;
  122.89 +    private boolean isWriting;
  122.90 +
  122.91 +    /** The node ranges are inclusive */
  122.92 +    InputOutputFinder(PythonTree startNode, PythonTree endNode, List<PythonTree> applicableBlocks) {
  122.93 +        this.startNode = startNode;
  122.94 +        this.endNode = endNode;
  122.95 +        this.applicableBlocks = applicableBlocks;
  122.96 +
  122.97 +        startPos = startNode.getCharStartIndex();
  122.98 +        endPos = endNode.getCharStopIndex();
  122.99 +    }
 122.100 +
 122.101 +    public Set<String> getInputVars() {
 122.102 +        UsageScope scope = methodScope;
 122.103 +        for (UsageScope s : blockScopes.values()) {
 122.104 +            if (s.block != null && !applicableBlocks.contains(s.block)) {
 122.105 +                continue;
 122.106 +            }
 122.107 +            scope.merge(s);
 122.108 +        }
 122.109 +
 122.110 +        Set<String> inputs = new HashSet<>(scope.readDuring);
 122.111 +        // But not read before
 122.112 +        inputs.removeAll(scope.writtenBeforeReadDuring);
 122.113 +
 122.114 +        // Also need to pass in any variables I'm modifying that are read after
 122.115 +        Set<String> outputs = new HashSet<>(scope.writtenDuring);
 122.116 +        outputs.retainAll(scope.readAfter);
 122.117 +        Set<String> extraOutputs = new HashSet<>(scope.writtenBefore);
 122.118 +        extraOutputs.retainAll(outputs);
 122.119 +        // unless they are written before read
 122.120 +        extraOutputs.removeAll(scope.writtenBeforeReadDuring);
 122.121 +        inputs.addAll(extraOutputs);
 122.122 +
 122.123 +        return inputs;
 122.124 +    }
 122.125 +
 122.126 +    public Set<String> getOutputVars() {
 122.127 +        UsageScope scope = methodScope;
 122.128 +        for (UsageScope s : blockScopes.values()) {
 122.129 +            if (s.block != null && !applicableBlocks.contains(s.block)) {
 122.130 +                continue;
 122.131 +            }
 122.132 +            scope.merge(s);
 122.133 +        }
 122.134 +
 122.135 +        Set<String> outputs = new HashSet<>(scope.writtenDuring);
 122.136 +        outputs.retainAll(scope.readAfter);
 122.137 +
 122.138 +        return outputs;
 122.139 +    }
 122.140 +
 122.141 +    @Override
 122.142 +    public Object visitFunctionDef(FunctionDef node) throws Exception {
 122.143 +        // Record the parameters
 122.144 +//        assert when == WHEN_BEFORE; // Is this true when I extract a whole method? I can't do that, right?
 122.145 +        boolean x = true;
 122.146 +        assert x;
 122.147 +
 122.148 +        for (String param : PythonAstUtils.getParameters(node)) {
 122.149 +            methodScope.write(param);
 122.150 +        }
 122.151 +
 122.152 +        return super.visitFunctionDef(node);
 122.153 +    }
 122.154 +
 122.155 +    @SuppressWarnings("unchecked")
 122.156 +    @Override
 122.157 +    public Object visitAssign(Assign node) throws Exception {
 122.158 +        // Visit the right hand side of the assignment first, such
 122.159 +        // that with for example
 122.160 +        //    x = x + 1
 122.161 +        // we treat this as a read of x, before a write of x.
 122.162 +        // The Assign.traverse() implementation will do the targets first,
 122.163 +        // so we explicitly do it here in the opposite order instead...
 122.164 +
 122.165 +        if (when == WHEN_BEFORE && node.getCharStartIndex() >= startPos) {
 122.166 +            when = WHEN_DURING;
 122.167 +        }
 122.168 +        int oldWhen = when;
 122.169 +        
 122.170 +        expr nodeValue = node.getInternalValue();
 122.171 +        if (nodeValue != null) {
 122.172 +            nodeValue.accept(this);
 122.173 +        }
 122.174 +        int newWhen = when;
 122.175 +        when = oldWhen;
 122.176 +
 122.177 +        boolean oldWriting = isWriting;
 122.178 +        try {
 122.179 +            isWriting = true;
 122.180 +            List<expr> targets = node.getInternalTargets();
 122.181 +            if (targets != null) {
 122.182 +                for (expr expr : targets) {
 122.183 +                    if (expr != null) {
 122.184 +                        expr.accept(this);
 122.185 +                    }
 122.186 +                }
 122.187 +            }
 122.188 +        } finally {
 122.189 +            isWriting = oldWriting;
 122.190 +        }
 122.191 +
 122.192 +        when = newWhen;
 122.193 +
 122.194 +        return node;
 122.195 +    }
 122.196 +
 122.197 +    @Override
 122.198 +    public Object visitName(Name node) throws Exception {
 122.199 +        if (parent instanceof Call && ((Call)parent).getInternalFunc() == node) { // Name in a call is the call name, not a variable
 122.200 +            return super.visitName(node);
 122.201 +        }
 122.202 +
 122.203 +        methodScope.read(node.getInternalId());
 122.204 +
 122.205 +        return super.visitName(node);
 122.206 +    }
 122.207 +
 122.208 +    @Override
 122.209 +    public void traverse(PythonTree node) throws Exception {
 122.210 +        if (node == startNode) {
 122.211 +            when = WHEN_DURING;
 122.212 +        }
 122.213 +
 122.214 +        PythonTree oldParent = parent;
 122.215 +        parent = node;
 122.216 +        super.traverse(node);
 122.217 +        parent = oldParent;
 122.218 +
 122.219 +        if (node == endNode) {
 122.220 +            when = WHEN_AFTER;
 122.221 +        }
 122.222 +
 122.223 +    }
 122.224 +
 122.225 +    private class UsageScope {
 122.226 +        UsageScope(PythonTree block) {
 122.227 +            this.block = block;
 122.228 +        }
 122.229 +
 122.230 +        private void read(String name) {
 122.231 +            // No need to pass class references or constants in/out
 122.232 +            // TODO: Make this smarter such that what it really does
 122.233 +            // is ignore any variables that aren't defined locally - so
 122.234 +            // global variables for example aren't passed in since they
 122.235 +            // can -also- be accessed from the extracted method.
 122.236 +            if (Character.isUpperCase(name.charAt(0))) {
 122.237 +                return;
 122.238 +            }
 122.239 +
 122.240 +            if (isWriting) {
 122.241 +                // A read in the AST for example on the left hand side of an
 122.242 +                // assignment is really a write
 122.243 +                write(name);
 122.244 +                return;
 122.245 +            }
 122.246 +
 122.247 +            if (when == WHEN_DURING) {
 122.248 +                if (!writtenBeforeReadDuring.contains(name)) {
 122.249 +                    readDuring.add(name);
 122.250 +                }
 122.251 +            } else if (when == WHEN_AFTER) {
 122.252 +                // I don't want a reassignment of the variable before it's been
 122.253 +                // read to count as a usage of the result from the fragment
 122.254 +                if (!writtenAfter.contains(name)) {
 122.255 +                    readAfter.add(name);
 122.256 +                }
 122.257 +            }
 122.258 +        }
 122.259 +
 122.260 +        private void write(String name) {
 122.261 +            // No need to pass class references or constants in/out
 122.262 +            // TODO: Make this smarter such that what it really does
 122.263 +            // is ignore any variables that aren't defined locally - so
 122.264 +            // global variables for example aren't passed in since they
 122.265 +            // can -also- be accessed from the extracted method.
 122.266 +            if (Character.isUpperCase(name.charAt(0))) {
 122.267 +                return;
 122.268 +            }
 122.269 +
 122.270 +            if (when == WHEN_BEFORE) {
 122.271 +                writtenBefore.add(name);
 122.272 +            } else if (when == WHEN_DURING) {
 122.273 +                writtenDuring.add(name);
 122.274 +                if (ifs == 0 && !readDuring.contains(name)) {
 122.275 +                    writtenBeforeReadDuring.add(name);
 122.276 +                }
 122.277 +            } else if (when == WHEN_AFTER) {
 122.278 +                if (ifs == 0 && !readAfter.contains(name)) {
 122.279 +                    writtenAfter.add(name);
 122.280 +                }
 122.281 +            }
 122.282 +        }
 122.283 +
 122.284 +        private void merge(UsageScope other) {
 122.285 +            writtenBefore.addAll(other.writtenBefore);
 122.286 +            readDuring.addAll(other.readDuring);
 122.287 +            writtenDuring.addAll(other.writtenDuring);
 122.288 +            writtenBeforeReadDuring.addAll(other.writtenBeforeReadDuring);
 122.289 +            writtenAfter.addAll(other.writtenAfter);
 122.290 +            readAfter.addAll(other.readAfter);
 122.291 +        }
 122.292 +        /** Block, or null if it's the local method */
 122.293 +        private PythonTree block;
 122.294 +        /** Variables that exist in scope before the code fragment */
 122.295 +        private final Set<String> writtenBefore = new HashSet<>();
 122.296 +        /** Variables that are read during the code fragment */
 122.297 +        private final Set<String> readDuring = new HashSet<>(); // rename readBeforeWrittenDuring
 122.298 +        /** Variables that are written to during the code fragment */
 122.299 +        private final Set<String> writtenDuring = new HashSet<>();
 122.300 +        /** Variables that are written to during the code fragment */
 122.301 +        private final Set<String> writtenBeforeReadDuring = new HashSet<>();
 122.302 +        /** Variables that are written PRIOR TO A READ OF THE SAME VAR after the code fragment */
 122.303 +        private final Set<String> writtenAfter = new HashSet<>(); // rename writtenBeforeReadAfter
 122.304 +        /** Variables that are read (prior to a write) after the code fragment */
 122.305 +        private final Set<String> readAfter = new HashSet<>(); // rename readBeforeWrittenAfter
 122.306 +    }
 122.307 +}
   123.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   123.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/NameRule.java	Mon Sep 21 13:01:16 2015 +0200
   123.3 @@ -0,0 +1,524 @@
   123.4 +/*
   123.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   123.6 + *
   123.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   123.8 + *
   123.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  123.10 + * Other names may be trademarks of their respective owners.
  123.11 + *
  123.12 + * The contents of this file are subject to the terms of either the GNU
  123.13 + * General Public License Version 2 only ("GPL") or the Common
  123.14 + * Development and Distribution License("CDDL") (collectively, the
  123.15 + * "License"). You may not use this file except in compliance with the
  123.16 + * License. You can obtain a copy of the License at
  123.17 + * http://www.netbeans.org/cddl-gplv2.html
  123.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  123.19 + * specific language governing permissions and limitations under the
  123.20 + * License.  When distributing the software, include this License Header
  123.21 + * Notice in each file and include the License file at
  123.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  123.23 + * particular file as subject to the "Classpath" exception as provided
  123.24 + * by Oracle in the GPL Version 2 section of the License file that
  123.25 + * accompanied this code. If applicable, add the following below the
  123.26 + * License Header, with the fields enclosed by brackets [] replaced by
  123.27 + * your own identifying information:
  123.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  123.29 + *
  123.30 + * Contributor(s):
  123.31 + *
  123.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  123.33 + */
  123.34 +package org.netbeans.modules.python.hints;
  123.35 +
  123.36 +import org.netbeans.modules.python.source.NameStyle;
  123.37 +import java.util.ArrayList;
  123.38 +import java.util.Collections;
  123.39 +import java.util.HashSet;
  123.40 +import java.util.List;
  123.41 +import java.util.Set;
  123.42 +import java.util.prefs.Preferences;
  123.43 +import javax.swing.JComponent;
  123.44 +import org.netbeans.editor.BaseDocument;
  123.45 +import org.netbeans.editor.Utilities;
  123.46 +import org.netbeans.modules.csl.api.EditList;
  123.47 +import org.netbeans.modules.csl.api.Hint;
  123.48 +import org.netbeans.modules.csl.api.HintFix;
  123.49 +import org.netbeans.modules.csl.api.HintSeverity;
  123.50 +import org.netbeans.modules.csl.api.OffsetRange;
  123.51 +import org.netbeans.modules.csl.api.PreviewableFix;
  123.52 +import org.netbeans.modules.csl.api.RuleContext;
  123.53 +import org.netbeans.modules.python.source.PythonAstUtils;
  123.54 +import org.netbeans.modules.python.source.PythonParserResult;
  123.55 +import org.netbeans.modules.python.source.PythonUtils;
  123.56 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  123.57 +import org.openide.util.NbBundle;
  123.58 +import org.python.antlr.PythonTree;
  123.59 +import org.python.antlr.ast.ClassDef;
  123.60 +import org.python.antlr.ast.FunctionDef;
  123.61 +import org.python.antlr.ast.Module;
  123.62 +import org.python.antlr.ast.arguments;
  123.63 +
  123.64 +import static org.netbeans.modules.python.source.NameStyle.*;
  123.65 +
  123.66 +/**
  123.67 + * Check names to see if they conform to standard Python conventions.
  123.68 + * These are documented here:
  123.69 + *   http://www.python.org/dev/peps/pep-0008/
  123.70 + * 
  123.71 + * @todo Add fix to rename!
  123.72 + * @todo Implement variable name checking!
  123.73 + * 
  123.74 + * 
  123.75 + * @author Tor Norbye
  123.76 + */
  123.77 +public class NameRule extends PythonAstRule {
  123.78 +    private static final String CLASS_STYLE_NAME = "classStyle"; // NOI18N
  123.79 +    private static final String IGNORED_NAMES = "ignoredNames"; // NOI18N
  123.80 +    private static final String MODULE_STYLE_NAME = "moduleStyle"; // NOI18N
  123.81 +    private static final String FUNCTION_STYLE_NAME = "functionStyle"; // NOI18N
  123.82 +    private static final String SELF_REQUIRED_NAME = "selfRequired"; // NOI18N
  123.83 +    private static final String VARIABLE_STYLE_NAME = "variableStyle"; // NOI18N
  123.84 +    private static NameStyle moduleStyle;
  123.85 +    private static NameStyle functionStyle;
  123.86 +    private static NameStyle classStyle;
  123.87 +    private static NameStyle variableStyle;
  123.88 +    private static String ignoredNames;
  123.89 +    private static boolean selfRequired;
  123.90 +
  123.91 +    public NameRule() {
  123.92 +    }
  123.93 +
  123.94 +    @Override
  123.95 +    public boolean appliesTo(RuleContext context) {
  123.96 +        moduleStyle = null; // Ensure lazy init
  123.97 +
  123.98 +        return true;
  123.99 +    }
 123.100 +
 123.101 +    private static void initializeFromPrefs(PythonRuleContext context, NameRule rule) {
 123.102 +        Preferences pref = context.manager.getPreferences(rule);
 123.103 +        moduleStyle = getModuleNameStyle(pref);
 123.104 +        classStyle = getClassNameStyle(pref);
 123.105 +        functionStyle = getFunctionNameStyle(pref);
 123.106 +        variableStyle = getVariableNameStyle(pref);
 123.107 +        ignoredNames = getIgnoredNames(pref);
 123.108 +        selfRequired = isSelfRequired(pref);
 123.109 +    }
 123.110 +
 123.111 +    @Override
 123.112 +    public Set<Class> getKinds() {
 123.113 +        Set<Class> classes = new HashSet<>();
 123.114 +        classes.add(Module.class);
 123.115 +        classes.add(FunctionDef.class);
 123.116 +        classes.add(ClassDef.class);
 123.117 +
 123.118 +        return classes;
 123.119 +    }
 123.120 +
 123.121 +    @Override
 123.122 +    public void run(PythonRuleContext context, List<Hint> result) {
 123.123 +        if (moduleStyle == null) {
 123.124 +            initializeFromPrefs(context, this);
 123.125 +        }
 123.126 +
 123.127 +        // TODO - check module name!!
 123.128 +
 123.129 +        PythonTree node = context.node;
 123.130 +        if (node instanceof Module) {
 123.131 +            if (moduleStyle != NO_PREFERENCE) {
 123.132 +                String moduleName = PythonUtils.getModuleName(context.parserResult.getSnapshot().getSource().getFileObject());
 123.133 +                if (!moduleStyle.complies(moduleName) && !moduleStyle.complies(moduleName.substring(moduleName.lastIndexOf('.') + 1))) {
 123.134 +                    String typeKey = "Module"; // NOI18N
 123.135 +                    String message = NbBundle.getMessage(NameRule.class, "WrongStyle", moduleName,
 123.136 +                            NbBundle.getMessage(NameRule.class, typeKey),
 123.137 +                            moduleStyle.getDisplayName());
 123.138 +                    List<HintFix> hintFixes = getNameStyleFixes(moduleName, context, moduleStyle, MODULE_STYLE_NAME, typeKey);
 123.139 +                    addError(moduleName, context, message, node, result, hintFixes);
 123.140 +                }
 123.141 +            }
 123.142 +        } else if (node instanceof FunctionDef) {
 123.143 +            FunctionDef def = (FunctionDef)node;
 123.144 +            if (functionStyle != NO_PREFERENCE) {
 123.145 +                if (!functionStyle.complies(def.getInternalName())) {
 123.146 +                    String typeKey = "Function"; // NOI18N
 123.147 +                    String message = NbBundle.getMessage(NameRule.class, "WrongStyle", def.getInternalName(),
 123.148 +                            NbBundle.getMessage(NameRule.class, typeKey),
 123.149 +                            functionStyle.getDisplayName());
 123.150 +                    List<HintFix> hintFixes = getNameStyleFixes(def.getInternalName(), context, functionStyle, FUNCTION_STYLE_NAME, typeKey);
 123.151 +                    addError(def.getInternalName(), context, message, def, result, hintFixes);
 123.152 +                }
 123.153 +            }
 123.154 +
 123.155 +            // Functions should have a first argument of name "self"
 123.156 +            if (selfRequired && !PythonAstUtils.isStaticMethod(def)) {
 123.157 +                arguments args = def.getInternalArgs();
 123.158 +                if (args.getInternalArgs().size() > 0) {
 123.159 +                    String name = PythonAstUtils.getName(args.getInternalArgs().get(0));
 123.160 +                    if (!("self".equals(name) || "cls".equals(name))) { // NOI18N
 123.161 +                        // Make sure it's a class; other methods don't have to
 123.162 +                        if (PythonAstUtils.isClassMethod(context.path, def)) {
 123.163 +                            String message = NbBundle.getMessage(NameRule.class,
 123.164 +                                    // TODO - determine if it should be cls or def
 123.165 +                                    "NameRuleWrongArg", // NOI18N
 123.166 +                                    name);
 123.167 +                            List<HintFix> fixList = new ArrayList<>(2);
 123.168 +                            fixList.add(new SelfParamFix(context, true, def, null));
 123.169 +                            List<String> parameters = PythonAstUtils.getParameters(def);
 123.170 +                            if (parameters.size() > 0) {
 123.171 +                                fixList.add(new SelfParamFix(context, false, def, parameters.get(0)));
 123.172 +                            }
 123.173 +                            addError(null, context, message, args, result, fixList);
 123.174 +                        }
 123.175 +                    }
 123.176 +                } else if (PythonAstUtils.isClassMethod(context.path, def)) {
 123.177 +                    String message = NbBundle.getMessage(NameRule.class,
 123.178 +                            // TODO - determine if it should be cls or def
 123.179 +                            "NameRuleWrongNoArg"); // NOI18N
 123.180 +                    List<HintFix> fixList = Collections.<HintFix>singletonList(new SelfParamFix(context, true, def, null));
 123.181 +                    addError(null, context, message, args, result, fixList);
 123.182 +                }
 123.183 +            }
 123.184 +        } else if (node instanceof ClassDef) {
 123.185 +            if (functionStyle != NO_PREFERENCE) {
 123.186 +                ClassDef def = (ClassDef)node;
 123.187 +                if (!classStyle.complies(def.getInternalName())) {
 123.188 +                    String typeKey = "Class"; // NOI18N
 123.189 +                    String message = NbBundle.getMessage(NameRule.class, "WrongStyle", def.getInternalName(),
 123.190 +                            NbBundle.getMessage(NameRule.class, typeKey),
 123.191 +                            classStyle.getDisplayName());
 123.192 +                    List<HintFix> hintFixes = getNameStyleFixes(def.getInternalName(), context, classStyle, CLASS_STYLE_NAME, typeKey);
 123.193 +                    addError(def.getInternalName(), context, message, def, result, hintFixes);
 123.194 +                }
 123.195 +            }
 123.196 +        }
 123.197 +    }
 123.198 +
 123.199 +    private List<HintFix> getNameStyleFixes(String name, PythonRuleContext context, NameStyle currentStyle, String key, String type) {
 123.200 +        List<HintFix> fixes = new ArrayList<>(5);
 123.201 +
 123.202 +        fixes.add(new IgnoreWordFix(name, this, context));
 123.203 +
 123.204 +        for (NameStyle style : NameStyle.values()) {
 123.205 +            if (style == currentStyle || style == NO_PREFERENCE) {
 123.206 +                continue;
 123.207 +            }
 123.208 +
 123.209 +            if (style.complies(name)) {
 123.210 +                ChangeStyleFix cs = new ChangeStyleFix(this, context, style, key, type);
 123.211 +                fixes.add(cs);
 123.212 +            }
 123.213 +        }
 123.214 +
 123.215 +        // No preference always last
 123.216 +        fixes.add(new ChangeStyleFix(this, context, NO_PREFERENCE, key, type));
 123.217 +
 123.218 +        return fixes;
 123.219 +    }
 123.220 +
 123.221 +    private void addError(String name, PythonRuleContext context, String message, PythonTree node, List<Hint> result, List<HintFix> fixList) {
 123.222 +        if (name != null && ignoredNames.length() > 0) {
 123.223 +            for (String ignoredName : ignoredNames.split(",")) { // NOI18N
 123.224 +                ignoredName = ignoredName.trim();
 123.225 +                if (name.equals(ignoredName)) {
 123.226 +                    return;
 123.227 +                }
 123.228 +            }
 123.229 +        }
 123.230 +        
 123.231 +        PythonParserResult info = (PythonParserResult)context.parserResult;
 123.232 +        OffsetRange range;
 123.233 +        if (node instanceof Module) {
 123.234 +            range = new OffsetRange(0, 0);
 123.235 +        } else {
 123.236 +            
 123.237 +            range = PythonAstUtils.getNameRange(info, node);
 123.238 +        }
 123.239 +        range = PythonLexerUtils.getLexerOffsets(info, range);
 123.240 +        if (range != OffsetRange.NONE) {
 123.241 +            if (fixList == null) {
 123.242 +                fixList = Collections.emptyList();
 123.243 +            }
 123.244 +            Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 1500);
 123.245 +            result.add(desc);
 123.246 +        }
 123.247 +    }
 123.248 +
 123.249 +    @Override
 123.250 +    public String getId() {
 123.251 +        return "NameRule"; // NOI18N
 123.252 +    }
 123.253 +
 123.254 +    @Override
 123.255 +    public String getDisplayName() {
 123.256 +        return NbBundle.getMessage(NameRule.class, "NameRule");
 123.257 +    }
 123.258 +
 123.259 +    @Override
 123.260 +    public String getDescription() {
 123.261 +        return NbBundle.getMessage(NameRule.class, "NameRuleDesc");
 123.262 +    }
 123.263 +
 123.264 +    @Override
 123.265 +    public boolean getDefaultEnabled() {
 123.266 +        return true;
 123.267 +    }
 123.268 +
 123.269 +    @Override
 123.270 +    public boolean showInTasklist() {
 123.271 +        return true;
 123.272 +    }
 123.273 +
 123.274 +    @Override
 123.275 +    public HintSeverity getDefaultSeverity() {
 123.276 +        return HintSeverity.WARNING;
 123.277 +    }
 123.278 +
 123.279 +    @Override
 123.280 +    public JComponent getCustomizer(Preferences node) {
 123.281 +        moduleStyle = null; // Ensure lazy init after this
 123.282 +        return new NameRulePrefs(this, node);
 123.283 +    }
 123.284 +
 123.285 +    static NameStyle getNameStyle(String key, NameStyle deflt, Preferences pref) {
 123.286 +        String value = pref.get(key, deflt.name());
 123.287 +
 123.288 +        return NameStyle.valueOf(value);
 123.289 +    }
 123.290 +
 123.291 +    static NameStyle getModuleNameStyle(Preferences pref) {
 123.292 +        return getNameStyle(MODULE_STYLE_NAME, NameStyle.NO_PREFERENCE, pref);
 123.293 +    }
 123.294 +
 123.295 +    static NameStyle getClassNameStyle(Preferences pref) {
 123.296 +        return getNameStyle(CLASS_STYLE_NAME, NameStyle.CAPITALIZED_WORDS, pref);
 123.297 +    }
 123.298 +
 123.299 +    static NameStyle getVariableNameStyle(Preferences pref) {
 123.300 +        return getNameStyle(VARIABLE_STYLE_NAME, NameStyle.LOWERCASE_WITH_UNDERSCORES, pref);
 123.301 +    }
 123.302 +
 123.303 +    static NameStyle getFunctionNameStyle(Preferences pref) {
 123.304 +        return getNameStyle(FUNCTION_STYLE_NAME, NameStyle.LOWERCASE_WITH_UNDERSCORES, pref);
 123.305 +    }
 123.306 +
 123.307 +    static boolean isSelfRequired(Preferences pref) {
 123.308 +        return pref.getBoolean(SELF_REQUIRED_NAME, true);
 123.309 +    }
 123.310 +
 123.311 +    static String getIgnoredNames(Preferences pref) {
 123.312 +        return pref.get(IGNORED_NAMES, "");
 123.313 +    }
 123.314 +
 123.315 +    void setModuleNameStyle(Preferences pref, NameStyle style) {
 123.316 +        pref.put(MODULE_STYLE_NAME, style.name());
 123.317 +    }
 123.318 +
 123.319 +    void setClassNameStyle(Preferences pref, NameStyle style) {
 123.320 +        pref.put(CLASS_STYLE_NAME, style.name());
 123.321 +    }
 123.322 +
 123.323 +    void setFunctionNameStyle(Preferences pref, NameStyle style) {
 123.324 +        pref.put(FUNCTION_STYLE_NAME, style.name());
 123.325 +    }
 123.326 +
 123.327 +    void setVariableNameStyle(Preferences pref, NameStyle style) {
 123.328 +        pref.put(VARIABLE_STYLE_NAME, style.name());
 123.329 +    }
 123.330 +
 123.331 +    void setIgnoredNames(Preferences pref, String ignoredNames) {
 123.332 +        pref.put(IGNORED_NAMES, ignoredNames);
 123.333 +    }
 123.334 +
 123.335 +    void setSelfRequired(Preferences pref, boolean requireSelf) {
 123.336 +        pref.putBoolean(SELF_REQUIRED_NAME, requireSelf);
 123.337 +    }
 123.338 +
 123.339 +    private static class IgnoreWordFix implements HintFix {
 123.340 +        private String name;
 123.341 +        private NameRule rule;
 123.342 +        private PythonRuleContext context;
 123.343 +
 123.344 +        public IgnoreWordFix(String name, NameRule rule, PythonRuleContext context) {
 123.345 +            this.name = name;
 123.346 +            this.rule = rule;
 123.347 +            this.context = context;
 123.348 +        }
 123.349 +
 123.350 +        @Override
 123.351 +        public String getDescription() {
 123.352 +            return NbBundle.getMessage(NameRule.class, "IgnoreWord", name);
 123.353 +        }
 123.354 +
 123.355 +        @Override
 123.356 +        public void implement() throws Exception {
 123.357 +            Preferences pref = context.manager.getPreferences(rule);
 123.358 +            String ignored = getIgnoredNames(pref);
 123.359 +            if (ignored.length() > 0) {
 123.360 +                ignored = ignored + "," + name; // NOI18N
 123.361 +            } else {
 123.362 +                ignored = name;
 123.363 +            }
 123.364 +            pref.put(IGNORED_NAMES, ignored);
 123.365 +
 123.366 +            context.manager.refreshHints(context);
 123.367 +        }
 123.368 +
 123.369 +        @Override
 123.370 +        public boolean isSafe() {
 123.371 +            return true;
 123.372 +        }
 123.373 +
 123.374 +        @Override
 123.375 +        public boolean isInteractive() {
 123.376 +            return true;
 123.377 +        }
 123.378 +    }
 123.379 +
 123.380 +    private static class ChangeStyleFix implements HintFix {
 123.381 +        private NameRule rule;
 123.382 +        private PythonRuleContext context;
 123.383 +        private NameStyle style;
 123.384 +        private String key;
 123.385 +        private String typeKey;
 123.386 +
 123.387 +        public ChangeStyleFix(NameRule rule, PythonRuleContext context, NameStyle style, String key, String type) {
 123.388 +            this.rule = rule;
 123.389 +            this.context = context;
 123.390 +            this.style = style;
 123.391 +            this.key = key;
 123.392 +            this.typeKey = type;
 123.393 +        }
 123.394 +
 123.395 +        @Override
 123.396 +        public String getDescription() {
 123.397 +            if (style == NO_PREFERENCE) {
 123.398 +                return NbBundle.getMessage(NameRule.class, "ChangeNoStyle", NbBundle.getMessage(NameRule.class, typeKey));
 123.399 +            } else {
 123.400 +                return NbBundle.getMessage(NameRule.class, "ChangeStyle", NbBundle.getMessage(NameRule.class, typeKey), style.getDisplayName());
 123.401 +            }
 123.402 +        }
 123.403 +
 123.404 +        @Override
 123.405 +        public void implement() throws Exception {
 123.406 +            Preferences pref = context.manager.getPreferences(rule);
 123.407 +            pref.put(key, style.name());
 123.408 +
 123.409 +            context.manager.refreshHints(context);
 123.410 +        }
 123.411 +
 123.412 +        @Override
 123.413 +        public boolean isSafe() {
 123.414 +            return true;
 123.415 +        }
 123.416 +
 123.417 +        @Override
 123.418 +        public boolean isInteractive() {
 123.419 +            return true;
 123.420 +        }
 123.421 +    }
 123.422 +
 123.423 +    /**
 123.424 +     * Fix to insert self argument or rename first argument to self
 123.425 +     */
 123.426 +    private static class SelfParamFix implements PreviewableFix {
 123.427 +        private final PythonRuleContext context;
 123.428 +        private final FunctionDef func;
 123.429 +        private final boolean insert;
 123.430 +        private final String first;
 123.431 +
 123.432 +        private SelfParamFix(PythonRuleContext context, boolean insert, FunctionDef func, String first) {
 123.433 +            this.context = context;
 123.434 +            this.insert = insert;
 123.435 +            this.func = func;
 123.436 +            this.first = first;
 123.437 +
 123.438 +            assert insert || first != null;
 123.439 +        }
 123.440 +
 123.441 +        @Override
 123.442 +        public String getDescription() {
 123.443 +            if (insert) {
 123.444 +                return NbBundle.getMessage(CreateDocString.class, "InsertSelf");
 123.445 +            } else {
 123.446 +                return NbBundle.getMessage(CreateDocString.class, "RenameSelf", first);
 123.447 +            }
 123.448 +        }
 123.449 +
 123.450 +        @Override
 123.451 +        public boolean canPreview() {
 123.452 +            return true;
 123.453 +        }
 123.454 +
 123.455 +        @Override
 123.456 +        public EditList getEditList() throws Exception {
 123.457 +            return getEditList(true);
 123.458 +        }
 123.459 +
 123.460 +        private EditList getEditList(boolean previewOnly) throws Exception {
 123.461 +            BaseDocument doc = context.doc;
 123.462 +            EditList edits = new EditList(doc);
 123.463 +
 123.464 +            OffsetRange astRange = PythonAstUtils.getNameRange((PythonParserResult) context.parserResult, func);
 123.465 +            OffsetRange lexRange = PythonLexerUtils.getLexerOffsets((PythonParserResult) context.parserResult, astRange);
 123.466 +            if (lexRange == OffsetRange.NONE) {
 123.467 +                return edits;
 123.468 +            }
 123.469 +            int paramStart = lexRange.getEnd();
 123.470 +            if (insert) {
 123.471 +                String missing;
 123.472 +                int lineEnd = Utilities.getRowEnd(doc, paramStart);
 123.473 +                int offset = paramStart;
 123.474 +                if (lineEnd > paramStart) {
 123.475 +                    String line = doc.getText(paramStart, lineEnd - paramStart);
 123.476 +                    int paren = line.indexOf('(');
 123.477 +                    int colon = line.indexOf(':');
 123.478 +                    if (paren != -1) {
 123.479 +                        offset = paramStart + paren + 1;
 123.480 +                        missing = "self"; // NOI18N
 123.481 +                        List<String> parameters = PythonAstUtils.getParameters(func);
 123.482 +                        if (parameters.size() > 0) {
 123.483 +                            missing = "self, "; // NOI18N
 123.484 +                        } else {
 123.485 +                            missing = "self"; // NOI18N
 123.486 +                        }
 123.487 +                    } else if (colon != -1) {
 123.488 +                        offset = paramStart + colon;
 123.489 +                        missing = "(self)"; // NOI18N
 123.490 +                    } else {
 123.491 +                        return edits;
 123.492 +                    }
 123.493 +                } else {
 123.494 +                    missing = "(self)"; // NOI18N
 123.495 +                }
 123.496 +                edits.replace(offset, 0, missing, false, 0);
 123.497 +            } else {
 123.498 +                String text = doc.getText(paramStart, doc.getLength() - paramStart);
 123.499 +                int offset = text.indexOf(first);
 123.500 +                if (offset != -1) {
 123.501 +                    offset += paramStart;
 123.502 +                    edits.replace(offset, first.length(), "self", false, 0); // NOI18N
 123.503 +                }
 123.504 +            }
 123.505 +
 123.506 +
 123.507 +            return edits;
 123.508 +        }
 123.509 +
 123.510 +        @Override
 123.511 +        public void implement() throws Exception {
 123.512 +            EditList edits = getEditList(true);
 123.513 +
 123.514 +            edits.apply();
 123.515 +        }
 123.516 +
 123.517 +        @Override
 123.518 +        public boolean isSafe() {
 123.519 +            return true;
 123.520 +        }
 123.521 +
 123.522 +        @Override
 123.523 +        public boolean isInteractive() {
 123.524 +            return false;
 123.525 +        }
 123.526 +    }
 123.527 +}
   124.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   124.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/NameRulePrefs.form	Mon Sep 21 13:01:16 2015 +0200
   124.3 @@ -0,0 +1,182 @@
   124.4 +<?xml version="1.0" encoding="UTF-8" ?>
   124.5 +
   124.6 +<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   124.7 +  <AuxValues>
   124.8 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   124.9 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  124.10 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  124.11 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
  124.12 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  124.13 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
  124.14 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
  124.15 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  124.16 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  124.17 +  </AuxValues>
  124.18 +
  124.19 +  <Layout>
  124.20 +    <DimensionLayout dim="0">
  124.21 +      <Group type="103" groupAlignment="0" attributes="0">
  124.22 +          <Group type="102" attributes="0">
  124.23 +              <Group type="103" groupAlignment="0" attributes="0">
  124.24 +                  <Group type="102" alignment="0" attributes="0">
  124.25 +                      <Group type="103" groupAlignment="0" attributes="0">
  124.26 +                          <Component id="moduleLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  124.27 +                          <Component id="classLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  124.28 +                          <Component id="functionLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  124.29 +                          <Component id="variableLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  124.30 +                      </Group>
  124.31 +                      <EmptySpace max="-2" attributes="0"/>
  124.32 +                      <Group type="103" groupAlignment="1" max="-2" attributes="0">
  124.33 +                          <Component id="variableCombo" alignment="0" max="32767" attributes="1"/>
  124.34 +                          <Component id="classCombo" alignment="0" max="32767" attributes="1"/>
  124.35 +                          <Component id="moduleCombo" alignment="0" pref="234" max="32767" attributes="1"/>
  124.36 +                          <Component id="functionCombo" alignment="1" max="32767" attributes="1"/>
  124.37 +                      </Group>
  124.38 +                  </Group>
  124.39 +                  <Component id="parameterLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  124.40 +                  <Component id="selfCb" alignment="0" min="-2" max="-2" attributes="0"/>
  124.41 +                  <Group type="102" alignment="0" attributes="0">
  124.42 +                      <Component id="ignoreLabel" min="-2" max="-2" attributes="0"/>
  124.43 +                      <EmptySpace max="-2" attributes="0"/>
  124.44 +                      <Component id="ignoredText" max="32767" attributes="0"/>
  124.45 +                  </Group>
  124.46 +              </Group>
  124.47 +              <EmptySpace max="-2" attributes="0"/>
  124.48 +          </Group>
  124.49 +      </Group>
  124.50 +    </DimensionLayout>
  124.51 +    <DimensionLayout dim="1">
  124.52 +      <Group type="103" groupAlignment="0" attributes="0">
  124.53 +          <Group type="102" alignment="0" attributes="0">
  124.54 +              <Group type="103" groupAlignment="3" attributes="0">
  124.55 +                  <Component id="moduleLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  124.56 +                  <Component id="moduleCombo" alignment="3" min="-2" max="-2" attributes="0"/>
  124.57 +              </Group>
  124.58 +              <EmptySpace max="-2" attributes="0"/>
  124.59 +              <Group type="103" groupAlignment="3" attributes="0">
  124.60 +                  <Component id="classLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  124.61 +                  <Component id="classCombo" alignment="3" min="-2" max="-2" attributes="0"/>
  124.62 +              </Group>
  124.63 +              <EmptySpace max="-2" attributes="0"/>
  124.64 +              <Group type="103" groupAlignment="3" attributes="0">
  124.65 +                  <Component id="functionLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  124.66 +                  <Component id="functionCombo" alignment="3" min="-2" max="-2" attributes="0"/>
  124.67 +              </Group>
  124.68 +              <EmptySpace max="-2" attributes="0"/>
  124.69 +              <Group type="103" groupAlignment="3" attributes="0">
  124.70 +                  <Component id="variableLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  124.71 +                  <Component id="variableCombo" alignment="3" min="-2" max="-2" attributes="0"/>
  124.72 +              </Group>
  124.73 +              <EmptySpace type="separate" max="-2" attributes="0"/>
  124.74 +              <Component id="parameterLabel" min="-2" max="-2" attributes="0"/>
  124.75 +              <EmptySpace max="-2" attributes="0"/>
  124.76 +              <Component id="selfCb" min="-2" max="-2" attributes="0"/>
  124.77 +              <EmptySpace type="separate" max="-2" attributes="0"/>
  124.78 +              <Group type="103" groupAlignment="3" attributes="0">
  124.79 +                  <Component id="ignoreLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  124.80 +                  <Component id="ignoredText" alignment="3" min="-2" max="-2" attributes="0"/>
  124.81 +              </Group>
  124.82 +              <EmptySpace max="32767" attributes="0"/>
  124.83 +          </Group>
  124.84 +      </Group>
  124.85 +    </DimensionLayout>
  124.86 +  </Layout>
  124.87 +  <SubComponents>
  124.88 +    <Component class="javax.swing.JLabel" name="classLabel">
  124.89 +      <Properties>
  124.90 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  124.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;)"/>
  124.92 +        </Property>
  124.93 +      </Properties>
  124.94 +    </Component>
  124.95 +    <Component class="javax.swing.JLabel" name="functionLabel">
  124.96 +      <Properties>
  124.97 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  124.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;)"/>
  124.99 +        </Property>
 124.100 +      </Properties>
 124.101 +    </Component>
 124.102 +    <Component class="javax.swing.JLabel" name="moduleLabel">
 124.103 +      <Properties>
 124.104 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 124.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;)"/>
 124.106 +        </Property>
 124.107 +      </Properties>
 124.108 +    </Component>
 124.109 +    <Component class="javax.swing.JLabel" name="parameterLabel">
 124.110 +      <Properties>
 124.111 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 124.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;)"/>
 124.113 +        </Property>
 124.114 +      </Properties>
 124.115 +    </Component>
 124.116 +    <Component class="javax.swing.JCheckBox" name="selfCb">
 124.117 +      <Properties>
 124.118 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 124.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;)"/>
 124.120 +        </Property>
 124.121 +      </Properties>
 124.122 +      <Events>
 124.123 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
 124.124 +      </Events>
 124.125 +    </Component>
 124.126 +    <Component class="javax.swing.JComboBox" name="moduleCombo">
 124.127 +      <Properties>
 124.128 +        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
 124.129 +          <Connection code="getNameStyleModel()" type="code"/>
 124.130 +        </Property>
 124.131 +      </Properties>
 124.132 +      <Events>
 124.133 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
 124.134 +      </Events>
 124.135 +    </Component>
 124.136 +    <Component class="javax.swing.JComboBox" name="classCombo">
 124.137 +      <Properties>
 124.138 +        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
 124.139 +          <Connection code="getNameStyleModel()" type="code"/>
 124.140 +        </Property>
 124.141 +      </Properties>
 124.142 +      <Events>
 124.143 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
 124.144 +      </Events>
 124.145 +    </Component>
 124.146 +    <Component class="javax.swing.JComboBox" name="functionCombo">
 124.147 +      <Properties>
 124.148 +        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
 124.149 +          <Connection code="getNameStyleModel()" type="code"/>
 124.150 +        </Property>
 124.151 +      </Properties>
 124.152 +      <Events>
 124.153 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
 124.154 +      </Events>
 124.155 +    </Component>
 124.156 +    <Component class="javax.swing.JLabel" name="variableLabel">
 124.157 +      <Properties>
 124.158 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 124.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;)"/>
 124.160 +        </Property>
 124.161 +        <Property name="enabled" type="boolean" value="false"/>
 124.162 +      </Properties>
 124.163 +    </Component>
 124.164 +    <Component class="javax.swing.JComboBox" name="variableCombo">
 124.165 +      <Properties>
 124.166 +        <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
 124.167 +          <Connection code="getNameStyleModel()" type="code"/>
 124.168 +        </Property>
 124.169 +        <Property name="enabled" type="boolean" value="false"/>
 124.170 +      </Properties>
 124.171 +      <Events>
 124.172 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
 124.173 +      </Events>
 124.174 +    </Component>
 124.175 +    <Component class="javax.swing.JLabel" name="ignoreLabel">
 124.176 +      <Properties>
 124.177 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 124.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;)"/>
 124.179 +        </Property>
 124.180 +      </Properties>
 124.181 +    </Component>
 124.182 +    <Component class="javax.swing.JTextField" name="ignoredText">
 124.183 +    </Component>
 124.184 +  </SubComponents>
 124.185 +</Form>
   125.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   125.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/NameRulePrefs.java	Mon Sep 21 13:01:16 2015 +0200
   125.3 @@ -0,0 +1,292 @@
   125.4 +/*
   125.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   125.6 + *
   125.7 + * Copyright 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 + * If you wish your version of this file to be governed by only the CDDL
  125.31 + * or only the GPL Version 2, indicate your decision by adding
  125.32 + * "[Contributor] elects to include this software in this distribution
  125.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  125.34 + * single choice of license, a recipient has the option to distribute
  125.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  125.36 + * to extend the choice of license to its licensees as provided above.
  125.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  125.38 + * Version 2 license, then the option applies only if the new code is
  125.39 + * made subject to such option by the copyright holder.
  125.40 + *
  125.41 + * Contributor(s):
  125.42 + *
  125.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  125.44 + */
  125.45 +package org.netbeans.modules.python.hints;
  125.46 +
  125.47 +import org.netbeans.modules.python.source.NameStyle;
  125.48 +import java.awt.Component;
  125.49 +import java.util.prefs.Preferences;
  125.50 +import javax.swing.ComboBoxModel;
  125.51 +import javax.swing.DefaultComboBoxModel;
  125.52 +import javax.swing.JLabel;
  125.53 +import javax.swing.JList;
  125.54 +import javax.swing.ListCellRenderer;
  125.55 +
  125.56 +/**
  125.57 + *
  125.58 + * @author Tor Norbye
  125.59 + */
  125.60 +public class NameRulePrefs extends javax.swing.JPanel {
  125.61 +    private NameRule rule;
  125.62 +    private Preferences prefs;
  125.63 +
  125.64 +    /** Creates new form NameRulePrefs */
  125.65 +    public NameRulePrefs(NameRule rule, Preferences prefs) {
  125.66 +        this.rule = rule;
  125.67 +        this.prefs = prefs;
  125.68 +
  125.69 +        initComponents();
  125.70 +
  125.71 +        ListCellRenderer renderer = new NameStyleRenderer();
  125.72 +        moduleCombo.setRenderer(renderer);
  125.73 +        functionCombo.setRenderer(renderer);
  125.74 +        classCombo.setRenderer(renderer);
  125.75 +        variableCombo.setRenderer(renderer);
  125.76 +
  125.77 +        moduleCombo.setSelectedItem(NameRule.getModuleNameStyle(prefs));
  125.78 +        functionCombo.setSelectedItem(NameRule.getFunctionNameStyle(prefs));
  125.79 +        classCombo.setSelectedItem(NameRule.getClassNameStyle(prefs));
  125.80 +        variableCombo.setSelectedItem(NameRule.getVariableNameStyle(prefs));
  125.81 +
  125.82 +        selfCb.setSelected(NameRule.isSelfRequired(prefs));
  125.83 +        ignoredText.setText(NameRule.getIgnoredNames(prefs));
  125.84 +    }
  125.85 +
  125.86 +    private ComboBoxModel getNameStyleModel() {
  125.87 +        return new DefaultComboBoxModel(NameStyle.values());
  125.88 +    }
  125.89 +
  125.90 +    private static class NameStyleRenderer extends JLabel implements ListCellRenderer/*, UIResource*/ {
  125.91 +        public NameStyleRenderer() {
  125.92 +            setOpaque(true);
  125.93 +        }
  125.94 +
  125.95 +        @Override
  125.96 +        public Component getListCellRendererComponent(JList list, Object value,
  125.97 +                int index, boolean isSelected, boolean cellHasFocus) {
  125.98 +            // #93658: GTK needs name to render cell renderer "natively"
  125.99 +            setName("ComboBox.listRenderer"); // NOI18N
 125.100 +
 125.101 +            if (isSelected) {
 125.102 +                setBackground(list.getSelectionBackground());
 125.103 +                setForeground(list.getSelectionForeground());
 125.104 +            } else {
 125.105 +                setBackground(list.getBackground());
 125.106 +                setForeground(list.getForeground());
 125.107 +            }
 125.108 +
 125.109 +            if (value instanceof NameStyle) {
 125.110 +                setText(((NameStyle)value).getDisplayName());
 125.111 +            }
 125.112 +
 125.113 +            return this;
 125.114 +        }
 125.115 +
 125.116 +        // #93658: GTK needs name to render cell renderer "natively"
 125.117 +        public 
 125.118 +        @Override
 125.119 +        String getName() {
 125.120 +            String name = super.getName();
 125.121 +            return name == null ? "ComboBox.renderer" : name;  // NOI18N
 125.122 +        }
 125.123 +    }
 125.124 +
 125.125 +    /** This method is called from within the constructor to
 125.126 +     * initialize the form.
 125.127 +     * WARNING: Do NOT modify this code. The content of this method is
 125.128 +     * always regenerated by the Form Editor.
 125.129 +     */
 125.130 +    @SuppressWarnings("unchecked")
 125.131 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
 125.132 +    private void initComponents() {
 125.133 +
 125.134 +        classLabel = new javax.swing.JLabel();
 125.135 +        functionLabel = new javax.swing.JLabel();
 125.136 +        moduleLabel = new javax.swing.JLabel();
 125.137 +        parameterLabel = new javax.swing.JLabel();
 125.138 +        selfCb = new javax.swing.JCheckBox();
 125.139 +        moduleCombo = new javax.swing.JComboBox();
 125.140 +        classCombo = new javax.swing.JComboBox();
 125.141 +        functionCombo = new javax.swing.JComboBox();
 125.142 +        variableLabel = new javax.swing.JLabel();
 125.143 +        variableCombo = new javax.swing.JComboBox();
 125.144 +        ignoreLabel = new javax.swing.JLabel();
 125.145 +        ignoredText = new javax.swing.JTextField();
 125.146 +
 125.147 +        classLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.classLabel.text")); // NOI18N
 125.148 +
 125.149 +        functionLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.functionLabel.text")); // NOI18N
 125.150 +
 125.151 +        moduleLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.moduleLabel.text")); // NOI18N
 125.152 +
 125.153 +        parameterLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.parameterLabel.text")); // NOI18N
 125.154 +
 125.155 +        selfCb.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.selfCb.text")); // NOI18N
 125.156 +        selfCb.addActionListener(new java.awt.event.ActionListener() {
 125.157 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
 125.158 +                changed(evt);
 125.159 +            }
 125.160 +        });
 125.161 +
 125.162 +        moduleCombo.setModel(getNameStyleModel());
 125.163 +        moduleCombo.addActionListener(new java.awt.event.ActionListener() {
 125.164 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
 125.165 +                changed(evt);
 125.166 +            }
 125.167 +        });
 125.168 +
 125.169 +        classCombo.setModel(getNameStyleModel());
 125.170 +        classCombo.addActionListener(new java.awt.event.ActionListener() {
 125.171 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
 125.172 +                changed(evt);
 125.173 +            }
 125.174 +        });
 125.175 +
 125.176 +        functionCombo.setModel(getNameStyleModel());
 125.177 +        functionCombo.addActionListener(new java.awt.event.ActionListener() {
 125.178 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
 125.179 +                changed(evt);
 125.180 +            }
 125.181 +        });
 125.182 +
 125.183 +        variableLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.variableLabel.text")); // NOI18N
 125.184 +        variableLabel.setEnabled(false);
 125.185 +
 125.186 +        variableCombo.setModel(getNameStyleModel());
 125.187 +        variableCombo.setEnabled(false);
 125.188 +        variableCombo.addActionListener(new java.awt.event.ActionListener() {
 125.189 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
 125.190 +                changed(evt);
 125.191 +            }
 125.192 +        });
 125.193 +
 125.194 +        ignoreLabel.setText(org.openide.util.NbBundle.getMessage(NameRulePrefs.class, "NameRulePrefs.ignoreLabel.text")); // NOI18N
 125.195 +
 125.196 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
 125.197 +        this.setLayout(layout);
 125.198 +        layout.setHorizontalGroup(
 125.199 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 125.200 +            .addGroup(layout.createSequentialGroup()
 125.201 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 125.202 +                    .addGroup(layout.createSequentialGroup()
 125.203 +                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 125.204 +                            .addComponent(moduleLabel)
 125.205 +                            .addComponent(classLabel)
 125.206 +                            .addComponent(functionLabel)
 125.207 +                            .addComponent(variableLabel))
 125.208 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 125.209 +                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
 125.210 +                            .addComponent(variableCombo, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 125.211 +                            .addComponent(classCombo, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 125.212 +                            .addComponent(moduleCombo, javax.swing.GroupLayout.Alignment.LEADING, 0, 234, Short.MAX_VALUE)
 125.213 +                            .addComponent(functionCombo, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
 125.214 +                    .addComponent(parameterLabel)
 125.215 +                    .addComponent(selfCb)
 125.216 +                    .addGroup(layout.createSequentialGroup()
 125.217 +                        .addComponent(ignoreLabel)
 125.218 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 125.219 +                        .addComponent(ignoredText)))
 125.220 +                .addContainerGap())
 125.221 +        );
 125.222 +        layout.setVerticalGroup(
 125.223 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 125.224 +            .addGroup(layout.createSequentialGroup()
 125.225 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 125.226 +                    .addComponent(moduleLabel)
 125.227 +                    .addComponent(moduleCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 125.228 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 125.229 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 125.230 +                    .addComponent(classLabel)
 125.231 +                    .addComponent(classCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 125.232 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 125.233 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 125.234 +                    .addComponent(functionLabel)
 125.235 +                    .addComponent(functionCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 125.236 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 125.237 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 125.238 +                    .addComponent(variableLabel)
 125.239 +                    .addComponent(variableCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 125.240 +                .addGap(18, 18, 18)
 125.241 +                .addComponent(parameterLabel)
 125.242 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 125.243 +                .addComponent(selfCb)
 125.244 +                .addGap(18, 18, 18)
 125.245 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 125.246 +                    .addComponent(ignoreLabel)
 125.247 +                    .addComponent(ignoredText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 125.248 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 125.249 +        );
 125.250 +    }// </editor-fold>//GEN-END:initComponents
 125.251 +
 125.252 +    private void changed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_changed
 125.253 +        Object source = evt.getSource();
 125.254 +
 125.255 +        if (source == moduleCombo) {
 125.256 +            NameStyle style = (NameStyle)moduleCombo.getSelectedItem();
 125.257 +            if (style != null) {
 125.258 +                rule.setModuleNameStyle(prefs, style);
 125.259 +            }
 125.260 +        } else if (source == functionCombo) {
 125.261 +            NameStyle style = (NameStyle)functionCombo.getSelectedItem();
 125.262 +            if (style != null) {
 125.263 +                rule.setFunctionNameStyle(prefs, style);
 125.264 +            }
 125.265 +        } else if (source == classCombo) {
 125.266 +            NameStyle style = (NameStyle)classCombo.getSelectedItem();
 125.267 +            if (style != null) {
 125.268 +                rule.setClassNameStyle(prefs, style);
 125.269 +            }
 125.270 +        } else if (source == variableCombo) {
 125.271 +            NameStyle style = (NameStyle)variableCombo.getSelectedItem();
 125.272 +            if (style != null) {
 125.273 +                rule.setVariableNameStyle(prefs, style);
 125.274 +            }
 125.275 +        } else if (source == ignoredText) {
 125.276 +            rule.setIgnoredNames(prefs, ignoredText.getText().trim());
 125.277 +        } else if (source == selfCb) {
 125.278 +            rule.setSelfRequired(prefs, selfCb.isSelected());
 125.279 +        }
 125.280 +    }//GEN-LAST:event_changed
 125.281 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 125.282 +    private javax.swing.JComboBox classCombo;
 125.283 +    private javax.swing.JLabel classLabel;
 125.284 +    private javax.swing.JComboBox functionCombo;
 125.285 +    private javax.swing.JLabel functionLabel;
 125.286 +    private javax.swing.JLabel ignoreLabel;
 125.287 +    private javax.swing.JTextField ignoredText;
 125.288 +    private javax.swing.JComboBox moduleCombo;
 125.289 +    private javax.swing.JLabel moduleLabel;
 125.290 +    private javax.swing.JLabel parameterLabel;
 125.291 +    private javax.swing.JCheckBox selfCb;
 125.292 +    private javax.swing.JComboBox variableCombo;
 125.293 +    private javax.swing.JLabel variableLabel;
 125.294 +    // End of variables declaration//GEN-END:variables
 125.295 +}
   126.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   126.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/PythonAstRule.java	Mon Sep 21 13:01:16 2015 +0200
   126.3 @@ -0,0 +1,51 @@
   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 java.util.List;
  126.37 +import java.util.Set;
  126.38 +import org.netbeans.modules.csl.api.Hint;
  126.39 +import org.netbeans.modules.csl.api.Rule.AstRule;
  126.40 +
  126.41 +public abstract class PythonAstRule implements AstRule {
  126.42 +    /** 
  126.43 +     * Get the ElementKinds this rule should run on.
  126.44 +     * The integers should correspond to values in {@link org.mozilla.javascript.Token}
  126.45 +     */
  126.46 +    @Override
  126.47 +    public abstract Set<Class> getKinds();
  126.48 +
  126.49 +    /**
  126.50 +     * Run the test on given CompilationUnit and return list of Errors or
  126.51 +     * warrnings to be shown in the editor.
  126.52 +     */
  126.53 +    public abstract void run(PythonRuleContext context, List<Hint> result);
  126.54 +}
   127.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   127.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/PythonHintOptions.java	Mon Sep 21 13:01:16 2015 +0200
   127.3 @@ -0,0 +1,71 @@
   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 org.netbeans.modules.csl.api.HintsProvider;
  127.37 +import org.netbeans.modules.csl.api.HintsProvider.HintsManager;
  127.38 +import org.netbeans.modules.python.api.PythonMIMEResolver;
  127.39 +import org.netbeans.spi.options.AdvancedOption;
  127.40 +import org.netbeans.spi.options.OptionsPanelController;
  127.41 +import org.openide.util.NbBundle;
  127.42 +
  127.43 +/**
  127.44 + * Hint settings for Python
  127.45 + */
  127.46 +public class PythonHintOptions extends AdvancedOption {
  127.47 +    OptionsPanelController panelController;
  127.48 +
  127.49 +    @Override
  127.50 +    public String getDisplayName() {
  127.51 +        return NbBundle.getMessage(PythonHintOptions.class, "CTL_Hints_DisplayName"); // NOI18N
  127.52 +    }
  127.53 +
  127.54 +    @Override
  127.55 +    public String getTooltip() {
  127.56 +        return NbBundle.getMessage(PythonHintOptions.class, "CTL_Hints_ToolTip"); // NOI18N
  127.57 +    }
  127.58 +
  127.59 +    @Override
  127.60 +    public synchronized OptionsPanelController create() {
  127.61 +        if (panelController == null) {
  127.62 +            HintsManager manager = HintsProvider.HintsManager.getManagerForMimeType(PythonMIMEResolver.PYTHON_MIME_TYPE);
  127.63 +            assert manager != null;
  127.64 +            panelController = manager.getOptionsController();
  127.65 +        }
  127.66 +
  127.67 +        return panelController;
  127.68 +    }
  127.69 +
  127.70 +    //TODO: temporary solution, this should be solved on GSF level
  127.71 +    public static OptionsPanelController createStatic() {
  127.72 +        return new PythonHintOptions().create();
  127.73 +    }
  127.74 +}
   128.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   128.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/PythonHintsProvider.java	Mon Sep 21 13:01:16 2015 +0200
   128.3 @@ -0,0 +1,433 @@
   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 java.util.Collections;
  128.37 +import java.util.HashMap;
  128.38 +import java.util.Iterator;
  128.39 +import java.util.LinkedList;
  128.40 +import java.util.List;
  128.41 +import java.util.Map;
  128.42 +import java.util.Map.Entry;
  128.43 +import java.util.Set;
  128.44 +import org.netbeans.modules.csl.api.Error;
  128.45 +import org.netbeans.modules.csl.api.Hint;
  128.46 +import org.netbeans.modules.csl.api.HintFix;
  128.47 +import org.netbeans.modules.csl.api.HintSeverity;
  128.48 +import org.netbeans.modules.csl.api.HintsProvider;
  128.49 +import org.netbeans.modules.csl.api.HintsProvider.HintsManager;
  128.50 +import org.netbeans.modules.csl.api.OffsetRange;
  128.51 +import org.netbeans.modules.csl.api.Rule;
  128.52 +import org.netbeans.modules.csl.api.RuleContext;
  128.53 +import org.netbeans.modules.csl.spi.GsfUtilities;
  128.54 +import org.netbeans.modules.csl.spi.ParserResult;
  128.55 +import org.netbeans.modules.python.source.AstPath;
  128.56 +import org.netbeans.modules.python.source.PythonAstUtils;
  128.57 +import org.netbeans.modules.python.source.PythonParserResult;
  128.58 +import org.openide.util.Exceptions;
  128.59 +import org.python.antlr.PythonTree;
  128.60 +import org.python.antlr.Visitor;
  128.61 +
  128.62 +/**
  128.63 + *
  128.64 + * @todo Write rules based on the PythonChecker ideas:
  128.65 + *   http://pychecker.sourceforge.net/
  128.66 + * @todo Write rules based on the PyLint ideas:
  128.67 + *   http://www.logilab.org/projects/pylint
  128.68 + *   http://www.logilab.org/card/pylintfeatures
  128.69 + *
  128.70 + * @author Tor Norbye
  128.71 + */
  128.72 +public class PythonHintsProvider implements HintsProvider {
  128.73 +    private boolean cancelled;
  128.74 +
  128.75 +    public PythonHintsProvider() {
  128.76 +    }
  128.77 +
  128.78 +    private static class ScopeRule implements Rule {
  128.79 +        @Override
  128.80 +        public boolean appliesTo(RuleContext context) {
  128.81 +            return true;
  128.82 +        }
  128.83 +
  128.84 +        @Override
  128.85 +        public String getDisplayName() {
  128.86 +            return "";
  128.87 +        }
  128.88 +
  128.89 +        @Override
  128.90 +        public boolean showInTasklist() {
  128.91 +            return true;
  128.92 +        }
  128.93 +
  128.94 +        @Override
  128.95 +        public HintSeverity getDefaultSeverity() {
  128.96 +            return HintSeverity.ERROR;
  128.97 +        }
  128.98 +    }
  128.99 +    
 128.100 +    @Override
 128.101 +    public void computeErrors(HintsManager manager, RuleContext context, List<Hint> result, List<Error> unhandled) {
 128.102 +        ParserResult parserResult = context.parserResult;
 128.103 +        if (parserResult == null) {
 128.104 +            return;
 128.105 +        }
 128.106 +
 128.107 +        PythonParserResult pr = (PythonParserResult)parserResult;
 128.108 +        List<Error> scopeErrors = pr.getSymbolTable().getErrors();
 128.109 +        if (scopeErrors.size() > 0) {
 128.110 +            List<HintFix> fixList = Collections.emptyList();
 128.111 +            Rule rule = new ScopeRule(); // HACK! Just need a rule that will return a severity!
 128.112 +            for (Error error : scopeErrors) {
 128.113 +                Hint desc = new Hint(rule, error.getDisplayName(), error.getFile(),
 128.114 +                        new OffsetRange(error.getStartPosition(), error.getEndPosition()), fixList, 10);
 128.115 +                result.add(desc);
 128.116 +            }
 128.117 +        }
 128.118 +
 128.119 +        List<? extends Error> errors = parserResult.getDiagnostics();
 128.120 +        if (errors == null || errors.size() == 0) {
 128.121 +            return;
 128.122 +        }
 128.123 +//
 128.124 +//        cancelled = false;
 128.125 +//
 128.126 +//        @SuppressWarnings("unchecked")
 128.127 +//        Map<String,List<JsErrorRule>> hints = (Map)manager.getErrors();
 128.128 +//
 128.129 +//        if (hints.isEmpty() || isCancelled()) {
 128.130 +        unhandled.addAll(errors);
 128.131 +//            return;
 128.132 +//        }
 128.133 +//
 128.134 +//        for (Error error : errors) {
 128.135 +//            if (!applyErrorRules(manager, context, error, hints, result)) {
 128.136 +//                unhandled.add(error);
 128.137 +//            }
 128.138 +//        }
 128.139 +    }
 128.140 +
 128.141 +    @Override
 128.142 +    public void computeSelectionHints(HintsManager manager, RuleContext context, List<Hint> result, int start, int end) {
 128.143 +        cancelled = false;
 128.144 +
 128.145 +        if (GsfUtilities.isCodeTemplateEditing(context.doc)) {
 128.146 +            return;
 128.147 +        }
 128.148 +
 128.149 +        ParserResult parserResult = context.parserResult;
 128.150 +        if (parserResult == null) {
 128.151 +            return;
 128.152 +        }
 128.153 +        PythonTree root = PythonAstUtils.getRoot(context.parserResult);
 128.154 +
 128.155 +        if (root == null) {
 128.156 +            return;
 128.157 +        }
 128.158 +        @SuppressWarnings("unchecked")
 128.159 +        List<? extends Rule.SelectionRule> hints = manager.getSelectionHints();
 128.160 +
 128.161 +        if (hints.isEmpty()) {
 128.162 +            return;
 128.163 +        }
 128.164 +
 128.165 +        if (isCancelled()) {
 128.166 +            return;
 128.167 +        }
 128.168 +
 128.169 +        try {
 128.170 +            context.doc.readLock();
 128.171 +            applySelectionRules(manager, context, hints, result);
 128.172 +        } finally {
 128.173 +            context.doc.readUnlock();
 128.174 +        }
 128.175 +}
 128.176 +
 128.177 +    private void applySelectionRules(HintsManager manager, RuleContext context, List<? extends Rule.SelectionRule> rules, List<Hint> result) {
 128.178 +
 128.179 +        PythonRuleContext pythonContext = (PythonRuleContext)context;
 128.180 +
 128.181 +        for (Rule.SelectionRule rule : rules) {
 128.182 +            if (!rule.appliesTo(context)) {
 128.183 +                continue;
 128.184 +            }
 128.185 +            
 128.186 +            if(!(rule instanceof PythonSelectionRule)) {
 128.187 +                continue;
 128.188 +            }
 128.189 +
 128.190 +            if (!manager.isEnabled((PythonSelectionRule)rule)) {
 128.191 +                continue;
 128.192 +            }
 128.193 +
 128.194 +            try {
 128.195 +                context.doc.readLock();
 128.196 +                ((PythonSelectionRule)rule).run(pythonContext, result);
 128.197 +            } finally {
 128.198 +                context.doc.readUnlock();
 128.199 +            }
 128.200 +        }
 128.201 +    }
 128.202 +
 128.203 +    @Override
 128.204 +    public void computeHints(HintsManager manager, RuleContext context, List<Hint> result) {
 128.205 +        cancelled = false;
 128.206 +
 128.207 +        if (context.parserResult == null) {
 128.208 +            return;
 128.209 +        }
 128.210 +        PythonTree root = PythonAstUtils.getRoot(context.parserResult);
 128.211 +
 128.212 +        if (root == null) {
 128.213 +            return;
 128.214 +        }
 128.215 +        @SuppressWarnings("unchecked")
 128.216 +        Map<Class, List<PythonAstRule>> hints = (Map)manager.getHints(false, context);
 128.217 +
 128.218 +        if (hints.isEmpty()) {
 128.219 +            return;
 128.220 +        }
 128.221 +
 128.222 +        if (isCancelled()) {
 128.223 +            return;
 128.224 +        }
 128.225 +
 128.226 +//        AstPath path = new AstPath();
 128.227 +//        path.descend(root);
 128.228 +//
 128.229 +//        //applyRules(manager, NodeTypes.ROOTNODE, root, path, info, hints, descriptions);
 128.230 +//        applyHints(manager, context, -1, root, path, hints, result);
 128.231 +//
 128.232 +//        scan(manager, context, root, path, hints, result);
 128.233 +//        path.ascend();
 128.234 +
 128.235 +
 128.236 +        RuleApplicator finder = new RuleApplicator(manager, context, hints, result);
 128.237 +        try {
 128.238 +            context.doc.readLock();
 128.239 +            finder.visit(root);
 128.240 +        } catch (Exception ex) {
 128.241 +            Exceptions.printStackTrace(ex);
 128.242 +        } finally {
 128.243 +            context.doc.readUnlock();
 128.244 +        }
 128.245 +    }
 128.246 +
 128.247 +    @SuppressWarnings("unchecked")
 128.248 +    @Override
 128.249 +    public void computeSuggestions(HintsManager manager, RuleContext context, List<Hint> result, int caretOffset) {
 128.250 +        cancelled = false;
 128.251 +        if (context.parserResult == null) {
 128.252 +            return;
 128.253 +        }
 128.254 +
 128.255 +        PythonTree root = PythonAstUtils.getRoot(context.parserResult);
 128.256 +
 128.257 +        if (root == null) {
 128.258 +            return;
 128.259 +        }
 128.260 +
 128.261 +        Map<Class, List<PythonAstRule>> suggestions = new HashMap<>();
 128.262 +        suggestions.putAll((Map)manager.getHints(true, context));
 128.263 +
 128.264 +        Set<Entry<Class, List<PythonAstRule>>> entrySet = (Set)manager.getSuggestions().entrySet();
 128.265 +        for (Entry<Class, List<PythonAstRule>> e : entrySet) {
 128.266 +            List<PythonAstRule> rules = suggestions.get(e.getKey());
 128.267 +
 128.268 +            if (rules != null) {
 128.269 +                List<PythonAstRule> res = new LinkedList<>();
 128.270 +
 128.271 +                res.addAll(rules);
 128.272 +                res.addAll(e.getValue());
 128.273 +
 128.274 +                suggestions.put(e.getKey(), res);
 128.275 +            } else {
 128.276 +                suggestions.put(e.getKey(), e.getValue());
 128.277 +            }
 128.278 +        }
 128.279 +
 128.280 +        if (suggestions.isEmpty()) {
 128.281 +            return;
 128.282 +        }
 128.283 +
 128.284 +
 128.285 +        if (isCancelled()) {
 128.286 +            return;
 128.287 +        }
 128.288 +
 128.289 +        try {
 128.290 +            context.doc.readLock();
 128.291 +
 128.292 +            PythonParserResult info = (PythonParserResult)context.parserResult;
 128.293 +            int astOffset = PythonAstUtils.getAstOffset(info, caretOffset);
 128.294 +            AstPath path = AstPath.get(root, astOffset);
 128.295 +            Iterator<PythonTree> it = path.leafToRoot();
 128.296 +            while (it.hasNext()) {
 128.297 +                if (isCancelled()) {
 128.298 +                    return;
 128.299 +                }
 128.300 +
 128.301 +                PythonTree node = it.next();
 128.302 +
 128.303 +                applySuggestions(manager, context, node.getClass(), node, path, suggestions, result);
 128.304 +            }
 128.305 +        } finally {
 128.306 +            context.doc.readUnlock();
 128.307 +        }
 128.308 +
 128.309 +    //applyRules(NodeTypes.ROOTNODE, path, info, suggestions, caretOffset, result);
 128.310 +    }
 128.311 +
 128.312 +    private void applySuggestions(HintsManager manager, RuleContext context, Class nodeType, PythonTree node, AstPath path, Map<Class, List<PythonAstRule>> hints,
 128.313 +            List<Hint> result) {
 128.314 +        List<PythonAstRule> rules = hints.get(nodeType);
 128.315 +
 128.316 +        if (rules != null) {
 128.317 +            PythonRuleContext pyCtx = (PythonRuleContext)context;
 128.318 +            pyCtx.node = node;
 128.319 +            pyCtx.path = path;
 128.320 +
 128.321 +            try {
 128.322 +                context.doc.readLock();
 128.323 +                for (PythonAstRule rule : rules) {
 128.324 +                    if (manager.isEnabled(rule)) {
 128.325 +                        rule.run(pyCtx, result);
 128.326 +                    }
 128.327 +                }
 128.328 +            } finally {
 128.329 +                context.doc.readUnlock();
 128.330 +            }
 128.331 +        }
 128.332 +    }
 128.333 +
 128.334 +//    /** Apply error rules and return true iff somebody added an error description for it */
 128.335 +//    private boolean applyErrorRules(HintsManager manager, RuleContext context, Error error, Map<String,List<JsErrorRule>> hints,
 128.336 +//            List<Hint> result) {
 128.337 +//        String code = error.getKey();
 128.338 +//        if (code != null) {
 128.339 +//            List<JsErrorRule> rules = hints.get(code);
 128.340 +//
 128.341 +//            if (rules != null) {
 128.342 +//                int countBefore = result.size();
 128.343 +//                PythonRuleContext jsContext = (PythonRuleContext)context;
 128.344 +//
 128.345 +//                boolean disabled = false;
 128.346 +//                for (JsErrorRule rule : rules) {
 128.347 +//                    if (!manager.isEnabled(rule)) {
 128.348 +//                        disabled = true;
 128.349 +//                    } else if (rule.appliesTo(context)) {
 128.350 +//                        rule.run(jsContext, error, result);
 128.351 +//                    }
 128.352 +//                }
 128.353 +//
 128.354 +//                return disabled || countBefore < result.size() || jsContext.remove;
 128.355 +//            }
 128.356 +//        }
 128.357 +//
 128.358 +//        return false;
 128.359 +//    }
 128.360 +//
 128.361 +//    private void applySelectionRules(HintsManager manager, RuleContext context, List<JsSelectionRule> rules,
 128.362 +//            List<Hint> result) {
 128.363 +//
 128.364 +//        for (JsSelectionRule rule : rules) {
 128.365 +//            if (!rule.appliesTo(context)) {
 128.366 +//                continue;
 128.367 +//            }
 128.368 +//
 128.369 +//            //if (!manager.isEnabled(rule)) {
 128.370 +//            //    continue;
 128.371 +//            //}
 128.372 +//
 128.373 +//            rule.run(context, result);
 128.374 +//        }
 128.375 +//    }
 128.376 +//
 128.377 +    @Override
 128.378 +    public void cancel() {
 128.379 +        cancelled = true;
 128.380 +    }
 128.381 +
 128.382 +    private boolean isCancelled() {
 128.383 +        return cancelled;
 128.384 +    }
 128.385 +
 128.386 +    @Override
 128.387 +    public RuleContext createRuleContext() {
 128.388 +        return new PythonRuleContext();
 128.389 +    }
 128.390 +
 128.391 +    @Override
 128.392 +    public List<Rule> getBuiltinRules() {
 128.393 +        return Collections.emptyList();
 128.394 +    }
 128.395 +
 128.396 +    private static class RuleApplicator extends Visitor {
 128.397 +        private HintsManager manager;
 128.398 +        private RuleContext context;
 128.399 +        private AstPath path;
 128.400 +        private Map<Class, List<PythonAstRule>> hints;
 128.401 +        private List<Hint> result;
 128.402 +
 128.403 +        public RuleApplicator(HintsManager manager, RuleContext context, Map<Class, List<PythonAstRule>> hints, List<Hint> result) {
 128.404 +            this.manager = manager;
 128.405 +            this.context = context;
 128.406 +            this.hints = hints;
 128.407 +            this.result = result;
 128.408 +
 128.409 +            path = new AstPath();
 128.410 +        }
 128.411 +
 128.412 +        @Override
 128.413 +        public void traverse(PythonTree node) throws Exception {
 128.414 +            path.descend(node);
 128.415 +            applyHints(node);
 128.416 +            super.traverse(node);
 128.417 +            path.ascend();
 128.418 +        }
 128.419 +
 128.420 +        private void applyHints(PythonTree node) {
 128.421 +            List<PythonAstRule> rules = hints.get(node.getClass());
 128.422 +
 128.423 +            if (rules != null) {
 128.424 +                PythonRuleContext jsContext = (PythonRuleContext)context;
 128.425 +                jsContext.node = node;
 128.426 +                jsContext.path = path;
 128.427 +
 128.428 +                for (PythonAstRule rule : rules) {
 128.429 +                    if (manager.isEnabled(rule)) {
 128.430 +                        rule.run(jsContext, result);
 128.431 +                    }
 128.432 +                }
 128.433 +            }
 128.434 +        }
 128.435 +    }
 128.436 +}
   129.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/PythonRuleContext.java	Mon Sep 21 13:01:16 2015 +0200
   129.3 @@ -0,0 +1,45 @@
   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 org.netbeans.modules.python.source.AstPath;
  129.37 +import org.python.antlr.PythonTree;
  129.38 +
  129.39 +/**
  129.40 + * Information about the current context a rule is being asked to evaluate.
  129.41 + * 
  129.42 + * @author Tor Norbye
  129.43 + */
  129.44 +public class PythonRuleContext extends org.netbeans.modules.csl.api.RuleContext {
  129.45 +    public AstPath path;
  129.46 +    public PythonTree node;
  129.47 +    public boolean remove;
  129.48 +}
   130.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/PythonSelectionRule.java	Mon Sep 21 13:01:16 2015 +0200
   130.3 @@ -0,0 +1,128 @@
   130.4 +/*
   130.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   130.6 + *
   130.7 + * Copyright 1997-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 + * Contributor(s):
  130.31 + *
  130.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  130.33 + */
  130.34 +package org.netbeans.modules.python.hints;
  130.35 +
  130.36 +import javax.swing.text.BadLocationException;
  130.37 +import java.util.List;
  130.38 +import org.netbeans.modules.python.source.PythonAstUtils;
  130.39 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  130.40 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
  130.41 +import org.netbeans.api.lexer.Token;
  130.42 +import org.netbeans.api.lexer.TokenId;
  130.43 +import org.netbeans.editor.BaseDocument;
  130.44 +import org.netbeans.editor.Utilities;
  130.45 +import org.netbeans.modules.csl.api.Hint;
  130.46 +import org.netbeans.modules.csl.api.OffsetRange;
  130.47 +import org.netbeans.modules.csl.api.Rule.SelectionRule;
  130.48 +import org.netbeans.modules.csl.api.Rule.UserConfigurableRule;
  130.49 +import org.openide.util.Exceptions;
  130.50 +import org.python.antlr.PythonTree;
  130.51 +
  130.52 +/**
  130.53 + * Represents a rule to be run on text selection
  130.54 + *
  130.55 + * @author Tor Norbye
  130.56 + */
  130.57 +public abstract class PythonSelectionRule implements SelectionRule, UserConfigurableRule {
  130.58 +    protected abstract int getApplicability(PythonRuleContext context, PythonTree root, OffsetRange astRange);
  130.59 +
  130.60 +    //public abstract void run(PythonRuleContext context, List<Hint> result);
  130.61 +    public void run(PythonRuleContext context, List<Hint> result) {
  130.62 +        // TODO - decide if this code represents a complete statement...
  130.63 +        // For now - that's true iff there's no code to the left on the
  130.64 +        // start line and code to the right on the end line
  130.65 +        BaseDocument doc = context.doc;
  130.66 +        int originalStart = context.selectionStart;
  130.67 +        int originalEnd = context.selectionEnd;
  130.68 +        int docLength = doc.getLength();
  130.69 +
  130.70 +        if (originalEnd > docLength) {
  130.71 +            return;
  130.72 +        }
  130.73 +        OffsetRange narrowed = PythonLexerUtils.narrow(doc, new OffsetRange(originalStart, originalEnd), false);
  130.74 +        if (narrowed == OffsetRange.NONE) {
  130.75 +            return;
  130.76 +        }
  130.77 +
  130.78 +        int start = narrowed.getStart();
  130.79 +        int end = narrowed.getEnd();
  130.80 +        try {
  130.81 +            if (start > Utilities.getRowFirstNonWhite(doc, Math.min(docLength, start))) {
  130.82 +                return;
  130.83 +            }
  130.84 +            if (end < Utilities.getRowLastNonWhite(doc, Math.min(docLength, end)) + 1) {
  130.85 +                return;
  130.86 +            }
  130.87 +        } catch (BadLocationException ex) {
  130.88 +            Exceptions.printStackTrace(ex);
  130.89 +        }
  130.90 +
  130.91 +        PythonTree root = PythonAstUtils.getRoot(context.parserResult);
  130.92 +        if (root == null) {
  130.93 +            return;
  130.94 +        }
  130.95 +
  130.96 +        OffsetRange astRange = PythonAstUtils.getAstOffsets(context.parserResult, new OffsetRange(start, end));
  130.97 +        if (astRange == OffsetRange.NONE) {
  130.98 +            return;
  130.99 +        }
 130.100 +
 130.101 +        int applicability = getApplicability(context, root, astRange);
 130.102 +        if (applicability == 0) {
 130.103 +            return;
 130.104 +        }
 130.105 +        // Don't allow extract with if you're inside strings or comments
 130.106 +        Token<? extends PythonTokenId> startToken = PythonLexerUtils.getToken(doc, start);
 130.107 +        Token<? extends PythonTokenId> endToken = PythonLexerUtils.getToken(doc, end);
 130.108 +        if (startToken == null || endToken == null) {
 130.109 +            return;
 130.110 +        }
 130.111 +        TokenId startId = startToken.id();
 130.112 +        if (startId == PythonTokenId.STRING_LITERAL ||
 130.113 +                (startId == PythonTokenId.COMMENT && start > 0 && startToken == PythonLexerUtils.getToken(doc, start - 1))) {
 130.114 +            return;
 130.115 +        }
 130.116 +        TokenId endId = endToken.id();
 130.117 +        if (endId == PythonTokenId.STRING_LITERAL) {
 130.118 +            return;
 130.119 +        }
 130.120 +
 130.121 +        // TODO - don't enable inside comments or strings!!
 130.122 +        // TODO - if you are including functions or classes it should probably
 130.123 +        // be disabled!
 130.124 +
 130.125 +        OffsetRange range = new OffsetRange(originalStart, originalEnd);
 130.126 +
 130.127 +        run(context, result, range, applicability);
 130.128 +    }
 130.129 +
 130.130 +    public abstract void run(PythonRuleContext context, List<Hint> result, OffsetRange range, int applicability);
 130.131 +}
   131.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   131.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/RelativeImports.java	Mon Sep 21 13:01:16 2015 +0200
   131.3 @@ -0,0 +1,246 @@
   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.ParserResult;
  131.66 +import org.netbeans.modules.python.source.PythonParserResult;
  131.67 +import org.openide.filesystems.FileObject;
  131.68 +import org.openide.util.Exceptions;
  131.69 +import org.openide.util.NbBundle;
  131.70 +import org.python.antlr.PythonTree;
  131.71 +import org.python.antlr.ast.ImportFrom;
  131.72 +
  131.73 +/**
  131.74 + * Import statements should be one per line. This quickfix
  131.75 + * offers to make it so.
  131.76 + *
  131.77 + * @todo Ensure that
  131.78 + *  {@code from __future__ import absolute_import}
  131.79 + *   is present, at least until Python 2.7
  131.80 + *
  131.81 + * @author Tor Norbye
  131.82 + */
  131.83 +public class RelativeImports extends PythonAstRule {
  131.84 +    @Override
  131.85 +    public Set<Class> getKinds() {
  131.86 +        return Collections.singleton((Class)ImportFrom.class);
  131.87 +    }
  131.88 +
  131.89 +    @Override
  131.90 +    public void run(PythonRuleContext context, List<Hint> result) {
  131.91 +        ImportFrom imp = (ImportFrom)context.node;
  131.92 +        if (imp.getInternalModule() != null && imp.getInternalModule().startsWith(".")) {
  131.93 +            PythonTree node = context.node;
  131.94 +            PythonParserResult info = (PythonParserResult) context.parserResult;
  131.95 +            OffsetRange astOffsets = PythonAstUtils.getNameRange(info, node);
  131.96 +            OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
  131.97 +            BaseDocument doc = context.doc;
  131.98 +            try {
  131.99 +                if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
 131.100 +                        (context.caretOffset == -1 ||
 131.101 +                        Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
 131.102 +                    List<HintFix> fixList = new ArrayList<>();
 131.103 +                    fixList.add(new RelativeImportsFix(context, imp));
 131.104 +                    String displayName = getDisplayName();
 131.105 +                    Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
 131.106 +                    result.add(desc);
 131.107 +                }
 131.108 +            } catch (BadLocationException ex) {
 131.109 +                Exceptions.printStackTrace(ex);
 131.110 +            }
 131.111 +        }
 131.112 +    }
 131.113 +
 131.114 +    @Override
 131.115 +    public String getId() {
 131.116 +        return "RelativeImports"; // NOI18N
 131.117 +    }
 131.118 +
 131.119 +    @Override
 131.120 +    public String getDisplayName() {
 131.121 +        return NbBundle.getMessage(RelativeImports.class, "RelativeImports");
 131.122 +    }
 131.123 +
 131.124 +    @Override
 131.125 +    public String getDescription() {
 131.126 +        return NbBundle.getMessage(RelativeImports.class, "RelativeImportsDesc");
 131.127 +    }
 131.128 +
 131.129 +    @Override
 131.130 +    public boolean getDefaultEnabled() {
 131.131 +        return true;
 131.132 +    }
 131.133 +
 131.134 +    @Override
 131.135 +    public JComponent getCustomizer(Preferences node) {
 131.136 +        return null;
 131.137 +    }
 131.138 +
 131.139 +    @Override
 131.140 +    public boolean appliesTo(RuleContext context) {
 131.141 +        return true;
 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 RelativeImportsFix implements PreviewableFix {
 131.155 +        private final PythonRuleContext context;
 131.156 +        private final ImportFrom imp;
 131.157 +
 131.158 +        private RelativeImportsFix(PythonRuleContext context, ImportFrom 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(RelativeImports.class, "RelativeImportsFix");
 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 +            // Algorithm:
 131.179 +            //  (1) Figure out which package we are in
 131.180 +            //  (2) Subtrack package elements per dot
 131.181 +            //  (3) Replace relative reference
 131.182 +
 131.183 +            OffsetRange astRange = PythonAstUtils.getRange(imp);
 131.184 +            if (astRange != OffsetRange.NONE) {
 131.185 +                PythonParserResult info = (PythonParserResult)context.parserResult;
 131.186 +                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 131.187 +                if (lexRange != OffsetRange.NONE) {
 131.188 +                    FileObject fo = info.getSnapshot().getSource().getFileObject();
 131.189 +                    if (fo != null) {
 131.190 +                        String path = imp.getInternalModule();
 131.191 +                        int i = 0;
 131.192 +                        for (; i < path.length(); i++) {
 131.193 +                            if (path.charAt(i) != '.') {
 131.194 +                                break;
 131.195 +                            }
 131.196 +                        }
 131.197 +                        int levels = i;
 131.198 +                        path = path.substring(levels);
 131.199 +
 131.200 +                        for (int j = 0; j < levels; j++) {
 131.201 +                            if (fo != null) {
 131.202 +                                fo = fo.getParent();
 131.203 +                            }
 131.204 +                        }
 131.205 +
 131.206 +                        // Finally, find out the absolute path we are in
 131.207 +                        // Hopefully, I will have access to the python load path
 131.208 +                        // here. But in the mean time, I can just see which 
 131.209 +                        // packages I am in...
 131.210 +                        while (fo != null) {
 131.211 +                            if (fo.getFileObject("__init__.py") != null) { // NOI18N
 131.212 +                                // Yep, we're still in a package
 131.213 +                                if (path.length() > 0) {
 131.214 +                                    path = fo.getName() + "." + path; // NOI18N
 131.215 +                                } else {
 131.216 +                                    path = fo.getName();
 131.217 +                                }
 131.218 +                            }
 131.219 +                            fo = fo.getParent();
 131.220 +                        }
 131.221 +                        String text = doc.getText(lexRange.getStart(), lexRange.getLength());
 131.222 +                        int relativePos = text.indexOf(imp.getInternalModule());
 131.223 +                        if (relativePos != -1) {
 131.224 +                            edits.replace(lexRange.getStart() + relativePos, imp.getInternalModule().length(), path, false, 0);
 131.225 +                        }
 131.226 +                    }
 131.227 +                }
 131.228 +            }
 131.229 +
 131.230 +            return edits;
 131.231 +        }
 131.232 +
 131.233 +        @Override
 131.234 +        public void implement() throws Exception {
 131.235 +            EditList edits = getEditList();
 131.236 +            edits.apply();
 131.237 +        }
 131.238 +
 131.239 +        @Override
 131.240 +        public boolean isSafe() {
 131.241 +            return true;
 131.242 +        }
 131.243 +
 131.244 +        @Override
 131.245 +        public boolean isInteractive() {
 131.246 +            return false;
 131.247 +        }
 131.248 +    }
 131.249 +}
   132.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   132.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/SplitImports.java	Mon Sep 21 13:01:16 2015 +0200
   132.3 @@ -0,0 +1,222 @@
   132.4 +/*
   132.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   132.6 + *
   132.7 + * Copyright 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 + * If you wish your version of this file to be governed by only the CDDL
  132.31 + * or only the GPL Version 2, indicate your decision by adding
  132.32 + * "[Contributor] elects to include this software in this distribution
  132.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  132.34 + * single choice of license, a recipient has the option to distribute
  132.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  132.36 + * to extend the choice of license to its licensees as provided above.
  132.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  132.38 + * Version 2 license, then the option applies only if the new code is
  132.39 + * made subject to such option by the copyright holder.
  132.40 + *
  132.41 + * Contributor(s):
  132.42 + *
  132.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  132.44 + */
  132.45 +package org.netbeans.modules.python.hints;
  132.46 +
  132.47 +import java.util.ArrayList;
  132.48 +import java.util.Collections;
  132.49 +import java.util.List;
  132.50 +import java.util.Set;
  132.51 +import java.util.prefs.Preferences;
  132.52 +import javax.swing.JComponent;
  132.53 +import javax.swing.text.BadLocationException;
  132.54 +import org.netbeans.modules.python.source.PythonAstUtils;
  132.55 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  132.56 +import org.netbeans.editor.BaseDocument;
  132.57 +import org.netbeans.editor.Utilities;
  132.58 +import org.netbeans.modules.csl.api.EditList;
  132.59 +import org.netbeans.modules.csl.api.Hint;
  132.60 +import org.netbeans.modules.csl.api.HintFix;
  132.61 +import org.netbeans.modules.csl.api.HintSeverity;
  132.62 +import org.netbeans.modules.csl.api.OffsetRange;
  132.63 +import org.netbeans.modules.csl.api.PreviewableFix;
  132.64 +import org.netbeans.modules.csl.api.RuleContext;
  132.65 +import org.netbeans.modules.csl.spi.GsfUtilities;
  132.66 +import org.netbeans.modules.editor.indent.api.IndentUtils;
  132.67 +import org.netbeans.modules.python.source.PythonParserResult;
  132.68 +import org.netbeans.modules.python.source.CodeStyle;
  132.69 +import org.openide.util.Exceptions;
  132.70 +import org.openide.util.NbBundle;
  132.71 +import org.python.antlr.PythonTree;
  132.72 +import org.python.antlr.ast.Import;
  132.73 +import org.python.antlr.ast.alias;
  132.74 +
  132.75 +/**
  132.76 + * Import statements should be one per line. This quickfix
  132.77 + * offers to make it so.
  132.78 + *
  132.79 + * @author Tor Norbye
  132.80 + */
  132.81 +public class SplitImports extends PythonAstRule {
  132.82 +    @Override
  132.83 +    public Set<Class> getKinds() {
  132.84 +        return Collections.singleton((Class)Import.class);
  132.85 +    }
  132.86 +
  132.87 +    @Override
  132.88 +    public void run(PythonRuleContext context, List<Hint> result) {
  132.89 +        Import imp = (Import)context.node;
  132.90 +        List<alias> names = imp.getInternalNames();
  132.91 +        if (names != null && names.size() > 1) {
  132.92 +            PythonTree node = context.node;
  132.93 +            PythonParserResult info = (PythonParserResult)context.parserResult;
  132.94 +            OffsetRange astOffsets = PythonAstUtils.getNameRange(info, node);
  132.95 +            OffsetRange lexOffsets = PythonLexerUtils.getLexerOffsets(info, astOffsets);
  132.96 +            BaseDocument doc = context.doc;
  132.97 +            try {
  132.98 +                if (lexOffsets != OffsetRange.NONE && lexOffsets.getStart() < doc.getLength() &&
  132.99 +                        (context.caretOffset == -1 ||
 132.100 +                        Utilities.getRowStart(doc, context.caretOffset) == Utilities.getRowStart(doc, lexOffsets.getStart()))) {
 132.101 +                    List<HintFix> fixList = new ArrayList<>();
 132.102 +                    fixList.add(new SplitImportsFix(context, imp));
 132.103 +                    String displayName = getDisplayName();
 132.104 +                    Hint desc = new Hint(this, displayName, info.getSnapshot().getSource().getFileObject(), lexOffsets, fixList, 1500);
 132.105 +                    result.add(desc);
 132.106 +                }
 132.107 +            } catch (BadLocationException ex) {
 132.108 +                Exceptions.printStackTrace(ex);
 132.109 +            }
 132.110 +        }
 132.111 +    }
 132.112 +
 132.113 +    @Override
 132.114 +    public String getId() {
 132.115 +        return "SplitImports"; // NOI18N
 132.116 +    }
 132.117 +
 132.118 +    @Override
 132.119 +    public String getDisplayName() {
 132.120 +        return NbBundle.getMessage(SplitImports.class, "SplitImports");
 132.121 +    }
 132.122 +
 132.123 +    @Override
 132.124 +    public String getDescription() {
 132.125 +        return NbBundle.getMessage(SplitImports.class, "SplitImportsDesc");
 132.126 +    }
 132.127 +
 132.128 +    @Override
 132.129 +    public boolean getDefaultEnabled() {
 132.130 +        return true;
 132.131 +    }
 132.132 +
 132.133 +    @Override
 132.134 +    public JComponent getCustomizer(Preferences node) {
 132.135 +        return null;
 132.136 +    }
 132.137 +
 132.138 +    @Override
 132.139 +    public boolean appliesTo(RuleContext context) {
 132.140 +        CodeStyle codeStyle = CodeStyle.getDefault(context.doc);
 132.141 +        return codeStyle == null || codeStyle.oneImportPerLine();
 132.142 +    }
 132.143 +
 132.144 +    @Override
 132.145 +    public boolean showInTasklist() {
 132.146 +        return true;
 132.147 +    }
 132.148 +
 132.149 +    @Override
 132.150 +    public HintSeverity getDefaultSeverity() {
 132.151 +        return HintSeverity.WARNING;
 132.152 +    }
 132.153 +
 132.154 +    private static class SplitImportsFix implements PreviewableFix {
 132.155 +        private final PythonRuleContext context;
 132.156 +        private final Import imp;
 132.157 +
 132.158 +        private SplitImportsFix(PythonRuleContext context, Import imp) {
 132.159 +            this.context = context;
 132.160 +            this.imp = imp;
 132.161 +        }
 132.162 +
 132.163 +        @Override
 132.164 +        public String getDescription() {
 132.165 +            return NbBundle.getMessage(SplitImports.class, "SplitImportsFix");
 132.166 +        }
 132.167 +
 132.168 +        @Override
 132.169 +        public boolean canPreview() {
 132.170 +            return true;
 132.171 +        }
 132.172 +
 132.173 +        @Override
 132.174 +        public EditList getEditList() throws Exception {
 132.175 +            BaseDocument doc = context.doc;
 132.176 +            EditList edits = new EditList(doc);
 132.177 +
 132.178 +            OffsetRange astRange = PythonAstUtils.getRange(imp);
 132.179 +            if (astRange != OffsetRange.NONE) {
 132.180 +                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets((PythonParserResult) context.parserResult, astRange);
 132.181 +                if (lexRange != OffsetRange.NONE) {
 132.182 +                    int indent = GsfUtilities.getLineIndent(doc, lexRange.getStart());
 132.183 +                    StringBuilder sb = new StringBuilder();
 132.184 +                    List<alias> names = imp.getInternalNames();
 132.185 +                    if (names != null) {
 132.186 +                        for (alias at : names) {
 132.187 +                            if (indent > 0 && sb.length() > 0) {
 132.188 +                                sb.append(IndentUtils.createIndentString(doc, indent));
 132.189 +                            }
 132.190 +                            sb.append("import "); // NOI18N
 132.191 +                            sb.append(at.getInternalName());
 132.192 +                            if (at.getInternalAsname() != null && at.getInternalAsname().length() > 0) {
 132.193 +                                sb.append(" as "); // NOI18N
 132.194 +                                sb.append(at.getInternalAsname());
 132.195 +                            }
 132.196 +                            sb.append("\n");
 132.197 +                        }
 132.198 +                    }
 132.199 +                    // Remove the final newline since Import doesn't include it
 132.200 +                    sb.setLength(sb.length() - 1);
 132.201 +
 132.202 +                    edits.replace(lexRange.getStart(), lexRange.getLength(), sb.toString(), false, 0);
 132.203 +                }
 132.204 +            }
 132.205 +
 132.206 +            return edits;
 132.207 +        }
 132.208 +
 132.209 +        @Override
 132.210 +        public void implement() throws Exception {
 132.211 +            EditList edits = getEditList();
 132.212 +            edits.apply();
 132.213 +        }
 132.214 +
 132.215 +        @Override
 132.216 +        public boolean isSafe() {
 132.217 +            return true;
 132.218 +        }
 132.219 +
 132.220 +        @Override
 132.221 +        public boolean isInteractive() {
 132.222 +            return false;
 132.223 +        }
 132.224 +    }
 132.225 +}
   133.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   133.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/SurroundWith.java	Mon Sep 21 13:01:16 2015 +0200
   133.3 @@ -0,0 +1,377 @@
   133.4 +/*
   133.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   133.6 + *
   133.7 + * Copyright 1997-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 + * Contributor(s):
  133.31 + *
  133.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  133.33 + */
  133.34 +package org.netbeans.modules.python.hints;
  133.35 +
  133.36 +import java.util.ArrayList;
  133.37 +import java.util.List;
  133.38 +import java.util.prefs.Preferences;
  133.39 +import javax.swing.JComponent;
  133.40 +import javax.swing.text.JTextComponent;
  133.41 +import javax.swing.text.Position;
  133.42 +import org.netbeans.editor.BaseDocument;
  133.43 +import org.netbeans.editor.Utilities;
  133.44 +import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager;
  133.45 +import org.netbeans.modules.csl.api.EditList;
  133.46 +import org.netbeans.modules.csl.api.Hint;
  133.47 +import org.netbeans.modules.csl.api.HintFix;
  133.48 +import org.netbeans.modules.csl.api.HintSeverity;
  133.49 +import org.netbeans.modules.csl.api.OffsetRange;
  133.50 +import org.netbeans.modules.csl.api.PreviewableFix;
  133.51 +import org.netbeans.modules.csl.api.RuleContext;
  133.52 +import org.netbeans.modules.csl.spi.GsfUtilities;
  133.53 +import org.netbeans.modules.editor.indent.api.IndentUtils;
  133.54 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  133.55 +import org.openide.util.Exceptions;
  133.56 +import org.openide.util.NbBundle;
  133.57 +import org.python.antlr.PythonTree;
  133.58 +import org.python.antlr.Visitor;
  133.59 +import org.python.antlr.ast.ClassDef;
  133.60 +import org.python.antlr.ast.FunctionDef;
  133.61 +import org.python.antlr.ast.Import;
  133.62 +import org.python.antlr.ast.ImportFrom;
  133.63 +
  133.64 +/**
  133.65 + * Offer to surround code with for example try/except/finally
  133.66 + *
  133.67 + * @author Tor Norbye
  133.68 + */
  133.69 +public class SurroundWith extends PythonSelectionRule {
  133.70 +    @Override
  133.71 +    protected int getApplicability(PythonRuleContext context, PythonTree root, OffsetRange astRange) {
  133.72 +        if (!ApplicabilityVisitor.applies(root, astRange)) {
  133.73 +            return 0;
  133.74 +        }
  133.75 +
  133.76 +        return 1;
  133.77 +    }
  133.78 +
  133.79 +    @Override
  133.80 +    public void run(PythonRuleContext context, List<Hint> result, OffsetRange range, int applicability) {
  133.81 +        int start = range.getStart();
  133.82 +        int end = range.getEnd();
  133.83 +
  133.84 +        // Adjust the fix range to be right around the dot so that the light bulb ends up
  133.85 +        // on the same line as the caret and alt-enter works
  133.86 +        JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
  133.87 +        if (target != null) {
  133.88 +            int dot = target.getCaret().getDot();
  133.89 +            range = new OffsetRange(dot, dot);
  133.90 +        }
  133.91 +
  133.92 +        List<HintFix> fixList = new ArrayList<>(3);
  133.93 +        fixList.add(new SurroundWithFix(context, start, end, false, true));
  133.94 +        fixList.add(new SurroundWithFix(context, start, end, true, true));
  133.95 +        fixList.add(new SurroundWithFix(context, start, end, true, false));
  133.96 +        String displayName = getDisplayName();
  133.97 +        Hint desc = new Hint(this, displayName, context.parserResult.getSnapshot().getSource().getFileObject(),
  133.98 +                range, fixList, 1500);
  133.99 +        result.add(desc);
 133.100 +    }
 133.101 +
 133.102 +    @Override
 133.103 +    public boolean appliesTo(RuleContext context) {
 133.104 +        return true;
 133.105 +    }
 133.106 +
 133.107 +    @Override
 133.108 +    public String getDisplayName() {
 133.109 +        return NbBundle.getMessage(SurroundWith.class, "SurroundWith");
 133.110 +    }
 133.111 +
 133.112 +    @Override
 133.113 +    public boolean showInTasklist() {
 133.114 +        return false;
 133.115 +    }
 133.116 +
 133.117 +    @Override
 133.118 +    public HintSeverity getDefaultSeverity() {
 133.119 +        return HintSeverity.CURRENT_LINE_WARNING;
 133.120 +    }
 133.121 +
 133.122 +    @Override
 133.123 +    public String getId() {
 133.124 +        return "SurroundWith"; // NOI18N
 133.125 +    }
 133.126 +
 133.127 +    @Override
 133.128 +    public String getDescription() {
 133.129 +        return "";
 133.130 +    }
 133.131 +
 133.132 +    @Override
 133.133 +    public boolean getDefaultEnabled() {
 133.134 +        return true;
 133.135 +    }
 133.136 +
 133.137 +    @Override
 133.138 +    public JComponent getCustomizer(Preferences node) {
 133.139 +        return null;
 133.140 +    }
 133.141 +
 133.142 +    private static class SurroundWithFix implements PreviewableFix {
 133.143 +        private final PythonRuleContext context;
 133.144 +        private final boolean includeFinally;
 133.145 +        private final boolean includeExcept;
 133.146 +        private Position startPos;
 133.147 +        private Position endPos;
 133.148 +        private Position codeTemplatePos;
 133.149 +        private String codeTemplateText;
 133.150 +        private final int start;
 133.151 +        private final int end;
 133.152 +
 133.153 +        private SurroundWithFix(PythonRuleContext context,
 133.154 +                int start, int end,
 133.155 +                boolean includeFinally, boolean includeExcept) {
 133.156 +            assert includeExcept || includeFinally;
 133.157 +
 133.158 +            this.context = context;
 133.159 +
 133.160 +            OffsetRange range = PythonLexerUtils.narrow(context.doc, new OffsetRange(start, end), false);
 133.161 +            this.start = range.getStart();
 133.162 +            this.end = range.getEnd();
 133.163 +            this.includeFinally = includeFinally;
 133.164 +            this.includeExcept = includeExcept;
 133.165 +        }
 133.166 +
 133.167 +        @Override
 133.168 +        public String getDescription() {
 133.169 +            if (includeExcept && includeFinally) {
 133.170 +                return NbBundle.getMessage(CreateDocString.class, "SurroundWithTEF");
 133.171 +            } else if (includeExcept) {
 133.172 +                return NbBundle.getMessage(CreateDocString.class, "SurroundWithTE");
 133.173 +            } else {
 133.174 +                assert includeFinally;
 133.175 +                return NbBundle.getMessage(CreateDocString.class, "SurroundWithTF");
 133.176 +            }
 133.177 +        }
 133.178 +
 133.179 +        @Override
 133.180 +        public boolean canPreview() {
 133.181 +            return true;
 133.182 +        }
 133.183 +
 133.184 +        @Override
 133.185 +        public EditList getEditList() throws Exception {
 133.186 +            return getEditList(true);
 133.187 +        }
 133.188 +
 133.189 +        private EditList getEditList(boolean previewOnly) throws Exception {
 133.190 +            BaseDocument doc = context.doc;
 133.191 +            EditList edits = new EditList(doc);
 133.192 +
 133.193 +            int indentSize = IndentUtils.indentLevelSize(doc);
 133.194 +            String oneIndent = IndentUtils.createIndentString(doc, indentSize);
 133.195 +            //int initialIndent = GsfUtilities.getLineIndent(doc, start);
 133.196 +            int lineStart = Utilities.getRowStart(doc, start);
 133.197 +            String initialIndentStr = IndentUtils.createIndentString(doc, IndentUtils.lineIndent(doc, lineStart));
 133.198 +            int nextLine = Utilities.getRowEnd(doc, end) + 1;
 133.199 +            if (nextLine > doc.getLength()) {
 133.200 +                nextLine = doc.getLength();
 133.201 +                edits.replace(nextLine, 0, "\n", false, 1);
 133.202 +            }
 133.203 +
 133.204 +            // Indent the selected lines
 133.205 +            edits.replace(lineStart, 0, initialIndentStr + "try:\n", false, 1);
 133.206 +            for (int offset = start; offset < end; offset = Utilities.getRowEnd(doc, offset) + 1) {
 133.207 +                edits.replace(offset, 0, oneIndent, false, 1);
 133.208 +            }
 133.209 +
 133.210 +            StringBuilder sb = new StringBuilder();
 133.211 +            if (includeExcept) {
 133.212 +                sb.append(initialIndentStr);
 133.213 +                sb.append("except ");
 133.214 +                if (!previewOnly) {
 133.215 +                    sb.append("${except default=\"");
 133.216 +                }
 133.217 +                sb.append("Exception, e");
 133.218 +                if (!previewOnly) {
 133.219 +                    sb.append("\"}");
 133.220 +                }
 133.221 +                sb.append(":\n");
 133.222 +                sb.append(initialIndentStr);
 133.223 +                sb.append(oneIndent);
 133.224 +                int caretDelta = sb.length();
 133.225 +                startPos = edits.createPosition(nextLine + caretDelta);
 133.226 +                if (!previewOnly) {
 133.227 +                    sb.append("${action default=\"");
 133.228 +                }
 133.229 +                sb.append("print \"Exception: \", e");
 133.230 +                if (!previewOnly) {
 133.231 +                    sb.append("\"}");
 133.232 +                }
 133.233 +                caretDelta = sb.length();
 133.234 +                endPos = edits.createPosition(nextLine + caretDelta);
 133.235 +                sb.append("\n");
 133.236 +                if (!previewOnly && !includeExcept) {
 133.237 +                    sb.append("${cursor}");
 133.238 +                }
 133.239 +            }
 133.240 +            if (includeFinally) {
 133.241 +                sb.append(initialIndentStr);
 133.242 +                sb.append("finally:\n");
 133.243 +                sb.append(initialIndentStr);
 133.244 +                sb.append(oneIndent);
 133.245 +                if (!previewOnly) {
 133.246 +                    sb.append("${finally default=\"\"}\n${cursor}");
 133.247 +                }
 133.248 +                int caretDelta = sb.length();
 133.249 +                if (!includeExcept) {
 133.250 +                    endPos = startPos = edits.createPosition(nextLine + caretDelta);
 133.251 +                }
 133.252 +                sb.append("\n");
 133.253 +            }
 133.254 +            if (previewOnly) {
 133.255 +                edits.replace(nextLine, 0, sb.toString(), false, 1);
 133.256 +            } else {
 133.257 +                codeTemplatePos = edits.createPosition(nextLine, Position.Bias.Backward);
 133.258 +                codeTemplateText = sb.toString();
 133.259 +            }
 133.260 +
 133.261 +            return edits;
 133.262 +        }
 133.263 +
 133.264 +        @Override
 133.265 +        public void implement() throws Exception {
 133.266 +            EditList edits = getEditList(true);
 133.267 +
 133.268 +            JTextComponent target = GsfUtilities.getPaneFor(context.parserResult.getSnapshot().getSource().getFileObject());
 133.269 +            edits.apply();
 133.270 +            if (target != null) {
 133.271 +                if (codeTemplateText != null && codeTemplatePos != null) {
 133.272 +                    final CodeTemplateManager ctm = CodeTemplateManager.get(context.doc);
 133.273 +                    if (ctm != null) {
 133.274 +                        target.getCaret().setDot(codeTemplatePos.getOffset());
 133.275 +                        ctm.createTemporary(codeTemplateText).insert(target);
 133.276 +                    }
 133.277 +                } else if (startPos != null && endPos != null) {
 133.278 +                    target.setSelectionStart(startPos.getOffset());
 133.279 +                    target.setSelectionEnd(endPos.getOffset());
 133.280 +                }
 133.281 +            }
 133.282 +        }
 133.283 +
 133.284 +        @Override
 133.285 +        public boolean isSafe() {
 133.286 +            return true;
 133.287 +        }
 133.288 +
 133.289 +        @Override
 133.290 +        public boolean isInteractive() {
 133.291 +            return false;
 133.292 +        }
 133.293 +    }
 133.294 +
 133.295 +    /** @todo Prune search in traverse, ala AstPath.
 133.296 +     *  @todo Build up start and end AstPaths.
 133.297 +     */
 133.298 +    private static class ApplicabilityVisitor extends Visitor {
 133.299 +        private boolean applies = true;
 133.300 +        private final int start;
 133.301 +        private final int end;
 133.302 +
 133.303 +        static boolean applies(PythonTree root, OffsetRange astRange) {
 133.304 +            ApplicabilityVisitor visitor = new ApplicabilityVisitor(astRange);
 133.305 +            try {
 133.306 +                visitor.visit(root);
 133.307 +            } catch (Exception ex) {
 133.308 +                Exceptions.printStackTrace(ex);
 133.309 +                return false;
 133.310 +            }
 133.311 +            return visitor.isApplicable();
 133.312 +        }
 133.313 +
 133.314 +        ApplicabilityVisitor(OffsetRange astRange) {
 133.315 +            this.start = astRange.getStart();
 133.316 +            this.end = astRange.getEnd();
 133.317 +        }
 133.318 +
 133.319 +        public boolean isApplicable() {
 133.320 +            return applies;
 133.321 +        }
 133.322 +
 133.323 +        private void maybeBail(PythonTree node) {
 133.324 +            int nodeStart = node.getCharStartIndex();
 133.325 +            int nodeEnd = node.getCharStopIndex();
 133.326 +            if (nodeStart >= start && nodeStart < end) {
 133.327 +                applies = false;
 133.328 +            }
 133.329 +            if (nodeEnd > start && nodeEnd < end) {
 133.330 +                applies = false;
 133.331 +            }
 133.332 +        }
 133.333 +
 133.334 +        @Override
 133.335 +        public void traverse(PythonTree node) throws Exception {
 133.336 +            if (!applies) {
 133.337 +                return;
 133.338 +            }
 133.339 +
 133.340 +            int nodeStart = node.getCharStartIndex();
 133.341 +            int nodeStop = node.getCharStopIndex();
 133.342 +            //if (!(nodeStop < start || nodeStart > end)) {
 133.343 +            if (nodeStop >= start && nodeStart <= end) {
 133.344 +                super.traverse(node);
 133.345 +            }
 133.346 +        }
 133.347 +
 133.348 +        @Override
 133.349 +        public Object visitClassDef(ClassDef node) throws Exception {
 133.350 +            maybeBail(node);
 133.351 +            return super.visitClassDef(node);
 133.352 +        }
 133.353 +
 133.354 +        @Override
 133.355 +        public Object visitFunctionDef(FunctionDef node) throws Exception {
 133.356 +            maybeBail(node);
 133.357 +            return super.visitFunctionDef(node);
 133.358 +        }
 133.359 +
 133.360 +        @Override
 133.361 +        public Object visitImport(Import node) throws Exception {
 133.362 +            maybeBail(node);
 133.363 +            return super.visitImport(node);
 133.364 +        }
 133.365 +
 133.366 +        @Override
 133.367 +        public Object visitImportFrom(ImportFrom node) throws Exception {
 133.368 +            maybeBail(node);
 133.369 +            return super.visitImportFrom(node);
 133.370 +        }
 133.371 +
 133.372 +        // Module is okay - you get this when you select all text in a simple "script" file
 133.373 +        // with only statements
 133.374 +        //@Override
 133.375 +        //public Object visitModule(Module node) throws Exception {
 133.376 +        //    maybeBail(node);
 133.377 +        //    return super.visitModule(node);
 133.378 +        //}
 133.379 +    }
 133.380 +}
   134.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   134.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/UnresolvedClassComponents.java	Mon Sep 21 13:01:16 2015 +0200
   134.3 @@ -0,0 +1,207 @@
   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.Collections;
  134.48 +import java.util.List;
  134.49 +import java.util.Set;
  134.50 +import java.util.prefs.Preferences;
  134.51 +import javax.swing.JComponent;
  134.52 +import org.netbeans.modules.csl.api.Hint;
  134.53 +import org.netbeans.modules.csl.api.HintFix;
  134.54 +import org.netbeans.modules.csl.api.HintSeverity;
  134.55 +import org.netbeans.modules.csl.api.OffsetRange;
  134.56 +import org.netbeans.modules.csl.api.RuleContext;
  134.57 +import org.netbeans.modules.python.source.PythonAstUtils;
  134.58 +import org.netbeans.modules.python.source.PythonParserResult;
  134.59 +import org.netbeans.modules.python.source.ImportManager;
  134.60 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  134.61 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  134.62 +import org.openide.util.NbBundle;
  134.63 +import org.python.antlr.PythonTree;
  134.64 +import org.python.antlr.ast.Module;
  134.65 +
  134.66 +/**
  134.67 + * Detect Unresolved class attributes
  134.68 + *
  134.69 + * @author Jean-Yves Mengant
  134.70 + */
  134.71 +public class UnresolvedClassComponents extends PythonAstRule {
  134.72 +
  134.73 +    private final static String CLASS_UNRESOLVED_ATTRIBUTES = "UnresolvedAttributes";
  134.74 +    private final static String CLASS_UNRESOLVED_INHERITANCE_VAR = "UnresolvedInheritanceVariable";
  134.75 +    private final static String CLASS_UNRESOLVED_ATTRIBUTES_VAR = "UnresolvedAttributesVariable";
  134.76 +    private final static String CLASS_UNRESOLVED_ATTRIBUTES_DESC = "UnresolvedAttributesDesc";
  134.77 +
  134.78 +
  134.79 +
  134.80 +    public UnresolvedClassComponents() {
  134.81 +    }
  134.82 +
  134.83 +    @Override
  134.84 +    public boolean appliesTo(RuleContext context) {
  134.85 +        return true;
  134.86 +    }
  134.87 +
  134.88 +    @Override
  134.89 +    public Set<Class> getKinds() {
  134.90 +        return Collections.<Class>singleton(Module.class);
  134.91 +    }
  134.92 +
  134.93 +    private void populateMessages( PythonParserResult info, List<PythonTree> unresolved , List<Hint> result ,boolean isClass ) {
  134.94 +        if (unresolved.size() > 0) {
  134.95 +
  134.96 +            for (PythonTree node : unresolved) {
  134.97 +                // Compute suggestions
  134.98 +                String name = PythonAstUtils.getName(node);
  134.99 +                if (name == null) {
 134.100 +                    name = "";
 134.101 +                }
 134.102 +                List<HintFix> fixList = Collections.emptyList();
 134.103 +                String message ;
 134.104 +                if ( isClass)
 134.105 +                  message = NbBundle.getMessage(NameRule.class, CLASS_UNRESOLVED_INHERITANCE_VAR, name);
 134.106 +                else
 134.107 +                  message = NbBundle.getMessage(NameRule.class, CLASS_UNRESOLVED_ATTRIBUTES_VAR, name);
 134.108 +                OffsetRange range = PythonAstUtils.getRange( node);
 134.109 +                range = PythonLexerUtils.getLexerOffsets(info, range);
 134.110 +                if (range != OffsetRange.NONE) {
 134.111 +                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
 134.112 +                    result.add(desc);
 134.113 +                }
 134.114 +            }
 134.115 +        }
 134.116 +    }
 134.117 +
 134.118 +
 134.119 +    @Override
 134.120 +    public void run(PythonRuleContext context, List<Hint> result) {
 134.121 +        PythonParserResult info = (PythonParserResult) context.parserResult;
 134.122 +        SymbolTable symbolTable = info.getSymbolTable();
 134.123 +
 134.124 +        List<PythonTree> unresolvedAttributes = symbolTable.getUnresolvedAttributes(info);
 134.125 +        populateMessages(info,unresolvedAttributes,result,false) ;
 134.126 +        List<PythonTree> unresolvedParents = symbolTable.getUnresolvedParents(info);
 134.127 +        populateMessages(info,unresolvedParents,result,true) ;
 134.128 +    }
 134.129 +
 134.130 +    @Override
 134.131 +    public String getId() {
 134.132 +        return CLASS_UNRESOLVED_ATTRIBUTES; // NOI18N
 134.133 +    }
 134.134 +
 134.135 +    @Override
 134.136 +    public String getDisplayName() {
 134.137 +        return NbBundle.getMessage(NameRule.class, CLASS_UNRESOLVED_ATTRIBUTES);
 134.138 +    }
 134.139 +
 134.140 +    @Override
 134.141 +    public String getDescription() {
 134.142 +        return NbBundle.getMessage(NameRule.class, CLASS_UNRESOLVED_ATTRIBUTES_DESC);
 134.143 +    }
 134.144 +
 134.145 +    @Override
 134.146 +    public boolean getDefaultEnabled() {
 134.147 +        return false;
 134.148 +    }
 134.149 +
 134.150 +    @Override
 134.151 +    public boolean showInTasklist() {
 134.152 +        return true;
 134.153 +    }
 134.154 +
 134.155 +    @Override
 134.156 +    public HintSeverity getDefaultSeverity() {
 134.157 +        return HintSeverity.ERROR;
 134.158 +    }
 134.159 +
 134.160 +    @Override
 134.161 +    public JComponent getCustomizer(Preferences node) {
 134.162 +        return null;
 134.163 +    }
 134.164 +
 134.165 +    private static class ImportFix implements HintFix {
 134.166 +        private final PythonRuleContext context;
 134.167 +        private final PythonTree node;
 134.168 +        private final String module;
 134.169 +
 134.170 +        private ImportFix(PythonRuleContext context, PythonTree node, String module) {
 134.171 +            this.context = context;
 134.172 +            this.node = node;
 134.173 +            this.module = module;
 134.174 +        }
 134.175 +
 134.176 +        @Override
 134.177 +        public String getDescription() {
 134.178 +            return NbBundle.getMessage(CreateDocString.class, "FixImport", module);
 134.179 +        }
 134.180 +
 134.181 +        @Override
 134.182 +        public void implement() throws Exception {
 134.183 +            String mod = this.module;
 134.184 +            String symbol = null;
 134.185 +            int colon = mod.indexOf(':');
 134.186 +            if (colon != -1) {
 134.187 +                int end = mod.indexOf('(', colon + 1);
 134.188 +                if (end == -1) {
 134.189 +                    end = mod.indexOf(';', colon + 1);
 134.190 +                    if (end == -1) {
 134.191 +                        end = mod.length();
 134.192 +                    }
 134.193 +                }
 134.194 +                symbol = mod.substring(colon + 1, end).trim();
 134.195 +                mod = mod.substring(0, colon).trim();
 134.196 +            }
 134.197 +            new ImportManager((PythonParserResult) context.parserResult).ensureImported(mod, symbol, false, false, true);
 134.198 +        }
 134.199 +
 134.200 +        @Override
 134.201 +        public boolean isSafe() {
 134.202 +            return true;
 134.203 +        }
 134.204 +
 134.205 +        @Override
 134.206 +        public boolean isInteractive() {
 134.207 +            return false;
 134.208 +        }
 134.209 +    }
 134.210 +}
   135.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   135.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/UnresolvedDetector.java	Mon Sep 21 13:01:16 2015 +0200
   135.3 @@ -0,0 +1,232 @@
   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.List;
  135.50 +import java.util.Set;
  135.51 +import java.util.prefs.Preferences;
  135.52 +import javax.swing.JComponent;
  135.53 +import org.netbeans.modules.csl.api.Hint;
  135.54 +import org.netbeans.modules.csl.api.HintFix;
  135.55 +import org.netbeans.modules.csl.api.HintSeverity;
  135.56 +import org.netbeans.modules.csl.api.OffsetRange;
  135.57 +import org.netbeans.modules.csl.api.RuleContext;
  135.58 +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
  135.59 +import org.netbeans.modules.python.source.PythonAstUtils;
  135.60 +import org.netbeans.modules.python.source.PythonIndex;
  135.61 +import org.netbeans.modules.python.source.PythonParserResult;
  135.62 +import org.netbeans.modules.python.source.elements.IndexedElement;
  135.63 +import org.netbeans.modules.python.source.ImportManager;
  135.64 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  135.65 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  135.66 +import org.openide.util.NbBundle;
  135.67 +import org.python.antlr.PythonTree;
  135.68 +import org.python.antlr.ast.Attribute;
  135.69 +import org.python.antlr.ast.Call;
  135.70 +import org.python.antlr.ast.Module;
  135.71 +
  135.72 +/**
  135.73 + * Detect Unresolved variables
  135.74 + *
  135.75 + * @author Tor Norbye
  135.76 + */
  135.77 +public class UnresolvedDetector extends PythonAstRule {
  135.78 +    public UnresolvedDetector() {
  135.79 +    }
  135.80 +
  135.81 +    @Override
  135.82 +    public boolean appliesTo(RuleContext context) {
  135.83 +        return true;
  135.84 +    }
  135.85 +
  135.86 +    @Override
  135.87 +    public Set<Class> getKinds() {
  135.88 +        return Collections.<Class>singleton(Module.class);
  135.89 +    }
  135.90 +
  135.91 +    @Override
  135.92 +    public void run(PythonRuleContext context, List<Hint> result) {
  135.93 +        PythonParserResult info = (PythonParserResult) context.parserResult;
  135.94 +        SymbolTable symbolTable = info.getSymbolTable();
  135.95 +
  135.96 +        List<PythonTree> unresolvedNames = symbolTable.getUnresolved(info);
  135.97 +        if (unresolvedNames.size() > 0) {
  135.98 +            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
  135.99 +
 135.100 +            for (PythonTree node : unresolvedNames) {
 135.101 +                // Compute suggestions
 135.102 +                String name = PythonAstUtils.getName(node);
 135.103 +                if (name == null) {
 135.104 +                    name = "";
 135.105 +                }
 135.106 +                // Ignore keywords and builtin
 135.107 +                if (PythonLexerUtils.isKeywordOrBuiltin(name)) {
 135.108 +                    continue;
 135.109 +                }
 135.110 +
 135.111 +                List<HintFix> fixList = new ArrayList<>(3);
 135.112 +                // Is is a reference to a module?
 135.113 +                boolean tryModule = false;
 135.114 +                if (node.getParent() instanceof Call) {
 135.115 +                    Call call = (Call)node.getParent();
 135.116 +                    PythonTree t = call.getInternalFunc();
 135.117 +                    if (t instanceof Attribute) {
 135.118 +                        tryModule = true;
 135.119 +                    }
 135.120 +                }
 135.121 +                String message = NbBundle.getMessage(NameRule.class, "UnresolvedVariable", name);
 135.122 +                if (name.equals("true")) { // NOI18N
 135.123 +                    // Help for new language converts...
 135.124 +                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "True"); // NOI18N
 135.125 +                } else if (name.equals("false")) {
 135.126 +                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "False"); // NOI18N
 135.127 +                } else if (name.equals("nil") || name.equals("null")) {
 135.128 +                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "None"); // NOI18N
 135.129 +                } else if (name.equals("this")) {
 135.130 +                    message = NbBundle.getMessage(NameRule.class, "UnresolvedVariableMaybe", name, "self"); // NOI18N
 135.131 +                } else if (tryModule) {
 135.132 +                    Set<IndexedElement> moduleElements = index.getModules(name, QuerySupport.Kind.EXACT);
 135.133 +                    if (moduleElements.size() > 0) {
 135.134 +                        fixList.add(new ImportFix(context, node, name));
 135.135 +                    }
 135.136 +                } else {
 135.137 +                    Set<String> modules = index.getImportsFor(name, true);
 135.138 +                    if (modules.size() > 0) {
 135.139 +                        for (String module : modules) {
 135.140 +                            fixList.add(new ImportFix(context, node, module));
 135.141 +                        }
 135.142 +                    }
 135.143 +                }
 135.144 +
 135.145 +                OffsetRange range = PythonAstUtils.getNameRange(info, node);
 135.146 +                range = PythonLexerUtils.getLexerOffsets(info, range);
 135.147 +                if (range != OffsetRange.NONE) {
 135.148 +                    Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
 135.149 +                    result.add(desc);
 135.150 +                }
 135.151 +            }
 135.152 +        }
 135.153 +    }
 135.154 +
 135.155 +    @Override
 135.156 +    public String getId() {
 135.157 +        return "Unresolved"; // NOI18N
 135.158 +    }
 135.159 +
 135.160 +    @Override
 135.161 +    public String getDisplayName() {
 135.162 +        return NbBundle.getMessage(NameRule.class, "Unresolved");
 135.163 +    }
 135.164 +
 135.165 +    @Override
 135.166 +    public String getDescription() {
 135.167 +        return NbBundle.getMessage(NameRule.class, "UnresolvedDesc");
 135.168 +    }
 135.169 +
 135.170 +    @Override
 135.171 +    public boolean getDefaultEnabled() {
 135.172 +        return false;
 135.173 +    }
 135.174 +
 135.175 +    @Override
 135.176 +    public boolean showInTasklist() {
 135.177 +        return true;
 135.178 +    }
 135.179 +
 135.180 +    @Override
 135.181 +    public HintSeverity getDefaultSeverity() {
 135.182 +        return HintSeverity.ERROR;
 135.183 +    }
 135.184 +
 135.185 +    @Override
 135.186 +    public JComponent getCustomizer(Preferences node) {
 135.187 +        return null;
 135.188 +    }
 135.189 +
 135.190 +    private static class ImportFix implements HintFix {
 135.191 +        private final PythonRuleContext context;
 135.192 +        private final PythonTree node;
 135.193 +        private final String module;
 135.194 +
 135.195 +        private ImportFix(PythonRuleContext context, PythonTree node, String module) {
 135.196 +            this.context = context;
 135.197 +            this.node = node;
 135.198 +            this.module = module;
 135.199 +        }
 135.200 +
 135.201 +        @Override
 135.202 +        public String getDescription() {
 135.203 +            return NbBundle.getMessage(CreateDocString.class, "FixImport", module);
 135.204 +        }
 135.205 +
 135.206 +        @Override
 135.207 +        public void implement() throws Exception {
 135.208 +            String mod = this.module;
 135.209 +            String symbol = null;
 135.210 +            int colon = mod.indexOf(':');
 135.211 +            if (colon != -1) {
 135.212 +                int end = mod.indexOf('(', colon + 1);
 135.213 +                if (end == -1) {
 135.214 +                    end = mod.indexOf(';', colon + 1);
 135.215 +                    if (end == -1) {
 135.216 +                        end = mod.length();
 135.217 +                    }
 135.218 +                }
 135.219 +                symbol = mod.substring(colon + 1, end).trim();
 135.220 +                mod = mod.substring(0, colon).trim();
 135.221 +            }
 135.222 +            new ImportManager((PythonParserResult) context.parserResult).ensureImported(mod, symbol, false, false, true);
 135.223 +        }
 135.224 +
 135.225 +        @Override
 135.226 +        public boolean isSafe() {
 135.227 +            return true;
 135.228 +        }
 135.229 +
 135.230 +        @Override
 135.231 +        public boolean isInteractive() {
 135.232 +            return false;
 135.233 +        }
 135.234 +    }
 135.235 +}
   136.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   136.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/UnusedDetector.java	Mon Sep 21 13:01:16 2015 +0200
   136.3 @@ -0,0 +1,244 @@
   136.4 +/*
   136.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   136.6 + *
   136.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   136.8 + *
   136.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  136.10 + * Other names may be trademarks of their respective owners.
  136.11 + *
  136.12 + * The contents of this file are subject to the terms of either the GNU
  136.13 + * General Public License Version 2 only ("GPL") or the Common
  136.14 + * Development and Distribution License("CDDL") (collectively, the
  136.15 + * "License"). You may not use this file except in compliance with the
  136.16 + * License. You can obtain a copy of the License at
  136.17 + * http://www.netbeans.org/cddl-gplv2.html
  136.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  136.19 + * specific language governing permissions and limitations under the
  136.20 + * License.  When distributing the software, include this License Header
  136.21 + * Notice in each file and include the License file at
  136.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  136.23 + * particular file as subject to the "Classpath" exception as provided
  136.24 + * by Oracle in the GPL Version 2 section of the License file that
  136.25 + * accompanied this code. If applicable, add the following below the
  136.26 + * License Header, with the fields enclosed by brackets [] replaced by
  136.27 + * your own identifying information:
  136.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  136.29 + *
  136.30 + * If you wish your version of this file to be governed by only the CDDL
  136.31 + * or only the GPL Version 2, indicate your decision by adding
  136.32 + * "[Contributor] elects to include this software in this distribution
  136.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  136.34 + * single choice of license, a recipient has the option to distribute
  136.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  136.36 + * to extend the choice of license to its licensees as provided above.
  136.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  136.38 + * Version 2 license, then the option applies only if the new code is
  136.39 + * made subject to such option by the copyright holder.
  136.40 + *
  136.41 + * Contributor(s):
  136.42 + *
  136.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  136.44 + */
  136.45 +package org.netbeans.modules.python.hints;
  136.46 +
  136.47 +import java.util.ArrayList;
  136.48 +import java.util.Collections;
  136.49 +import java.util.HashSet;
  136.50 +import java.util.List;
  136.51 +import java.util.Set;
  136.52 +import java.util.prefs.Preferences;
  136.53 +import javax.swing.JComponent;
  136.54 +import org.netbeans.modules.csl.api.Hint;
  136.55 +import org.netbeans.modules.csl.api.HintFix;
  136.56 +import org.netbeans.modules.csl.api.HintSeverity;
  136.57 +import org.netbeans.modules.csl.api.OffsetRange;
  136.58 +import org.netbeans.modules.csl.api.RuleContext;
  136.59 +import org.netbeans.modules.python.source.PythonAstUtils;
  136.60 +import org.netbeans.modules.python.source.PythonParserResult;
  136.61 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  136.62 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  136.63 +import org.openide.util.NbBundle;
  136.64 +import org.python.antlr.PythonTree;
  136.65 +import org.python.antlr.ast.Assign;
  136.66 +import org.python.antlr.ast.For;
  136.67 +import org.python.antlr.ast.Module;
  136.68 +import org.python.antlr.ast.Tuple;
  136.69 +import org.python.antlr.base.expr;
  136.70 +
  136.71 +/**
  136.72 + * Detect unused variables
  136.73 + *
  136.74 + * @todo Find a more reliable way of detecting return tuples without relying on the
  136.75 + *  parent reference
  136.76 + *
  136.77 + * @author Tor Norbye
  136.78 + */
  136.79 +public class UnusedDetector extends PythonAstRule {
  136.80 +    /** Default names ignored */
  136.81 +    private static final String DEFAULT_IGNORED_NAMES = "_, dummy";
  136.82 +    private static final String PARAMS_KEY = "params"; // NOI18N
  136.83 +    private static final String SKIP_TUPLE_ASSIGN_KEY = "skipTuples"; // NOI18N
  136.84 +    private static final String IGNORED_KEY = "ignorednames"; // NOI18N
  136.85 +
  136.86 +    public UnusedDetector() {
  136.87 +    }
  136.88 +
  136.89 +    @Override
  136.90 +    public boolean appliesTo(RuleContext context) {
  136.91 +        return true;
  136.92 +    }
  136.93 +
  136.94 +    @Override
  136.95 +    public Set<Class> getKinds() {
  136.96 +        return Collections.<Class>singleton(Module.class);
  136.97 +    }
  136.98 +
  136.99 +    @Override
 136.100 +    public void run(PythonRuleContext context, List<Hint> result) {
 136.101 +        PythonParserResult info = (PythonParserResult) context.parserResult;
 136.102 +        SymbolTable symbolTable = info.getSymbolTable();
 136.103 +
 136.104 +        boolean skipParams = true;
 136.105 +        Preferences pref = context.manager.getPreferences(this);
 136.106 +        if (pref != null) {
 136.107 +            skipParams = getSkipParameters(pref);
 136.108 +        }
 136.109 +
 136.110 +        List<PythonTree> unusedNames = symbolTable.getUnused(true, skipParams);
 136.111 +        if (unusedNames.size() == 0) {
 136.112 +            return;
 136.113 +        }
 136.114 +
 136.115 +        boolean skipTupleAssigns = true;
 136.116 +        Set<String> ignoreNames = Collections.emptySet();
 136.117 +        if (pref != null) {
 136.118 +            skipParams = getSkipParameters(pref);
 136.119 +            skipTupleAssigns = getSkipTupleAssignments(pref);
 136.120 +            String ignoreNamesStr = getIgnoreNames(pref);
 136.121 +            if (ignoreNamesStr.length() > 0) {
 136.122 +                ignoreNames = new HashSet<>();
 136.123 +                for (String s : ignoreNamesStr.split(",")) { // NOI18N
 136.124 +                    ignoreNames.add(s.trim());
 136.125 +                }
 136.126 +            }
 136.127 +        }
 136.128 +
 136.129 +        for (PythonTree node : unusedNames) {
 136.130 +            if (skipTupleAssigns && isTupleAssignment(node)) {
 136.131 +                continue;
 136.132 +            }
 136.133 +            String name = PythonAstUtils.getName(node);
 136.134 +            if (name == null) {
 136.135 +                name = "";
 136.136 +            }
 136.137 +            if (ignoreNames.contains(name)) {
 136.138 +                continue;
 136.139 +            }
 136.140 +            OffsetRange range = PythonAstUtils.getNameRange(info, node);
 136.141 +            range = PythonLexerUtils.getLexerOffsets(info, range);
 136.142 +            if (range != OffsetRange.NONE) {
 136.143 +                List<HintFix> fixList = new ArrayList<>(3);
 136.144 +                String message = NbBundle.getMessage(NameRule.class, "UnusedVariable", name);
 136.145 +                Hint desc = new Hint(this, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2305);
 136.146 +                result.add(desc);
 136.147 +            }
 136.148 +        }
 136.149 +    }
 136.150 +
 136.151 +    private boolean isTupleAssignment(PythonTree node) {
 136.152 +        // This may not work right since the parent pointers often aren't set right;
 136.153 +        // find a more efficient way to do it correctly than a path search for each node
 136.154 +        if (node.getParent() instanceof Tuple) {
 136.155 +            // Allow tuples in tuples
 136.156 +            PythonTree parentParent = node.getParent().getParent();
 136.157 +            while (parentParent instanceof Tuple) {
 136.158 +                parentParent = parentParent.getParent();
 136.159 +                node = node.getParent();
 136.160 +            }
 136.161 +            if (parentParent instanceof Assign) {
 136.162 +                Assign assign = (Assign)parentParent;
 136.163 +                List<expr> targets = assign.getInternalTargets();
 136.164 +                if (targets != null && targets.size() > 0 && targets.get(0) == node.getParent()) {
 136.165 +                    return true;
 136.166 +                }
 136.167 +            }
 136.168 +            if (parentParent instanceof For &&
 136.169 +                    ((For)parentParent).getInternalTarget() == node.getParent()) {
 136.170 +                return true;
 136.171 +            }
 136.172 +        }
 136.173 +
 136.174 +        return false;
 136.175 +    }
 136.176 +
 136.177 +    @Override
 136.178 +    public String getId() {
 136.179 +        return "Unused"; // NOI18N
 136.180 +    }
 136.181 +
 136.182 +    @Override
 136.183 +    public String getDisplayName() {
 136.184 +        return NbBundle.getMessage(NameRule.class, "Unused");
 136.185 +    }
 136.186 +
 136.187 +    @Override
 136.188 +    public String getDescription() {
 136.189 +        return NbBundle.getMessage(NameRule.class, "UnusedDesc");
 136.190 +    }
 136.191 +
 136.192 +    @Override
 136.193 +    public boolean getDefaultEnabled() {
 136.194 +        return true;
 136.195 +    }
 136.196 +
 136.197 +    @Override
 136.198 +    public boolean showInTasklist() {
 136.199 +        return true;
 136.200 +    }
 136.201 +
 136.202 +    @Override
 136.203 +    public HintSeverity getDefaultSeverity() {
 136.204 +        return HintSeverity.WARNING;
 136.205 +    }
 136.206 +
 136.207 +    @Override
 136.208 +    public JComponent getCustomizer(Preferences node) {
 136.209 +        return new UnusedDetectorPrefs(node);
 136.210 +    }
 136.211 +
 136.212 +    static boolean getSkipParameters(Preferences prefs) {
 136.213 +        return prefs.getBoolean(PARAMS_KEY, true);
 136.214 +    }
 136.215 +
 136.216 +    static void setSkipParameters(Preferences prefs, boolean skipParams) {
 136.217 +        if (skipParams) {
 136.218 +            prefs.remove(PARAMS_KEY);
 136.219 +        } else {
 136.220 +            prefs.putBoolean(PARAMS_KEY, false);
 136.221 +        }
 136.222 +    }
 136.223 +
 136.224 +    static boolean getSkipTupleAssignments(Preferences prefs) {
 136.225 +        return prefs.getBoolean(SKIP_TUPLE_ASSIGN_KEY, true);
 136.226 +    }
 136.227 +
 136.228 +    static void setSkipTupleAssignments(Preferences prefs, boolean skipTupleAssigns) {
 136.229 +        if (skipTupleAssigns) {
 136.230 +            prefs.remove(SKIP_TUPLE_ASSIGN_KEY);
 136.231 +        } else {
 136.232 +            prefs.putBoolean(SKIP_TUPLE_ASSIGN_KEY, false);
 136.233 +        }
 136.234 +    }
 136.235 +
 136.236 +    static String getIgnoreNames(Preferences prefs) {
 136.237 +        return prefs.get(IGNORED_KEY, DEFAULT_IGNORED_NAMES);
 136.238 +    }
 136.239 +
 136.240 +    static void setIgnoreNames(Preferences prefs, String ignoredNames) {
 136.241 +        if (ignoredNames.length() == 0) {
 136.242 +            prefs.remove(IGNORED_KEY);
 136.243 +        } else {
 136.244 +            prefs.put(IGNORED_KEY, ignoredNames);
 136.245 +        }
 136.246 +    }
 136.247 +}
   137.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   137.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/UnusedDetectorPrefs.form	Mon Sep 21 13:01:16 2015 +0200
   137.3 @@ -0,0 +1,84 @@
   137.4 +<?xml version="1.0" encoding="UTF-8" ?>
   137.5 +
   137.6 +<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   137.7 +  <AuxValues>
   137.8 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
   137.9 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  137.10 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  137.11 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
  137.12 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  137.13 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
  137.14 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="2"/>
  137.15 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  137.16 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  137.17 +  </AuxValues>
  137.18 +
  137.19 +  <Layout>
  137.20 +    <DimensionLayout dim="0">
  137.21 +      <Group type="103" groupAlignment="0" attributes="0">
  137.22 +          <Component id="skipParams" min="-2" max="-2" attributes="0"/>
  137.23 +          <Component id="skipTupleAssignments" alignment="0" min="-2" max="-2" attributes="0"/>
  137.24 +          <Group type="102" alignment="0" attributes="0">
  137.25 +              <Component id="ignoredLabel" min="-2" max="-2" attributes="0"/>
  137.26 +              <EmptySpace max="-2" attributes="0"/>
  137.27 +              <Component id="ignoredNames" min="-2" max="-2" attributes="0"/>
  137.28 +          </Group>
  137.29 +      </Group>
  137.30 +    </DimensionLayout>
  137.31 +    <DimensionLayout dim="1">
  137.32 +      <Group type="103" groupAlignment="0" attributes="0">
  137.33 +          <Group type="102" attributes="0">
  137.34 +              <Component id="skipParams" min="-2" max="-2" attributes="0"/>
  137.35 +              <EmptySpace max="-2" attributes="0"/>
  137.36 +              <Component id="skipTupleAssignments" min="-2" max="-2" attributes="0"/>
  137.37 +              <EmptySpace max="-2" attributes="0"/>
  137.38 +              <Group type="103" groupAlignment="3" attributes="0">
  137.39 +                  <Component id="ignoredLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  137.40 +                  <Component id="ignoredNames" alignment="3" min="-2" max="-2" attributes="0"/>
  137.41 +              </Group>
  137.42 +              <EmptySpace max="32767" attributes="0"/>
  137.43 +          </Group>
  137.44 +      </Group>
  137.45 +    </DimensionLayout>
  137.46 +  </Layout>
  137.47 +  <SubComponents>
  137.48 +    <Component class="javax.swing.JCheckBox" name="skipParams">
  137.49 +      <Properties>
  137.50 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  137.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;)"/>
  137.52 +        </Property>
  137.53 +      </Properties>
  137.54 +      <Events>
  137.55 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
  137.56 +      </Events>
  137.57 +    </Component>
  137.58 +    <Component class="javax.swing.JCheckBox" name="skipTupleAssignments">
  137.59 +      <Properties>
  137.60 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  137.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;)"/>
  137.62 +        </Property>
  137.63 +      </Properties>
  137.64 +      <Events>
  137.65 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
  137.66 +      </Events>
  137.67 +    </Component>
  137.68 +    <Component class="javax.swing.JTextField" name="ignoredNames">
  137.69 +      <Properties>
  137.70 +        <Property name="columns" type="int" value="25"/>
  137.71 +      </Properties>
  137.72 +      <Events>
  137.73 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changed"/>
  137.74 +      </Events>
  137.75 +    </Component>
  137.76 +    <Component class="javax.swing.JLabel" name="ignoredLabel">
  137.77 +      <Properties>
  137.78 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  137.79 +          <ComponentRef name="ignoredNames"/>
  137.80 +        </Property>
  137.81 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  137.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;)"/>
  137.83 +        </Property>
  137.84 +      </Properties>
  137.85 +    </Component>
  137.86 +  </SubComponents>
  137.87 +</Form>
   138.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   138.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/UnusedDetectorPrefs.java	Mon Sep 21 13:01:16 2015 +0200
   138.3 @@ -0,0 +1,152 @@
   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 +
  138.46 +/*
  138.47 + * UnusedDetectorPrefs.java
  138.48 + *
  138.49 + * Created on Nov 10, 2008, 9:48:35 AM
  138.50 + */
  138.51 +package org.netbeans.modules.python.hints;
  138.52 +
  138.53 +import java.awt.event.ActionListener;
  138.54 +import java.util.prefs.Preferences;
  138.55 +
  138.56 +/**
  138.57 + * Preferences where users can configure the unused detector rules
  138.58 + * 
  138.59 + * @author Tor Norbye
  138.60 + */
  138.61 +public class UnusedDetectorPrefs extends javax.swing.JPanel implements ActionListener {
  138.62 +    private Preferences prefs;
  138.63 +
  138.64 +    /** Creates new form UnusedDetectorPrefs */
  138.65 +    public UnusedDetectorPrefs(Preferences prefs) {
  138.66 +        initComponents();
  138.67 +        this.prefs = prefs;
  138.68 +        skipParams.setSelected(UnusedDetector.getSkipParameters(prefs));
  138.69 +        skipTupleAssignments.setSelected(UnusedDetector.getSkipTupleAssignments(prefs));
  138.70 +        String ignore = UnusedDetector.getIgnoreNames(prefs);
  138.71 +        if (ignore == null) {
  138.72 +            ignore = "";
  138.73 +        }
  138.74 +        ignoredNames.setText(ignore);
  138.75 +    }
  138.76 +
  138.77 +    @SuppressWarnings("unchecked")
  138.78 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  138.79 +    private void initComponents() {
  138.80 +
  138.81 +        skipParams = new javax.swing.JCheckBox();
  138.82 +        skipTupleAssignments = new javax.swing.JCheckBox();
  138.83 +        ignoredNames = new javax.swing.JTextField();
  138.84 +        ignoredLabel = new javax.swing.JLabel();
  138.85 +
  138.86 +        skipParams.setText(org.openide.util.NbBundle.getMessage(UnusedDetectorPrefs.class, "UnusedDetectorPrefs.skipParams.text")); // NOI18N
  138.87 +        skipParams.addActionListener(this);
  138.88 +
  138.89 +        skipTupleAssignments.setText(org.openide.util.NbBundle.getMessage(UnusedDetectorPrefs.class, "UnusedDetectorPrefs.skipTupleAssignments.text")); // NOI18N
  138.90 +        skipTupleAssignments.addActionListener(this);
  138.91 +
  138.92 +        ignoredNames.setColumns(25);
  138.93 +        ignoredNames.addActionListener(this);
  138.94 +
  138.95 +        ignoredLabel.setLabelFor(ignoredNames);
  138.96 +        ignoredLabel.setText(org.openide.util.NbBundle.getMessage(UnusedDetectorPrefs.class, "UnusedDetectorPrefs.ignoredLabel.text")); // NOI18N
  138.97 +
  138.98 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
  138.99 +        this.setLayout(layout);
 138.100 +        layout.setHorizontalGroup(
 138.101 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 138.102 +            .addComponent(skipParams)
 138.103 +            .addComponent(skipTupleAssignments)
 138.104 +            .addGroup(layout.createSequentialGroup()
 138.105 +                .addComponent(ignoredLabel)
 138.106 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 138.107 +                .addComponent(ignoredNames, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 138.108 +        );
 138.109 +        layout.setVerticalGroup(
 138.110 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 138.111 +            .addGroup(layout.createSequentialGroup()
 138.112 +                .addComponent(skipParams)
 138.113 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 138.114 +                .addComponent(skipTupleAssignments)
 138.115 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 138.116 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 138.117 +                    .addComponent(ignoredLabel)
 138.118 +                    .addComponent(ignoredNames, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 138.119 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 138.120 +        );
 138.121 +    }
 138.122 +
 138.123 +    // Code for dispatching events from components to event handlers.
 138.124 +
 138.125 +    public void actionPerformed(java.awt.event.ActionEvent evt) {
 138.126 +        if (evt.getSource() == skipParams) {
 138.127 +            UnusedDetectorPrefs.this.changed(evt);
 138.128 +        }
 138.129 +        else if (evt.getSource() == skipTupleAssignments) {
 138.130 +            UnusedDetectorPrefs.this.changed(evt);
 138.131 +        }
 138.132 +        else if (evt.getSource() == ignoredNames) {
 138.133 +            UnusedDetectorPrefs.this.changed(evt);
 138.134 +        }
 138.135 +    }// </editor-fold>//GEN-END:initComponents
 138.136 +
 138.137 +    private void changed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_changed
 138.138 +        Object source = evt.getSource();
 138.139 +        if (source == ignoredNames) {
 138.140 +            UnusedDetector.setIgnoreNames(prefs, ignoredNames.getText().trim());
 138.141 +        } else if (source == skipParams) {
 138.142 +            UnusedDetector.setSkipParameters(prefs, skipParams.isSelected());
 138.143 +        } else if (source == skipTupleAssignments) {
 138.144 +            UnusedDetector.setSkipTupleAssignments(prefs, skipTupleAssignments.isSelected());
 138.145 +        } else {
 138.146 +            assert false : source;
 138.147 +        }
 138.148 +    }//GEN-LAST:event_changed
 138.149 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 138.150 +    private javax.swing.JLabel ignoredLabel;
 138.151 +    private javax.swing.JTextField ignoredNames;
 138.152 +    private javax.swing.JCheckBox skipParams;
 138.153 +    private javax.swing.JCheckBox skipTupleAssignments;
 138.154 +    // End of variables declaration//GEN-END:variables
 138.155 +}
   139.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   139.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/UnusedImports.java	Mon Sep 21 13:01:16 2015 +0200
   139.3 @@ -0,0 +1,286 @@
   139.4 +/*
   139.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   139.6 + *
   139.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   139.8 + *
   139.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  139.10 + * Other names may be trademarks of their respective owners.
  139.11 + *
  139.12 + * The contents of this file are subject to the terms of either the GNU
  139.13 + * General Public License Version 2 only ("GPL") or the Common
  139.14 + * Development and Distribution License("CDDL") (collectively, the
  139.15 + * "License"). You may not use this file except in compliance with the
  139.16 + * License. You can obtain a copy of the License at
  139.17 + * http://www.netbeans.org/cddl-gplv2.html
  139.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  139.19 + * specific language governing permissions and limitations under the
  139.20 + * License.  When distributing the software, include this License Header
  139.21 + * Notice in each file and include the License file at
  139.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  139.23 + * particular file as subject to the "Classpath" exception as provided
  139.24 + * by Oracle in the GPL Version 2 section of the License file that
  139.25 + * accompanied this code. If applicable, add the following below the
  139.26 + * License Header, with the fields enclosed by brackets [] replaced by
  139.27 + * your own identifying information:
  139.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  139.29 + *
  139.30 + * If you wish your version of this file to be governed by only the CDDL
  139.31 + * or only the GPL Version 2, indicate your decision by adding
  139.32 + * "[Contributor] elects to include this software in this distribution
  139.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  139.34 + * single choice of license, a recipient has the option to distribute
  139.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  139.36 + * to extend the choice of license to its licensees as provided above.
  139.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  139.38 + * Version 2 license, then the option applies only if the new code is
  139.39 + * made subject to such option by the copyright holder.
  139.40 + *
  139.41 + * Contributor(s):
  139.42 + *
  139.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  139.44 + */
  139.45 +package org.netbeans.modules.python.hints;
  139.46 +
  139.47 +import java.util.ArrayList;
  139.48 +import java.util.Collections;
  139.49 +import java.util.HashMap;
  139.50 +import java.util.List;
  139.51 +import java.util.Map;
  139.52 +import java.util.Set;
  139.53 +import java.util.prefs.Preferences;
  139.54 +import javax.swing.JComponent;
  139.55 +import org.netbeans.editor.BaseDocument;
  139.56 +import org.netbeans.modules.csl.api.EditList;
  139.57 +import org.netbeans.modules.csl.api.Hint;
  139.58 +import org.netbeans.modules.csl.api.HintFix;
  139.59 +import org.netbeans.modules.csl.api.HintSeverity;
  139.60 +import org.netbeans.modules.csl.api.OffsetRange;
  139.61 +import org.netbeans.modules.csl.api.RuleContext;
  139.62 +import org.netbeans.modules.python.source.PythonAstUtils;
  139.63 +import org.netbeans.modules.python.source.PythonParserResult;
  139.64 +import org.netbeans.modules.python.source.ImportEntry;
  139.65 +import org.netbeans.modules.python.source.ImportManager;
  139.66 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  139.67 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  139.68 +import org.openide.filesystems.FileObject;
  139.69 +import org.openide.util.NbBundle;
  139.70 +import org.python.antlr.PythonTree;
  139.71 +import org.python.antlr.ast.Import;
  139.72 +import org.python.antlr.ast.ImportFrom;
  139.73 +import org.python.antlr.ast.Module;
  139.74 +import org.python.antlr.ast.alias;
  139.75 +
  139.76 +/**
  139.77 + * Detect unused imports
  139.78 + *
  139.79 + * @author Tor Norbye
  139.80 + */
  139.81 +public class UnusedImports extends PythonAstRule {
  139.82 +    public UnusedImports() {
  139.83 +    }
  139.84 +
  139.85 +    @Override
  139.86 +    public boolean appliesTo(RuleContext context) {
  139.87 +        FileObject fo = context.parserResult.getSnapshot().getSource().getFileObject();
  139.88 +        return fo == null || !fo.getName().equals("__init__"); // NOI18N
  139.89 +    }
  139.90 +
  139.91 +    @Override
  139.92 +    public Set<Class> getKinds() {
  139.93 +        return Collections.<Class>singleton(Module.class);
  139.94 +    }
  139.95 +
  139.96 +    @Override
  139.97 +    public void run(PythonRuleContext context, List<Hint> result) {
  139.98 +        computeUnusedImports(this, context, result, null);
  139.99 +    }
 139.100 +
 139.101 +    private static void computeUnusedImports(UnusedImports detector, PythonRuleContext context, List<Hint> result, Map<PythonTree, List<String>> unused) {
 139.102 +        assert result == null || unused == null; // compute either results or set of unused
 139.103 +
 139.104 +        PythonParserResult info = (PythonParserResult) context.parserResult;
 139.105 +        SymbolTable symbolTable = info.getSymbolTable();
 139.106 +        List<ImportEntry> unusedImports = symbolTable.getUnusedImports();
 139.107 +        if (unusedImports.isEmpty()) {
 139.108 +            return;
 139.109 +        }
 139.110 +        Map<PythonTree, List<String>> maps = new HashMap<>();
 139.111 +        for (ImportEntry entry : unusedImports) {
 139.112 +            maps.put(entry.node, new ArrayList<String>());
 139.113 +        }
 139.114 +        for (ImportEntry entry : unusedImports) {
 139.115 +            if (entry.isFromImport) {
 139.116 +                String name = entry.asName != null ? entry.asName : entry.symbol;
 139.117 +                maps.get(entry.node).add(name);
 139.118 +            } else {
 139.119 +                String name = entry.asName != null ? entry.asName : entry.module;
 139.120 +                maps.get(entry.node).add(name);
 139.121 +            }
 139.122 +        }
 139.123 +        for (Map.Entry<PythonTree, List<String>> entry : maps.entrySet()) {
 139.124 +            PythonTree node = entry.getKey();
 139.125 +            List<String> list = entry.getValue();
 139.126 +            if (node instanceof Import) {
 139.127 +                Import imp = (Import)node;
 139.128 +                List<alias> names = imp.getInternalNames();
 139.129 +                if (names != null && names.size() == list.size()) {
 139.130 +                    list.clear();
 139.131 +                }
 139.132 +            } else {
 139.133 +                assert node instanceof ImportFrom;
 139.134 +                ImportFrom imp = (ImportFrom)node;
 139.135 +                List<alias> names = imp.getInternalNames();
 139.136 +                if (names != null && names.size() == list.size()) {
 139.137 +                    list.clear();
 139.138 +                }
 139.139 +            }
 139.140 +        }
 139.141 +
 139.142 +        for (Map.Entry<PythonTree, List<String>> entry : maps.entrySet()) {
 139.143 +            PythonTree node = entry.getKey();
 139.144 +            List<String> list = entry.getValue();
 139.145 +            if (list.size() == 0) {
 139.146 +                list = null;
 139.147 +            }
 139.148 +            if (unused != null) {
 139.149 +                unused.put(node, list);
 139.150 +            } else {
 139.151 +                addError(detector, context, node, list, result);
 139.152 +            }
 139.153 +        }
 139.154 +    }
 139.155 +
 139.156 +    private static void addError(UnusedImports detector, PythonRuleContext context, PythonTree node, List<String> symbols, List<Hint> result) {
 139.157 +        PythonParserResult info = (PythonParserResult) context.parserResult;
 139.158 +        OffsetRange range = PythonAstUtils.getNameRange(info, node);
 139.159 +        range = PythonLexerUtils.getLexerOffsets(info, range);
 139.160 +        if (range != OffsetRange.NONE) {
 139.161 +            List<HintFix> fixList = new ArrayList<>(3);
 139.162 +            fixList.add(new UnusedFix(detector, context, node, symbols, false));
 139.163 +            fixList.add(new UnusedFix(detector, context, null, null, false)); // Remove All
 139.164 +            fixList.add(new UnusedFix(detector, context, null, null, true)); // Organize
 139.165 +            String message;
 139.166 +            if (symbols != null) {
 139.167 +                message = NbBundle.getMessage(NameRule.class, "UnusedImportSymbols", symbols);
 139.168 +            } else {
 139.169 +                message = NbBundle.getMessage(NameRule.class, "UnusedImport");
 139.170 +            }
 139.171 +            Hint desc = new Hint(detector, message, info.getSnapshot().getSource().getFileObject(), range, fixList, 2500);
 139.172 +            result.add(desc);
 139.173 +        }
 139.174 +    }
 139.175 +
 139.176 +    @Override
 139.177 +    public String getId() {
 139.178 +        return "UnusedImports"; // NOI18N
 139.179 +    }
 139.180 +
 139.181 +    @Override
 139.182 +    public String getDisplayName() {
 139.183 +        return NbBundle.getMessage(NameRule.class, "UnusedImports");
 139.184 +    }
 139.185 +
 139.186 +    @Override
 139.187 +    public String getDescription() {
 139.188 +        return NbBundle.getMessage(NameRule.class, "UnusedImportsDesc");
 139.189 +    }
 139.190 +
 139.191 +    @Override
 139.192 +    public boolean getDefaultEnabled() {
 139.193 +        return true;
 139.194 +    }
 139.195 +
 139.196 +    @Override
 139.197 +    public boolean showInTasklist() {
 139.198 +        return false; // ? or maybe yes?
 139.199 +    }
 139.200 +
 139.201 +    @Override
 139.202 +    public HintSeverity getDefaultSeverity() {
 139.203 +        return HintSeverity.WARNING;
 139.204 +    }
 139.205 +
 139.206 +    @Override
 139.207 +    public JComponent getCustomizer(Preferences node) {
 139.208 +        return null;
 139.209 +    }
 139.210 +
 139.211 +    /**
 139.212 +     * Fix to insert self argument or rename first argument to self
 139.213 +     */
 139.214 +    private static class UnusedFix implements /*PreviewableFix*/ HintFix { // Preview not particularly helpful and clutters menu
 139.215 +        private final UnusedImports detector;
 139.216 +        private final PythonRuleContext context;
 139.217 +        private final PythonTree node;
 139.218 +        private final List<String> symbols;
 139.219 +        private final boolean organizeOnly;
 139.220 +
 139.221 +        private UnusedFix(UnusedImports detector, PythonRuleContext context, PythonTree node, List<String> symbols, boolean organizeOnly) {
 139.222 +            this.detector = detector;
 139.223 +            this.context = context;
 139.224 +            this.node = node;
 139.225 +            this.symbols = symbols;
 139.226 +            this.organizeOnly = organizeOnly;
 139.227 +        }
 139.228 +
 139.229 +        @Override
 139.230 +        public String getDescription() {
 139.231 +            if (node == null) {
 139.232 +                if (organizeOnly) {
 139.233 +                    return NbBundle.getMessage(CreateDocString.class, "OrganizeImports");
 139.234 +                } else {
 139.235 +                    return NbBundle.getMessage(CreateDocString.class, "DeleteAllUnused");
 139.236 +                }
 139.237 +            } else if (symbols != null) {
 139.238 +                return NbBundle.getMessage(CreateDocString.class, "UnusedFixSymbols", symbols);
 139.239 +            } else {
 139.240 +                return NbBundle.getMessage(CreateDocString.class, "UnusedFix");
 139.241 +            }
 139.242 +        }
 139.243 +
 139.244 +        public boolean canPreview() {
 139.245 +            return true;
 139.246 +        }
 139.247 +
 139.248 +        public EditList getEditList() throws Exception {
 139.249 +            BaseDocument doc = context.doc;
 139.250 +            EditList edits = new EditList(doc);
 139.251 +
 139.252 +            ImportManager importManager = new ImportManager((PythonParserResult) context.parserResult);
 139.253 +
 139.254 +            if (node == null) {
 139.255 +                if (organizeOnly) {
 139.256 +                    importManager.cleanup(edits, 0, doc.getLength(), true);
 139.257 +                } else {
 139.258 +                    Map<PythonTree, List<String>> onlyNames = new HashMap<>();
 139.259 +                    computeUnusedImports(detector, context, null, onlyNames);
 139.260 +                    Set<PythonTree> candidates = onlyNames.keySet();
 139.261 +                    importManager.removeImports(edits, candidates, false, onlyNames);
 139.262 +                }
 139.263 +            } else {
 139.264 +                Set<PythonTree> candidates = Collections.singleton(node);
 139.265 +                Map<PythonTree, List<String>> onlyNames = new HashMap<>();
 139.266 +                onlyNames.put(node, symbols);
 139.267 +                importManager.removeImports(edits, candidates, false, onlyNames);
 139.268 +            }
 139.269 +
 139.270 +            return edits;
 139.271 +        }
 139.272 +
 139.273 +        @Override
 139.274 +        public void implement() throws Exception {
 139.275 +            EditList edits = getEditList();
 139.276 +            edits.apply();
 139.277 +        }
 139.278 +
 139.279 +        @Override
 139.280 +        public boolean isSafe() {
 139.281 +            return true;
 139.282 +        }
 139.283 +
 139.284 +        @Override
 139.285 +        public boolean isInteractive() {
 139.286 +            return false;
 139.287 +        }
 139.288 +    }
 139.289 +}
   140.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   140.2 +++ b/python.hints/src/org/netbeans/modules/python/hints/layer.xml	Mon Sep 21 13:01:16 2015 +0200
   140.3 @@ -0,0 +1,61 @@
   140.4 +<?xml version="1.0" encoding="UTF-8"?>
   140.5 +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
   140.6 +<filesystem>
   140.7 +    
   140.8 +    <folder name="csl-hints">
   140.9 +        <folder name="text">
  140.10 +            <folder name="x-python">
  140.11 +                <folder name="hints">
  140.12 +                    <folder name="general">
  140.13 +                        <attr name="position" intvalue="100"/>
  140.14 +                        <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.python.editor.hints.Bundle"/>
  140.15 +                        <file name="org-netbeans-modules-python-hints-NameRule.instance"/>
  140.16 +                        <file name="org-netbeans-modules-python-hints-CreateDocString.instance"/>
  140.17 +                        <file name="org-netbeans-modules-python-hints-AssignToVariable.instance"/>
  140.18 +                        <file name="org-netbeans-modules-python-hints-SplitImports.instance"/>
  140.19 +                        <file name="org-netbeans-modules-python-hints-RelativeImports.instance"/>
  140.20 +                        <file name="org-netbeans-modules-python-hints-Deprecations.instance"/>
  140.21 +                        <file name="org-netbeans-modules-python-hints-UnusedImports.instance"/>
  140.22 +                        <file name="org-netbeans-modules-python-hints-UnusedDetector.instance"/>
  140.23 +                        <file name="org-netbeans-modules-python-hints-UnresolvedDetector.instance"/>
  140.24 +                        <file name="org-netbeans-modules-python-hints-UnresolvedClassComponents.instance"/>
  140.25 +                        <file name="org-netbeans-modules-python-hints-AllAssignExists.instance"/>
  140.26 +                        <file name="org-netbeans-modules-python-hints-AccessToProtected.instance"/>
  140.27 +                        <file name="org-netbeans-modules-python-hints-AttributeDefinedOutsideInit.instance"/>
  140.28 +                        <file name="org-netbeans-modules-python-hints-ClassCircularRedundancy.instance"/>
  140.29 +                    </folder>
  140.30 +                </folder>
  140.31 +                <folder name="selection">
  140.32 +                    <file name="org-netbeans-modules-python-editor-hints-SurroundWith.instance"/>
  140.33 +                    <file name="org-netbeans-modules-python-editor-hints-ExtractCode.instance"/>
  140.34 +                </folder>
  140.35 +            </folder>
  140.36 +        </folder>
  140.37 +    </folder>
  140.38 +    
  140.39 +    <folder name="CslPlugins">
  140.40 +        <folder name="text">
  140.41 +            <folder name="x-python">
  140.42 +                <file name="hints.instance">
  140.43 +                    <attr name="instanceClass" stringvalue="org.netbeans.modules.python.hints.PythonHintsProvider"/>
  140.44 +                </file>
  140.45 +            </folder>
  140.46 +        </folder>
  140.47 +    </folder>
  140.48 +    
  140.49 +    <folder name="OptionsDialog">
  140.50 +        <folder name="Editor">
  140.51 +            <folder name="Hints">
  140.52 +                <attr name="position" intvalue="0"/>
  140.53 +                <folder name="text">
  140.54 +                    <folder name="x-python">
  140.55 +                        <file name="PythonHints.instance">
  140.56 +                            <attr name="instanceOf" stringvalue="org.netbeans.spi.options.OptionsPanelController"/>
  140.57 +                            <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.hints.PythonHintOptions.createStatic"/>
  140.58 +                        </file>
  140.59 +                    </folder>
  140.60 +                </folder>
  140.61 +            </folder>
  140.62 +        </folder>
  140.63 +    </folder>
  140.64 +</filesystem>
   141.1 --- a/python.project/src/org/netbeans/modules/python/project/GotoTest.java	Fri Sep 18 16:20:24 2015 -0500
   141.2 +++ b/python.project/src/org/netbeans/modules/python/project/GotoTest.java	Mon Sep 21 13:01:16 2015 +0200
   141.3 @@ -48,7 +48,7 @@
   141.4  import java.util.regex.Pattern;
   141.5  
   141.6  
   141.7 -import org.netbeans.modules.python.editor.PythonUtils;
   141.8 +import org.netbeans.modules.python.source.PythonUtils;
   141.9  import org.netbeans.spi.gototest.TestLocator;
  141.10  import org.netbeans.spi.gototest.TestLocator.LocationResult;
  141.11  import org.openide.filesystems.FileObject;
   142.1 --- a/python.project/src/org/netbeans/modules/python/project/PythonLogicalView.java	Fri Sep 18 16:20:24 2015 -0500
   142.2 +++ b/python.project/src/org/netbeans/modules/python/project/PythonLogicalView.java	Mon Sep 21 13:01:16 2015 +0200
   142.3 @@ -85,7 +85,8 @@
   142.4  
   142.5          public PythonProjectNode() {
   142.6              super(NodeFactorySupport.createCompositeChildren(project, "Projects/org-netbeans-modules-python-project/Nodes"),
   142.7 -                    Lookups.singleton(project));
   142.8 +                    project.sourceRoots.getRoots().length > 0 ? Lookups.fixed(project, project.sourceRoots.getRoots()[0]) :
   142.9 +                            Lookups.singleton(project));
  142.10              setIconBaseWithExtension("org/netbeans/modules/python/project/resources/py_25_16.png");
  142.11              super.setName(ProjectUtils.getInformation(project).getDisplayName());
  142.12          }
   143.1 --- a/python.project2/src/org/netbeans/modules/python/project2/PythonProject2.java	Fri Sep 18 16:20:24 2015 -0500
   143.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/PythonProject2.java	Mon Sep 21 13:01:16 2015 +0200
   143.3 @@ -24,7 +24,9 @@
   143.4  import org.netbeans.spi.project.AuxiliaryConfiguration;
   143.5  import org.netbeans.spi.project.ProjectState;
   143.6  import org.netbeans.spi.project.ui.LogicalViewProvider;
   143.7 +import org.netbeans.spi.project.ui.PrivilegedTemplates;
   143.8  import org.netbeans.spi.project.ui.ProjectOpenedHook;
   143.9 +import org.netbeans.spi.project.ui.RecommendedTemplates;
  143.10  import org.openide.filesystems.FileAttributeEvent;
  143.11  import org.openide.filesystems.FileChangeListener;
  143.12  import org.openide.filesystems.FileEvent;
  143.13 @@ -114,10 +116,11 @@
  143.14  //            new PythonPlatformProvider(getEvaluator()),
  143.15              new PythonCoverageProvider(this),
  143.16              new PythonProjectSourceLevelQuery(this),
  143.17 +            new RecommendedTemplatesImpl(),
  143.18              state
  143.19          });
  143.20      }
  143.21 -
  143.22 +    
  143.23      public void addPropertyChangeListener(PropertyChangeListener propertyChangeListener) {
  143.24          support.addPropertyChangeListener(propertyChangeListener);
  143.25      }
  143.26 @@ -379,4 +382,32 @@
  143.27  //            }
  143.28          }
  143.29      }
  143.30 +
  143.31 +    private static final class RecommendedTemplatesImpl implements RecommendedTemplates, PrivilegedTemplates {
  143.32 +
  143.33 +        // List of primarily supported templates
  143.34 +        private static final String[] APPLICATION_TYPES = new String[]{
  143.35 +            "python", // NOI18N
  143.36 +            "XML", // NOI18N
  143.37 +            "simple-files" // NOI18N
  143.38 +        };
  143.39 +
  143.40 +        private static final String[] PRIVILEGED_NAMES = new String[]{
  143.41 +            "Templates/Python/_package", // NOI18N
  143.42 +            "Templates/Python/_module.py", //NOI18N
  143.43 +            "Templates/Python/_main.py", // NOI18N
  143.44 +            "Templates/Python/_empty_module.py", // NOI18N
  143.45 +            "Templates/Python/_test.py", // NOI18N
  143.46 +        };
  143.47 +
  143.48 +        @Override
  143.49 +        public String[] getRecommendedTypes() {
  143.50 +            return APPLICATION_TYPES;
  143.51 +        }
  143.52 +
  143.53 +        @Override
  143.54 +        public String[] getPrivilegedTemplates() {
  143.55 +            return PRIVILEGED_NAMES;
  143.56 +        }
  143.57 +    }
  143.58  }
   144.1 --- a/python.source/manifest.mf	Fri Sep 18 16:20:24 2015 -0500
   144.2 +++ b/python.source/manifest.mf	Mon Sep 21 13:01:16 2015 +0200
   144.3 @@ -1,5 +1,6 @@
   144.4  Manifest-Version: 1.0
   144.5  OpenIDE-Module: org.netbeans.modules.python.source
   144.6 +OpenIDE-Module-Layer: org/netbeans/modules/python/source/layer.xml
   144.7  OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/python/source/Bundle.properties
   144.8 -OpenIDE-Module-Specification-Version: 1.0
   144.9 +OpenIDE-Module-Specification-Version: 1.1
  144.10  AutoUpdate-Show-In-Client: false
   145.1 --- a/python.source/nbproject/project.xml	Fri Sep 18 16:20:24 2015 -0500
   145.2 +++ b/python.source/nbproject/project.xml	Mon Sep 21 13:01:16 2015 +0200
   145.3 @@ -7,6 +7,15 @@
   145.4              <!--<suite-component/>-->
   145.5              <module-dependencies>
   145.6                  <dependency>
   145.7 +                    <code-name-base>org.jython</code-name-base>
   145.8 +                    <build-prerequisite/>
   145.9 +                    <compile-dependency/>
  145.10 +                    <run-dependency>
  145.11 +                        <release-version>2</release-version>
  145.12 +                        <specification-version>2.12</specification-version>
  145.13 +                    </run-dependency>
  145.14 +                </dependency>
  145.15 +                <dependency>
  145.16                      <code-name-base>org.netbeans.api.annotations.common</code-name-base>
  145.17                      <build-prerequisite/>
  145.18                      <compile-dependency/>
  145.19 @@ -16,6 +25,103 @@
  145.20                      </run-dependency>
  145.21                  </dependency>
  145.22                  <dependency>
  145.23 +                    <code-name-base>org.netbeans.modules.csl.api</code-name-base>
  145.24 +                    <build-prerequisite/>
  145.25 +                    <compile-dependency/>
  145.26 +                    <run-dependency>
  145.27 +                        <release-version>2</release-version>
  145.28 +                        <specification-version>2.51</specification-version>
  145.29 +                    </run-dependency>
  145.30 +                </dependency>
  145.31 +                <dependency>
  145.32 +                    <code-name-base>org.netbeans.modules.editor.document</code-name-base>
  145.33 +                    <build-prerequisite/>
  145.34 +                    <compile-dependency/>
  145.35 +                    <run-dependency>
  145.36 +                        <specification-version>1.5</specification-version>
  145.37 +                    </run-dependency>
  145.38 +                </dependency>
  145.39 +                <dependency>
  145.40 +                    <code-name-base>org.netbeans.modules.editor.indent</code-name-base>
  145.41 +                    <build-prerequisite/>
  145.42 +                    <compile-dependency/>
  145.43 +                    <run-dependency>
  145.44 +                        <release-version>2</release-version>
  145.45 +                        <specification-version>1.42</specification-version>
  145.46 +                    </run-dependency>
  145.47 +                </dependency>
  145.48 +                <dependency>
  145.49 +                    <code-name-base>org.netbeans.modules.editor.lib</code-name-base>
  145.50 +                    <build-prerequisite/>
  145.51 +                    <compile-dependency/>
  145.52 +                    <run-dependency>
  145.53 +                        <release-version>3</release-version>
  145.54 +                        <specification-version>4.3</specification-version>
  145.55 +                    </run-dependency>
  145.56 +                </dependency>
  145.57 +                <dependency>
  145.58 +                    <code-name-base>org.netbeans.modules.editor.lib2</code-name-base>
  145.59 +                    <build-prerequisite/>
  145.60 +                    <compile-dependency/>
  145.61 +                    <run-dependency>
  145.62 +                        <release-version>1</release-version>
  145.63 +                        <specification-version>2.3</specification-version>
  145.64 +                    </run-dependency>
  145.65 +                </dependency>
  145.66 +                <dependency>
  145.67 +                    <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
  145.68 +                    <build-prerequisite/>
  145.69 +                    <compile-dependency/>
  145.70 +                    <run-dependency>
  145.71 +                        <release-version>1</release-version>
  145.72 +                        <specification-version>1.39</specification-version>
  145.73 +                    </run-dependency>
  145.74 +                </dependency>
  145.75 +                <dependency>
  145.76 +                    <code-name-base>org.netbeans.modules.editor.settings</code-name-base>
  145.77 +                    <build-prerequisite/>
  145.78 +                    <compile-dependency/>
  145.79 +                    <run-dependency>
  145.80 +                        <release-version>1</release-version>
  145.81 +                        <specification-version>1.55</specification-version>
  145.82 +                    </run-dependency>
  145.83 +                </dependency>
  145.84 +                <dependency>
  145.85 +                    <code-name-base>org.netbeans.modules.lexer</code-name-base>
  145.86 +                    <build-prerequisite/>
  145.87 +                    <compile-dependency/>
  145.88 +                    <run-dependency>
  145.89 +                        <release-version>2</release-version>
  145.90 +                        <specification-version>1.62</specification-version>
  145.91 +                    </run-dependency>
  145.92 +                </dependency>
  145.93 +                <dependency>
  145.94 +                    <code-name-base>org.netbeans.modules.options.editor</code-name-base>
  145.95 +                    <build-prerequisite/>
  145.96 +                    <compile-dependency/>
  145.97 +                    <run-dependency>
  145.98 +                        <release-version>1</release-version>
  145.99 +                        <specification-version>1.55</specification-version>
 145.100 +                    </run-dependency>
 145.101 +                </dependency>
 145.102 +                <dependency>
 145.103 +                    <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
 145.104 +                    <build-prerequisite/>
 145.105 +                    <compile-dependency/>
 145.106 +                    <run-dependency>
 145.107 +                        <release-version>1</release-version>
 145.108 +                        <specification-version>9.5</specification-version>
 145.109 +                    </run-dependency>
 145.110 +                </dependency>
 145.111 +                <dependency>
 145.112 +                    <code-name-base>org.netbeans.modules.parsing.indexing</code-name-base>
 145.113 +                    <build-prerequisite/>
 145.114 +                    <compile-dependency/>
 145.115 +                    <run-dependency>
 145.116 +                        <specification-version>9.7</specification-version>
 145.117 +                    </run-dependency>
 145.118 +                </dependency>
 145.119 +                <dependency>
 145.120                      <code-name-base>org.netbeans.modules.projectapi</code-name-base>
 145.121                      <build-prerequisite/>
 145.122                      <compile-dependency/>
 145.123 @@ -25,6 +131,31 @@
 145.124                      </run-dependency>
 145.125                  </dependency>
 145.126                  <dependency>
 145.127 +                    <code-name-base>org.netbeans.modules.python.core</code-name-base>
 145.128 +                    <build-prerequisite/>
 145.129 +                    <compile-dependency/>
 145.130 +                    <run-dependency>
 145.131 +                        <specification-version>1.4</specification-version>
 145.132 +                    </run-dependency>
 145.133 +                </dependency>
 145.134 +                <dependency>
 145.135 +                    <code-name-base>org.netbeans.modules.queries</code-name-base>
 145.136 +                    <build-prerequisite/>
 145.137 +                    <compile-dependency/>
 145.138 +                    <run-dependency>
 145.139 +                        <release-version>1</release-version>
 145.140 +                        <specification-version>1.42</specification-version>
 145.141 +                    </run-dependency>
 145.142 +                </dependency>
 145.143 +                <dependency>
 145.144 +                    <code-name-base>org.openide.awt</code-name-base>
 145.145 +                    <build-prerequisite/>
 145.146 +                    <compile-dependency/>
 145.147 +                    <run-dependency>
 145.148 +                        <specification-version>7.65</specification-version>
 145.149 +                    </run-dependency>
 145.150 +                </dependency>
 145.151 +                <dependency>
 145.152                      <code-name-base>org.openide.filesystems</code-name-base>
 145.153                      <build-prerequisite/>
 145.154                      <compile-dependency/>
 145.155 @@ -49,6 +180,38 @@
 145.156                      </run-dependency>
 145.157                  </dependency>
 145.158                  <dependency>
 145.159 +                    <code-name-base>org.openide.loaders</code-name-base>
 145.160 +                    <build-prerequisite/>
 145.161 +                    <compile-dependency/>
 145.162 +                    <run-dependency>
 145.163 +                        <specification-version>7.63</specification-version>
 145.164 +                    </run-dependency>
 145.165 +                </dependency>
 145.166 +                <dependency>
 145.167 +                    <code-name-base>org.openide.modules</code-name-base>
 145.168 +                    <build-prerequisite/>
 145.169 +                    <compile-dependency/>
 145.170 +                    <run-dependency>
 145.171 +                        <specification-version>7.47</specification-version>
 145.172 +                    </run-dependency>
 145.173 +                </dependency>
 145.174 +                <dependency>
 145.175 +                    <code-name-base>org.openide.nodes</code-name-base>
 145.176 +                    <build-prerequisite/>
 145.177 +                    <compile-dependency/>
 145.178 +                    <run-dependency>
 145.179 +                        <specification-version>7.42</specification-version>
 145.180 +                    </run-dependency>
 145.181 +                </dependency>
 145.182 +                <dependency>
 145.183 +                    <code-name-base>org.openide.text</code-name-base>
 145.184 +                    <build-prerequisite/>
 145.185 +                    <compile-dependency/>
 145.186 +                    <run-dependency>
 145.187 +                        <specification-version>6.66</specification-version>
 145.188 +                    </run-dependency>
 145.189 +                </dependency>
 145.190 +                <dependency>
 145.191                      <code-name-base>org.openide.util</code-name-base>
 145.192                      <build-prerequisite/>
 145.193                      <compile-dependency/>
 145.194 @@ -72,9 +235,21 @@
 145.195                          <specification-version>9.3</specification-version>
 145.196                      </run-dependency>
 145.197                  </dependency>
 145.198 +                <dependency>
 145.199 +                    <code-name-base>org.openide.windows</code-name-base>
 145.200 +                    <build-prerequisite/>
 145.201 +                    <compile-dependency/>
 145.202 +                    <run-dependency>
 145.203 +                        <specification-version>6.74</specification-version>
 145.204 +                    </run-dependency>
 145.205 +                </dependency>
 145.206              </module-dependencies>
 145.207              <public-packages>
 145.208 +                <package>org.netbeans.modules.python.source</package>
 145.209 +                <package>org.netbeans.modules.python.source.elements</package>
 145.210 +                <package>org.netbeans.modules.python.source.lexer</package>
 145.211                  <package>org.netbeans.modules.python.source.queries</package>
 145.212 +                <package>org.netbeans.modules.python.source.scopes</package>
 145.213              </public-packages>
 145.214          </data>
 145.215      </configuration>
   146.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   146.2 +++ b/python.source/src/org/netbeans/modules/python/source/AstPath.java	Mon Sep 21 13:01:16 2015 +0200
   146.3 @@ -0,0 +1,436 @@
   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 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  146.33 + */
  146.34 +package org.netbeans.modules.python.source;
  146.35 +
  146.36 +import java.util.ArrayList;
  146.37 +import java.util.Iterator;
  146.38 +import java.util.ListIterator;
  146.39 +import org.openide.util.Exceptions;
  146.40 +import org.python.antlr.PythonTree;
  146.41 +import org.python.antlr.Visitor;
  146.42 +
  146.43 +/**
  146.44 + * AstPath represents a path from a root node to a particular node in the AST.
  146.45 + * This is necessary because the parent node pointers in the nodes aren't always
  146.46 + * non null, so we can't just pass a node as a reference to a traversable path
  146.47 + * from the root to a node.
  146.48 + *
  146.49 + * @author Tor Norbye
  146.50 + */
  146.51 +public class AstPath implements Iterable<PythonTree> {
  146.52 +    private ArrayList<PythonTree> path = new ArrayList<>(30);
  146.53 +
  146.54 +    public AstPath() {
  146.55 +    }
  146.56 +
  146.57 +    public AstPath(AstPath other) {
  146.58 +        path.addAll(other.path);
  146.59 +    }
  146.60 +
  146.61 +    public AstPath(ArrayList<PythonTree> path) {
  146.62 +        this.path = path;
  146.63 +    }
  146.64 +
  146.65 +//    /**
  146.66 +//     * Initialize a node path to the given caretOffset
  146.67 +//     */
  146.68 +//    public AstPath(PythonTree root, int caretOffset) {
  146.69 +//        findPathTo(root, caretOffset);
  146.70 +//    }
  146.71 +//
  146.72 +//    /**
  146.73 +//     * Find the path to the given node in the AST
  146.74 +//     */
  146.75 +//    @SuppressWarnings("unchecked")
  146.76 +//    public AstPath(PythonTree node, PythonTree target) {
  146.77 +//        if (!find(node, target)) {
  146.78 +//            path.clear();
  146.79 +//        } else {
  146.80 +//            // Reverse the list such that node is on top
  146.81 +//            // When I get time rewrite the find method to build the list that way in the first place
  146.82 +//            Collections.reverse(path);
  146.83 +//        }
  146.84 +//    }
  146.85 +    public void descend(PythonTree node) {
  146.86 +        path.add(node);
  146.87 +    }
  146.88 +
  146.89 +    public void ascend() {
  146.90 +        path.remove(path.size() - 1);
  146.91 +    }
  146.92 +
  146.93 +    /**
  146.94 +     * Return the closest ancestor of the leaf that is of the given type
  146.95 +     */
  146.96 +    public PythonTree getTypedAncestor(Class clz) {
  146.97 +        return getTypedAncestor(clz, null);
  146.98 +    }
  146.99 +
 146.100 +    /**
 146.101 +     * Return the closest ancestor of the given node that is of the given type
 146.102 +     */
 146.103 +    public PythonTree getTypedAncestor(Class clz, PythonTree from) {
 146.104 +        int i = path.size() - 1;
 146.105 +
 146.106 +        // First find the given starting point
 146.107 +        if (from != null) {
 146.108 +            for (; i >= 0; i--) {
 146.109 +                PythonTree node = path.get(i);
 146.110 +
 146.111 +                if (node == from) {
 146.112 +                    break;
 146.113 +                }
 146.114 +            }
 146.115 +        }
 146.116 +
 146.117 +        for (; i >= 0; i--) {
 146.118 +            PythonTree node = path.get(i);
 146.119 +
 146.120 +            if (clz.isInstance(node)) {
 146.121 +                return node;
 146.122 +            }
 146.123 +        }
 146.124 +
 146.125 +        return null; // not found
 146.126 +    }
 146.127 +
 146.128 +    /**
 146.129 +     * Return true iff this path contains a node of the given node type
 146.130 +     *
 146.131 +     * @param nodeType The nodeType to check
 146.132 +     * @return true if the given nodeType is found in the path
 146.133 +     */
 146.134 +    public boolean contains(Class clz) {
 146.135 +        return getTypedAncestor(clz) != null;
 146.136 +    }
 146.137 +
 146.138 +//    /**
 146.139 +//     * Find the position closest to the given offset in the AST. Place the path from the leaf up to the path in the
 146.140 +//     * passed in path list.
 146.141 +//     */
 146.142 +//    @SuppressWarnings("unchecked")
 146.143 +//    public PythonTree findPathTo(PythonTree node, int offset) {
 146.144 +//        PythonTree result = find(node, offset);
 146.145 +//        path.add(node);
 146.146 +//
 146.147 +//        // Reverse the list such that node is on top
 146.148 +//        // When I get time rewrite the find method to build the list that way in the first place
 146.149 +//        Collections.reverse(path);
 146.150 +//
 146.151 +//        return result;
 146.152 +//    }
 146.153 +//
 146.154 +//    @SuppressWarnings("unchecked")
 146.155 +//    private PythonTree find(PythonTree node, int offset) {
 146.156 +//        int begin = node.getSourceStart();
 146.157 +//        int end = node.getSourceEnd();
 146.158 +//
 146.159 +//        if ((offset >= begin) && (offset <= end)) {
 146.160 +//            for (PythonTree child = node.getFirstChild(); child != null; child = child.getNext()) {
 146.161 +//                PythonTree found = find(child, offset);
 146.162 +//
 146.163 +//                if (found != null) {
 146.164 +//                    path.add(child);
 146.165 +//
 146.166 +//                    return found;
 146.167 +//                }
 146.168 +//            }
 146.169 +//
 146.170 +//            return node;
 146.171 +//        } else {
 146.172 +//        for (PythonTree child = node.getFirstChild(); child != null; child = child.getNext()) {
 146.173 +//                PythonTree found = find(child, offset);
 146.174 +//
 146.175 +//                if (found != null) {
 146.176 +//                    path.add(child);
 146.177 +//
 146.178 +//                    return found;
 146.179 +//                }
 146.180 +//            }
 146.181 +//
 146.182 +//            return null;
 146.183 +//        }
 146.184 +//    }
 146.185 +//
 146.186 +//    /**
 146.187 +//     * Find the path to the given node in the AST
 146.188 +//     */
 146.189 +//    @SuppressWarnings("unchecked")
 146.190 +//    public boolean find(PythonTree node, PythonTree target) {
 146.191 +//        if (node == target) {
 146.192 +//            return true;
 146.193 +//        }
 146.194 +//
 146.195 +//        for (PythonTree child = node.getFirstChild(); child != null; child = child.getNext()) {
 146.196 +//            boolean found = find(child, target);
 146.197 +//
 146.198 +//            if (found) {
 146.199 +//                path.add(child);
 146.200 +//
 146.201 +//                return found;
 146.202 +//            }
 146.203 +//        }
 146.204 +//
 146.205 +//        return false;
 146.206 +//    }
 146.207 +    @Override
 146.208 +    public String toString() {
 146.209 +        StringBuilder sb = new StringBuilder();
 146.210 +        sb.append("Path(");
 146.211 +        sb.append(path.size());
 146.212 +        sb.append(")=[");
 146.213 +
 146.214 +        for (PythonTree n : path) {
 146.215 +            String name = n.toString();
 146.216 +            name = name.substring(name.lastIndexOf('.') + 1);
 146.217 +            sb.append(name);
 146.218 +            sb.append(":");
 146.219 +        }
 146.220 +
 146.221 +        sb.append("]");
 146.222 +
 146.223 +        return sb.toString();
 146.224 +    }
 146.225 +
 146.226 +    public PythonTree leaf() {
 146.227 +        if (path.size() == 0) {
 146.228 +            return null;
 146.229 +        } else {
 146.230 +            return path.get(path.size() - 1);
 146.231 +        }
 146.232 +    }
 146.233 +
 146.234 +    public PythonTree leafParent() {
 146.235 +        if (path.size() < 2) {
 146.236 +            return null;
 146.237 +        } else {
 146.238 +            return path.get(path.size() - 2);
 146.239 +        }
 146.240 +    }
 146.241 +
 146.242 +    public PythonTree leafGrandParent() {
 146.243 +        if (path.size() < 3) {
 146.244 +            return null;
 146.245 +        } else {
 146.246 +            return path.get(path.size() - 3);
 146.247 +        }
 146.248 +    }
 146.249 +
 146.250 +    /**
 146.251 +     * Return the top/module level node -- this is not the module node
 146.252 +     * itself but the first node below it.
 146.253 +     */
 146.254 +    public PythonTree topModuleLevel() {
 146.255 +        if (path.size() >= 2) {
 146.256 +            return path.get(1);
 146.257 +        } else {
 146.258 +            return null;
 146.259 +        }
 146.260 +    }
 146.261 +
 146.262 +    public PythonTree root() {
 146.263 +        if (path.size() == 0) {
 146.264 +            return null;
 146.265 +        } else {
 146.266 +            return path.get(0);
 146.267 +        }
 146.268 +    }
 146.269 +
 146.270 +    /** Return an iterator that returns the elements from the leaf back up to the root */
 146.271 +    @Override
 146.272 +    public Iterator<PythonTree> iterator() {
 146.273 +        return new LeafToRootIterator(path);
 146.274 +    }
 146.275 +
 146.276 +    /** REturn an iterator that starts at the root and walks down to the leaf */
 146.277 +    public ListIterator<PythonTree> rootToLeaf() {
 146.278 +        return path.listIterator();
 146.279 +    }
 146.280 +
 146.281 +    /** Return an iterator that walks from the leaf back up to the root */
 146.282 +    public ListIterator<PythonTree> leafToRoot() {
 146.283 +        return new LeafToRootIterator(path);
 146.284 +    }
 146.285 +
 146.286 +    private static class LeafToRootIterator implements ListIterator<PythonTree> {
 146.287 +        private final ListIterator<PythonTree> it;
 146.288 +
 146.289 +        private LeafToRootIterator(ArrayList<PythonTree> path) {
 146.290 +            it = path.listIterator(path.size());
 146.291 +        }
 146.292 +
 146.293 +        @Override
 146.294 +        public boolean hasNext() {
 146.295 +            return it.hasPrevious();
 146.296 +        }
 146.297 +
 146.298 +        @Override
 146.299 +        public PythonTree next() {
 146.300 +            return it.previous();
 146.301 +        }
 146.302 +
 146.303 +        @Override
 146.304 +        public boolean hasPrevious() {
 146.305 +            return it.hasNext();
 146.306 +        }
 146.307 +
 146.308 +        @Override
 146.309 +        public PythonTree previous() {
 146.310 +            return it.next();
 146.311 +        }
 146.312 +
 146.313 +        @Override
 146.314 +        public int nextIndex() {
 146.315 +            return it.previousIndex();
 146.316 +        }
 146.317 +
 146.318 +        @Override
 146.319 +        public int previousIndex() {
 146.320 +            return it.nextIndex();
 146.321 +        }
 146.322 +
 146.323 +        @Override
 146.324 +        public void remove() {
 146.325 +            throw new UnsupportedOperationException("Not supported yet.");
 146.326 +        }
 146.327 +
 146.328 +        @Override
 146.329 +        public void set(PythonTree arg0) {
 146.330 +            throw new UnsupportedOperationException("Not supported yet.");
 146.331 +        }
 146.332 +
 146.333 +        @Override
 146.334 +        public void add(PythonTree arg0) {
 146.335 +            throw new UnsupportedOperationException("Not supported yet.");
 146.336 +        }
 146.337 +    }
 146.338 +
 146.339 +    private static class FindByOffsetVisitor extends Visitor {
 146.340 +        private int targetOffset;
 146.341 +        private ArrayList<PythonTree> path = new ArrayList<>();
 146.342 +
 146.343 +        private FindByOffsetVisitor(int targetOffset) {
 146.344 +            this.targetOffset = targetOffset;
 146.345 +        }
 146.346 +
 146.347 +        @Override
 146.348 +        public void traverse(PythonTree node) throws Exception {
 146.349 +            if (targetOffset >= node.getCharStartIndex() && targetOffset <= node.getCharStopIndex()) {
 146.350 +//                if (targetOffset == node.getCharStopIndex() && node.getClass() == FunctionDef.class) {
 146.351 +//                    // For functions, don't include the last offset, since we can end up with
 146.352 +//                    // functions that overlap - caret at the start position will add BOTH functions
 146.353 +//                    // which we don't want
 146.354 +//                } else {
 146.355 +                path.add(node);
 146.356 +//                }
 146.357 +                super.traverse(node);
 146.358 +            }
 146.359 +        }
 146.360 +
 146.361 +        AstPath getPath() {
 146.362 +            return new AstPath(path);
 146.363 +        }
 146.364 +    }
 146.365 +
 146.366 +    public static AstPath get(PythonTree root, int offset) {
 146.367 +        FindByOffsetVisitor finder = new FindByOffsetVisitor(offset);
 146.368 +        try {
 146.369 +            finder.visit(root);
 146.370 +            AstPath path = finder.getPath();
 146.371 +            if (path.path.size() == 0) {
 146.372 +                path.path.add(root);
 146.373 +            }
 146.374 +
 146.375 +            return path;
 146.376 +        } catch (Exception ex) {
 146.377 +            Exceptions.printStackTrace(ex);
 146.378 +        }
 146.379 +
 146.380 +        return null;
 146.381 +    }
 146.382 +
 146.383 +    private static class FindByNodeVisitor extends Visitor {
 146.384 +        private PythonTree target;
 146.385 +        private int startOffset;
 146.386 +        private int endOffset;
 146.387 +        private ArrayList<PythonTree> path = new ArrayList<>();
 146.388 +        private boolean found;
 146.389 +
 146.390 +        private FindByNodeVisitor(PythonTree target) {
 146.391 +            this.target = target;
 146.392 +            this.startOffset = target.getCharStartIndex();
 146.393 +            this.endOffset = target.getCharStopIndex();
 146.394 +        }
 146.395 +
 146.396 +        @Override
 146.397 +        public void traverse(PythonTree node) throws Exception {
 146.398 +            if (found) {
 146.399 +                return;
 146.400 +            }
 146.401 +            if (node == target) {
 146.402 +                path.add(node);
 146.403 +                found = true;
 146.404 +                return;
 146.405 +            }
 146.406 +            if (startOffset >= node.getCharStartIndex() && endOffset <= node.getCharStopIndex()) {
 146.407 +                path.add(node);
 146.408 +                node.traverse(this);
 146.409 +                if (found) {
 146.410 +                    return;
 146.411 +                }
 146.412 +                path.remove(path.size() - 1);
 146.413 +            }
 146.414 +        }
 146.415 +
 146.416 +        AstPath getPath() {
 146.417 +            return new AstPath(path);
 146.418 +        }
 146.419 +    }
 146.420 +
 146.421 +    /**
 146.422 +     * Find the path to the given node in the AST
 146.423 +     */
 146.424 +    public static AstPath get(PythonTree root, PythonTree target) {
 146.425 +        FindByNodeVisitor finder = new FindByNodeVisitor(target);
 146.426 +        try {
 146.427 +            finder.visit(root);
 146.428 +            AstPath path = finder.getPath();
 146.429 +            if (path.path.size() == 0) {
 146.430 +                path.path.add(root);
 146.431 +            }
 146.432 +
 146.433 +            return path;
 146.434 +        } catch (Exception ex) {
 146.435 +            Exceptions.printStackTrace(ex);
 146.436 +            return null;
 146.437 +        }
 146.438 +    }
 146.439 +}
   147.1 --- a/python.source/src/org/netbeans/modules/python/source/Bundle.properties	Fri Sep 18 16:20:24 2015 -0500
   147.2 +++ b/python.source/src/org/netbeans/modules/python/source/Bundle.properties	Mon Sep 21 13:01:16 2015 +0200
   147.3 @@ -1,1 +1,3 @@
   147.4  OpenIDE-Module-Name=Python Source
   147.5 +
   147.6 +NoPreference=No Preference
   148.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   148.2 +++ b/python.source/src/org/netbeans/modules/python/source/CodeStyle.java	Mon Sep 21 13:01:16 2015 +0200
   148.3 @@ -0,0 +1,738 @@
   148.4 +/*
   148.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   148.6 + *
   148.7 + * Copyright 1997-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 + * Contributor(s):
  148.31 + *
  148.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  148.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  148.34 + * Microsystems, Inc. All Rights Reserved.
  148.35 + *
  148.36 + * If you wish your version of this file to be governed by only the CDDL
  148.37 + * or only the GPL Version 2, indicate your decision by adding
  148.38 + * "[Contributor] elects to include this software in this distribution
  148.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  148.40 + * single choice of license, a recipient has the option to distribute
  148.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  148.42 + * to extend the choice of license to its licensees as provided above.
  148.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  148.44 + * Version 2 license, then the option applies only if the new code is
  148.45 + * made subject to such option by the copyright holder.
  148.46 + */
  148.47 +package org.netbeans.modules.python.source;
  148.48 +
  148.49 +import java.util.prefs.Preferences;
  148.50 +import javax.swing.text.Document;
  148.51 +import org.netbeans.modules.editor.indent.spi.CodeStylePreferences;
  148.52 +import org.netbeans.modules.python.source.ui.FmtOptions;
  148.53 +
  148.54 +import org.openide.filesystems.FileObject;
  148.55 +import static org.netbeans.modules.python.source.ui.FmtOptions.*;
  148.56 +
  148.57 +/** 
  148.58 + *  XXX make sure the getters get the defaults from somewhere
  148.59 + *  XXX add support for profiles
  148.60 + *  XXX get the preferences node from somewhere else in odrer to be able not to
  148.61 + *      use the getters and to be able to write to it.
  148.62 + * 
  148.63 + * @author Dusan Balek
  148.64 + */
  148.65 +public final class CodeStyle {
  148.66 +    static {
  148.67 +        FmtOptions.codeStyleProducer = new Producer();
  148.68 +    }
  148.69 +    private Preferences preferences;
  148.70 +
  148.71 +    private CodeStyle(Preferences preferences) {
  148.72 +        this.preferences = preferences;
  148.73 +    }
  148.74 +
  148.75 +//    /**
  148.76 +//     * Gets <code>CodeStyle</code> for files in the given project.
  148.77 +//     *
  148.78 +//     * <p>Please see the other two <code>getDefault</code> methods as they are
  148.79 +//     * the preferred way of getting <code>CodeStyle</code>.
  148.80 +//     *
  148.81 +//     * @param project The project to get the <code>CodeStyle</code> for.
  148.82 +//     * @return The current code style that would be used by documents opened
  148.83 +//     *   from files belonging to the <code>project</code>.
  148.84 +//     *
  148.85 +//     * @deprecated Please use {@link #getDefault(javax.swing.text.Document)}
  148.86 +//     *   or {@link #getDefault(org.openide.filesystems.FileObject)} respectively.
  148.87 +//     */
  148.88 +//    @Deprecated
  148.89 +//    public static CodeStyle getDefault(Project project) {
  148.90 +//        return getDefault(project.getProjectDirectory());
  148.91 +//    }
  148.92 +    /**
  148.93 +     * Gets <code>CodeStyle</code> for the given file. If you have a document
  148.94 +     * instance you should use the {@link #getDefault(javax.swing.text.Document)}
  148.95 +     * method.
  148.96 +     * 
  148.97 +     * @param file The file to get the <code>CodeStyle</code> for.
  148.98 +     * @return The current code style that would be used by a document if the
  148.99 +     *   <code>file</code> were opened in the editor.
 148.100 +     *
 148.101 +     * @since 0.39
 148.102 +     */
 148.103 +    public synchronized static CodeStyle getDefault(FileObject file) {
 148.104 +        Preferences prefs = CodeStylePreferences.get(file).getPreferences();
 148.105 +        return FmtOptions.codeStyleProducer.create(prefs);
 148.106 +    }
 148.107 +
 148.108 +    /**
 148.109 +     * Gets <code>CodeStyle</code> for the given document. This is the preferred
 148.110 +     * method of getting <code>CodeStyle</code>. If you don't have a document
 148.111 +     * you can use {@link #getDefault(org.openide.filesystems.FileObject)} method instead.
 148.112 +     *
 148.113 +     * @param doc The document to get the <code>CodeStyle</code> for.
 148.114 +     * @return The current code style used by a document. This is the code style that
 148.115 +     *   will be used when formatting the document or generating new code.
 148.116 +     * 
 148.117 +     * @since 0.39
 148.118 +     */
 148.119 +    public synchronized static CodeStyle getDefault(Document doc) {
 148.120 +        Preferences prefs = CodeStylePreferences.get(doc).getPreferences();
 148.121 +        return FmtOptions.codeStyleProducer.create(prefs);
 148.122 +    }
 148.123 +
 148.124 +    // General tabs and indents ------------------------------------------------
 148.125 +    public boolean expandTabToSpaces() {
 148.126 +//        System.out.println("~~~ expand-tabs=" + preferences.get(SimpleValueNames.EXPAND_TABS, null));
 148.127 +        return preferences.getBoolean(expandTabToSpaces, getDefaultAsBoolean(expandTabToSpaces));
 148.128 +    }
 148.129 +
 148.130 +    public int getTabSize() {
 148.131 +//        System.out.println("~~~ tab-size=" + preferences.get(SimpleValueNames.TAB_SIZE, null));
 148.132 +        return preferences.getInt(tabSize, getDefaultAsInt(tabSize));
 148.133 +    }
 148.134 +
 148.135 +    public int getIndentSize() {
 148.136 +//        System.out.println("~~~ indent-shift-width=" + preferences.get(SimpleValueNames.INDENT_SHIFT_WIDTH, null));
 148.137 +        int indentLevel = preferences.getInt(indentSize, getDefaultAsInt(indentSize));
 148.138 +
 148.139 +        if (indentLevel <= 0) {
 148.140 +//            System.out.println("~~~ expand-tabs=" + preferences.get(SimpleValueNames.EXPAND_TABS, null));
 148.141 +            boolean expandTabs = preferences.getBoolean(expandTabToSpaces, getDefaultAsBoolean(expandTabToSpaces));
 148.142 +            if (expandTabs) {
 148.143 +//                System.out.println("~~~ spaces-per-tab=" + preferences.get(SimpleValueNames.SPACES_PER_TAB, null));
 148.144 +                indentLevel = preferences.getInt(spacesPerTab, getDefaultAsInt(spacesPerTab));
 148.145 +            } else {
 148.146 +//                System.out.println("~~~ tab-size=" + preferences.get(SimpleValueNames.TAB_SIZE, null));
 148.147 +                indentLevel = preferences.getInt(tabSize, getDefaultAsInt(tabSize));
 148.148 +            }
 148.149 +        }
 148.150 +
 148.151 +        return indentLevel;
 148.152 +    }
 148.153 +
 148.154 +    public int getContinuationIndentSize() {
 148.155 +        return preferences.getInt(continuationIndentSize, getDefaultAsInt(continuationIndentSize));
 148.156 +    }
 148.157 +
 148.158 +    public int getLabelIndent() {
 148.159 +        return preferences.getInt(labelIndent, getDefaultAsInt(labelIndent));
 148.160 +    }
 148.161 +
 148.162 +    public boolean absoluteLabelIndent() {
 148.163 +        return preferences.getBoolean(absoluteLabelIndent, getDefaultAsBoolean(absoluteLabelIndent));
 148.164 +    }
 148.165 +
 148.166 +    public boolean indentTopLevelClassMembers() {
 148.167 +        return preferences.getBoolean(indentTopLevelClassMembers, getDefaultAsBoolean(indentTopLevelClassMembers));
 148.168 +    }
 148.169 +
 148.170 +    public boolean indentCasesFromSwitch() {
 148.171 +        return preferences.getBoolean(indentCasesFromSwitch, getDefaultAsBoolean(indentCasesFromSwitch));
 148.172 +    }
 148.173 +
 148.174 +    public int getRightMargin() {
 148.175 +        return preferences.getInt(rightMargin, getDefaultAsInt(rightMargin));
 148.176 +    }
 148.177 +
 148.178 +    /*
 148.179 +    public boolean addLeadingStarInComment() {
 148.180 +    return preferences.getBoolean(addLeadingStarInComment, getDefaultAsBoolean(addLeadingStarInComment));
 148.181 +    }
 148.182 +
 148.183 +    // Code generation ---------------------------------------------------------
 148.184 +    
 148.185 +    public boolean preferLongerNames() {
 148.186 +    return preferences.getBoolean(preferLongerNames, getDefaultAsBoolean(preferLongerNames));
 148.187 +    }
 148.188 +
 148.189 +    public String getFieldNamePrefix() {
 148.190 +    return preferences.get(fieldNamePrefix, getDefaultAsString(fieldNamePrefix));
 148.191 +    }
 148.192 +
 148.193 +    public String getFieldNameSuffix() {
 148.194 +    return preferences.get(fieldNameSuffix, getDefaultAsString(fieldNameSuffix));
 148.195 +    }
 148.196 +
 148.197 +    public String getStaticFieldNamePrefix() {
 148.198 +    return preferences.get(staticFieldNamePrefix, getDefaultAsString(staticFieldNamePrefix));
 148.199 +    }
 148.200 +
 148.201 +    public String getStaticFieldNameSuffix() {
 148.202 +    return preferences.get(staticFieldNameSuffix, getDefaultAsString(staticFieldNameSuffix));
 148.203 +    }
 148.204 +
 148.205 +    public String getParameterNamePrefix() {
 148.206 +    return preferences.get(parameterNamePrefix, getDefaultAsString(parameterNamePrefix));
 148.207 +    }
 148.208 +
 148.209 +    public String getParameterNameSuffix() {
 148.210 +    return preferences.get(parameterNameSuffix, getDefaultAsString(parameterNameSuffix));
 148.211 +    }
 148.212 +
 148.213 +    public String getLocalVarNamePrefix() {
 148.214 +    return preferences.get(localVarNamePrefix, getDefaultAsString(localVarNamePrefix));
 148.215 +    }
 148.216 +
 148.217 +    public String getLocalVarNameSuffix() {
 148.218 +    return preferences.get(localVarNameSuffix, getDefaultAsString(localVarNameSuffix));
 148.219 +    }
 148.220 +
 148.221 +    public boolean qualifyFieldAccess() {
 148.222 +    return preferences.getBoolean(qualifyFieldAccess, getDefaultAsBoolean(qualifyFieldAccess));
 148.223 +    }
 148.224 +
 148.225 +    public boolean useIsForBooleanGetters() {
 148.226 +    return preferences.getBoolean(useIsForBooleanGetters, getDefaultAsBoolean(useIsForBooleanGetters));
 148.227 +    }
 148.228 +
 148.229 +    public boolean addOverrideAnnotation() {
 148.230 +    return preferences.getBoolean(addOverrideAnnotation, getDefaultAsBoolean(addOverrideAnnotation));
 148.231 +    }
 148.232 +
 148.233 +    public boolean makeLocalVarsFinal() {
 148.234 +    return preferences.getBoolean(makeLocalVarsFinal, getDefaultAsBoolean(makeLocalVarsFinal));
 148.235 +    }
 148.236 +
 148.237 +    // Alignment ----------------------------------------------------
 148.238 +    
 148.239 +    public boolean alignMultilineMethodParams() {
 148.240 +    return preferences.getBoolean(alignMultilineMethodParams, getDefaultAsBoolean(alignMultilineMethodParams));
 148.241 +    }
 148.242 +
 148.243 +    public boolean alignMultilineCallArgs() {
 148.244 +    return preferences.getBoolean(alignMultilineCallArgs, getDefaultAsBoolean(alignMultilineCallArgs));
 148.245 +    }
 148.246 +
 148.247 +    public boolean alignMultilineAnnotationArgs() {
 148.248 +    return preferences.getBoolean(alignMultilineAnnotationArgs, getDefaultAsBoolean(alignMultilineAnnotationArgs));
 148.249 +    }
 148.250 +
 148.251 +    public boolean alignMultilineImplements() {
 148.252 +    return preferences.getBoolean(alignMultilineImplements, getDefaultAsBoolean(alignMultilineImplements));
 148.253 +    }
 148.254 +
 148.255 +    public boolean alignMultilineThrows() {
 148.256 +    return preferences.getBoolean(alignMultilineThrows, getDefaultAsBoolean(alignMultilineThrows));
 148.257 +    }
 148.258 +
 148.259 +    public boolean alignMultilineParenthesized() {
 148.260 +    return preferences.getBoolean(alignMultilineParenthesized, getDefaultAsBoolean(alignMultilineParenthesized));
 148.261 +    }
 148.262 +
 148.263 +    public boolean alignMultilineBinaryOp() {
 148.264 +    return preferences.getBoolean(alignMultilineBinaryOp, getDefaultAsBoolean(alignMultilineBinaryOp));
 148.265 +    }
 148.266 +
 148.267 +    public boolean alignMultilineTernaryOp() {
 148.268 +    return preferences.getBoolean(alignMultilineTernaryOp, getDefaultAsBoolean(alignMultilineTernaryOp));
 148.269 +    }
 148.270 +
 148.271 +    public boolean alignMultilineAssignment() {
 148.272 +    return preferences.getBoolean(alignMultilineAssignment, getDefaultAsBoolean(alignMultilineAssignment));
 148.273 +    }
 148.274 +
 148.275 +    public boolean alignMultilineFor() {
 148.276 +    return preferences.getBoolean(alignMultilineFor, getDefaultAsBoolean(alignMultilineFor));
 148.277 +    }
 148.278 +
 148.279 +    public boolean alignMultilineArrayInit() {
 148.280 +    return preferences.getBoolean(alignMultilineArrayInit, getDefaultAsBoolean(alignMultilineArrayInit));
 148.281 +    }
 148.282 +
 148.283 +    public boolean placeElseOnNewLine() {
 148.284 +    return preferences.getBoolean(placeElseOnNewLine, getDefaultAsBoolean(placeElseOnNewLine));
 148.285 +    }
 148.286 +
 148.287 +    public boolean placeWhileOnNewLine() {
 148.288 +    return preferences.getBoolean(placeWhileOnNewLine, getDefaultAsBoolean(placeWhileOnNewLine));
 148.289 +    }
 148.290 +
 148.291 +    public boolean placeCatchOnNewLine() {
 148.292 +    return preferences.getBoolean(placeCatchOnNewLine, getDefaultAsBoolean(placeCatchOnNewLine));
 148.293 +    }
 148.294 +
 148.295 +    public boolean placeFinallyOnNewLine() {
 148.296 +    return preferences.getBoolean(placeFinallyOnNewLine, getDefaultAsBoolean(placeFinallyOnNewLine));
 148.297 +    }
 148.298 +    
 148.299 +    public boolean placeNewLineAfterModifiers() {
 148.300 +    return preferences.getBoolean(placeNewLineAfterModifiers, getDefaultAsBoolean(placeNewLineAfterModifiers));
 148.301 +    }
 148.302 +
 148.303 +    // Wrapping ----------------------------------------------------------------
 148.304 +    
 148.305 +    public WrapStyle wrapExtendsImplementsKeyword() {
 148.306 +    String wrap = preferences.get(wrapExtendsImplementsKeyword, getDefaultAsString(wrapExtendsImplementsKeyword));
 148.307 +    return WrapStyle.valueOf(wrap);
 148.308 +    }
 148.309 +
 148.310 +    public WrapStyle wrapExtendsImplementsList() {
 148.311 +    String wrap = preferences.get(wrapExtendsImplementsList, getDefaultAsString(wrapExtendsImplementsList));
 148.312 +    return WrapStyle.valueOf(wrap);
 148.313 +    }
 148.314 +
 148.315 +    public WrapStyle wrapMethodParams() {
 148.316 +    String wrap = preferences.get(wrapMethodParams, getDefaultAsString(wrapMethodParams));
 148.317 +    return WrapStyle.valueOf(wrap);
 148.318 +    }
 148.319 +
 148.320 +    public WrapStyle wrapThrowsKeyword() {
 148.321 +    String wrap = preferences.get(wrapThrowsKeyword, getDefaultAsString(wrapThrowsKeyword));
 148.322 +    return WrapStyle.valueOf(wrap);
 148.323 +    }
 148.324 +
 148.325 +    public WrapStyle wrapThrowsList() {
 148.326 +    String wrap = preferences.get(wrapThrowsList, getDefaultAsString(wrapThrowsList));
 148.327 +    return WrapStyle.valueOf(wrap);
 148.328 +    }
 148.329 +
 148.330 +    public WrapStyle wrapMethodCallArgs() {
 148.331 +    String wrap = preferences.get(wrapMethodCallArgs, getDefaultAsString(wrapMethodCallArgs));
 148.332 +    return WrapStyle.valueOf(wrap);
 148.333 +    }
 148.334 +
 148.335 +    public WrapStyle wrapAnnotationArgs() {
 148.336 +    String wrap = preferences.get(wrapAnnotationArgs, getDefaultAsString(wrapAnnotationArgs));
 148.337 +    return WrapStyle.valueOf(wrap);
 148.338 +    }
 148.339 +
 148.340 +    public WrapStyle wrapChainedMethodCalls() {
 148.341 +    String wrap = preferences.get(wrapChainedMethodCalls, getDefaultAsString(wrapChainedMethodCalls));
 148.342 +    return WrapStyle.valueOf(wrap);
 148.343 +    }
 148.344 +
 148.345 +    public WrapStyle wrapArrayInit() {
 148.346 +    String wrap = preferences.get(wrapArrayInit, getDefaultAsString(wrapArrayInit));
 148.347 +    return WrapStyle.valueOf(wrap);
 148.348 +    }
 148.349 +
 148.350 +    public WrapStyle wrapFor() {
 148.351 +    String wrap = preferences.get(wrapFor, getDefaultAsString(wrapFor));
 148.352 +    return WrapStyle.valueOf(wrap);
 148.353 +    }
 148.354 +
 148.355 +    public WrapStyle wrapForStatement() {
 148.356 +    String wrap = preferences.get(wrapForStatement, getDefaultAsString(wrapForStatement));
 148.357 +    return WrapStyle.valueOf(wrap);
 148.358 +    }
 148.359 +
 148.360 +    public WrapStyle wrapIfStatement() {
 148.361 +    String wrap = preferences.get(wrapIfStatement, getDefaultAsString(wrapIfStatement));
 148.362 +    return WrapStyle.valueOf(wrap);
 148.363 +    }
 148.364 +
 148.365 +    public WrapStyle wrapWhileStatement() {
 148.366 +    String wrap = preferences.get(wrapWhileStatement, getDefaultAsString(wrapWhileStatement));
 148.367 +    return WrapStyle.valueOf(wrap);
 148.368 +    }
 148.369 +
 148.370 +    public WrapStyle wrapDoWhileStatement() {
 148.371 +    String wrap = preferences.get(wrapDoWhileStatement, getDefaultAsString(wrapDoWhileStatement));
 148.372 +    return WrapStyle.valueOf(wrap);
 148.373 +    }
 148.374 +
 148.375 +    public WrapStyle wrapAssert() {
 148.376 +    String wrap = preferences.get(wrapAssert, getDefaultAsString(wrapAssert));
 148.377 +    return WrapStyle.valueOf(wrap);
 148.378 +    }
 148.379 +
 148.380 +    public WrapStyle wrapEnumConstants() {
 148.381 +    String wrap = preferences.get(wrapEnumConstants, getDefaultAsString(wrapEnumConstants));
 148.382 +    return WrapStyle.valueOf(wrap);
 148.383 +    }
 148.384 +
 148.385 +    public WrapStyle wrapAnnotations() {
 148.386 +    String wrap = preferences.get(wrapAnnotations, getDefaultAsString(wrapAnnotations));
 148.387 +    return WrapStyle.valueOf(wrap);
 148.388 +    }
 148.389 +
 148.390 +    public WrapStyle wrapBinaryOps() {
 148.391 +    String wrap = preferences.get(wrapBinaryOps, getDefaultAsString(wrapBinaryOps));
 148.392 +    return WrapStyle.valueOf(wrap);
 148.393 +    }
 148.394 +
 148.395 +    public WrapStyle wrapTernaryOps() {
 148.396 +    String wrap = preferences.get(wrapTernaryOps, getDefaultAsString(wrapTernaryOps));
 148.397 +    return WrapStyle.valueOf(wrap);
 148.398 +    }
 148.399 +
 148.400 +    public WrapStyle wrapAssignOps() {
 148.401 +    String wrap = preferences.get(wrapAssignOps, getDefaultAsString(wrapAssignOps));
 148.402 +    return WrapStyle.valueOf(wrap);
 148.403 +    }
 148.404 +
 148.405 +    // Blank lines -------------------------------------------------------------
 148.406 +    
 148.407 +    public int getBlankLinesBeforePackage() {
 148.408 +    return preferences.getInt(blankLinesBeforePackage, getDefaultAsInt(blankLinesBeforePackage));
 148.409 +    }
 148.410 +
 148.411 +    public int getBlankLinesAfterPackage() {
 148.412 +    return preferences.getInt(blankLinesAfterPackage, getDefaultAsInt(blankLinesAfterPackage));
 148.413 +    }
 148.414 +
 148.415 +    public int getBlankLinesBeforeImports() {
 148.416 +    return preferences.getInt(blankLinesBeforeImports, getDefaultAsInt(blankLinesBeforeImports));
 148.417 +    }
 148.418 +
 148.419 +    public int getBlankLinesAfterImports() {
 148.420 +    return preferences.getInt(blankLinesAfterImports, getDefaultAsInt(blankLinesAfterImports));
 148.421 +    }
 148.422 +
 148.423 +    public int getBlankLinesBeforeClass() {
 148.424 +    return preferences.getInt(blankLinesBeforeClass, getDefaultAsInt(blankLinesBeforeClass));
 148.425 +    }
 148.426 +
 148.427 +    public int getBlankLinesAfterClass() {
 148.428 +    return preferences.getInt(blankLinesAfterClass, getDefaultAsInt(blankLinesAfterClass));
 148.429 +    }
 148.430 +
 148.431 +    public int getBlankLinesAfterClassHeader() {
 148.432 +    return preferences.getInt(blankLinesAfterClassHeader, getDefaultAsInt(blankLinesAfterClassHeader));
 148.433 +    }
 148.434 +
 148.435 +    public int getBlankLinesBeforeFields() {
 148.436 +    return preferences.getInt(blankLinesBeforeFields, getDefaultAsInt(blankLinesBeforeFields));
 148.437 +    }
 148.438 +
 148.439 +    public int getBlankLinesAfterFields() {
 148.440 +    return preferences.getInt(blankLinesAfterFields, getDefaultAsInt(blankLinesAfterFields));
 148.441 +    }
 148.442 +
 148.443 +    public int getBlankLinesBeforeMethods() {
 148.444 +    return preferences.getInt(blankLinesBeforeMethods, getDefaultAsInt(blankLinesBeforeMethods));
 148.445 +    }
 148.446 +
 148.447 +    public int getBlankLinesAfterMethods() {
 148.448 +    return preferences.getInt(blankLinesAfterMethods, getDefaultAsInt(blankLinesAfterMethods));
 148.449 +    }
 148.450 +
 148.451 +    // Spaces ------------------------------------------------------------------
 148.452 +    
 148.453 +    public boolean spaceBeforeWhile() {
 148.454 +    return preferences.getBoolean(spaceBeforeWhile, getDefaultAsBoolean(spaceBeforeWhile));
 148.455 +    }
 148.456 +
 148.457 +    public boolean spaceBeforeElse() {
 148.458 +    return preferences.getBoolean(spaceBeforeElse, getDefaultAsBoolean(spaceBeforeElse));
 148.459 +    }
 148.460 +
 148.461 +    public boolean spaceBeforeCatch() {
 148.462 +    return preferences.getBoolean(spaceBeforeCatch, getDefaultAsBoolean(spaceBeforeCatch));
 148.463 +    }
 148.464 +
 148.465 +    public boolean spaceBeforeFinally() {
 148.466 +    return preferences.getBoolean(spaceBeforeFinally, getDefaultAsBoolean(spaceBeforeFinally));
 148.467 +    }
 148.468 +
 148.469 +    public boolean spaceBeforeMethodDeclParen() {
 148.470 +    return preferences.getBoolean(spaceBeforeMethodDeclParen, getDefaultAsBoolean(spaceBeforeMethodDeclParen));
 148.471 +    }
 148.472 +
 148.473 +    public boolean spaceBeforeMethodCallParen() {
 148.474 +    return preferences.getBoolean(spaceBeforeMethodCallParen, getDefaultAsBoolean(spaceBeforeMethodCallParen));
 148.475 +    }
 148.476 +
 148.477 +    public boolean spaceBeforeIfParen() {
 148.478 +    return preferences.getBoolean(spaceBeforeIfParen, getDefaultAsBoolean(spaceBeforeIfParen));
 148.479 +    }
 148.480 +
 148.481 +    public boolean spaceBeforeForParen() {
 148.482 +    return preferences.getBoolean(spaceBeforeForParen, getDefaultAsBoolean(spaceBeforeForParen));
 148.483 +    }
 148.484 +
 148.485 +    public boolean spaceBeforeWhileParen() {
 148.486 +    return preferences.getBoolean(spaceBeforeWhileParen, getDefaultAsBoolean(spaceBeforeWhileParen));
 148.487 +    }
 148.488 +
 148.489 +    public boolean spaceBeforeCatchParen() {
 148.490 +    return preferences.getBoolean(spaceBeforeCatchParen, getDefaultAsBoolean(spaceBeforeCatchParen));
 148.491 +    }
 148.492 +
 148.493 +    public boolean spaceBeforeSwitchParen() {
 148.494 +    return preferences.getBoolean(spaceBeforeSwitchParen, getDefaultAsBoolean(spaceBeforeSwitchParen));
 148.495 +    }
 148.496 +
 148.497 +    public boolean spaceBeforeSynchronizedParen() {
 148.498 +    return preferences.getBoolean(spaceBeforeSynchronizedParen, getDefaultAsBoolean(spaceBeforeSynchronizedParen));
 148.499 +    }
 148.500 +
 148.501 +    public boolean spaceBeforeAnnotationParen() {
 148.502 +    return preferences.getBoolean(spaceBeforeAnnotationParen, getDefaultAsBoolean(spaceBeforeAnnotationParen));
 148.503 +    }
 148.504 +
 148.505 +    public boolean spaceAroundUnaryOps() {
 148.506 +    return preferences.getBoolean(spaceAroundUnaryOps, getDefaultAsBoolean(spaceAroundUnaryOps));
 148.507 +    }
 148.508 +
 148.509 +    public boolean spaceAroundBinaryOps() {
 148.510 +    return preferences.getBoolean(spaceAroundBinaryOps, getDefaultAsBoolean(spaceAroundBinaryOps));
 148.511 +    }
 148.512 +
 148.513 +    public boolean spaceAroundTernaryOps() {
 148.514 +    return preferences.getBoolean(spaceAroundTernaryOps, getDefaultAsBoolean(spaceAroundTernaryOps));
 148.515 +    }
 148.516 +
 148.517 +    public boolean spaceAroundAssignOps() {
 148.518 +    return preferences.getBoolean(spaceAroundAssignOps, getDefaultAsBoolean(spaceAroundAssignOps));
 148.519 +    }
 148.520 +
 148.521 +    public boolean spaceBeforeClassDeclLeftBrace() {
 148.522 +    return preferences.getBoolean(spaceBeforeClassDeclLeftBrace, getDefaultAsBoolean(spaceBeforeClassDeclLeftBrace));
 148.523 +    }
 148.524 +
 148.525 +    public boolean spaceBeforeMethodDeclLeftBrace() {
 148.526 +    return preferences.getBoolean(spaceBeforeMethodDeclLeftBrace, getDefaultAsBoolean(spaceBeforeMethodDeclLeftBrace));
 148.527 +    }
 148.528 +
 148.529 +    public boolean spaceBeforeIfLeftBrace() {
 148.530 +    return preferences.getBoolean(spaceBeforeIfLeftBrace, getDefaultAsBoolean(spaceBeforeIfLeftBrace));
 148.531 +    }
 148.532 +
 148.533 +    public boolean spaceBeforeElseLeftBrace() {
 148.534 +    return preferences.getBoolean(spaceBeforeElseLeftBrace, getDefaultAsBoolean(spaceBeforeElseLeftBrace));
 148.535 +    }
 148.536 +
 148.537 +    public boolean spaceBeforeWhileLeftBrace() {
 148.538 +    return preferences.getBoolean(spaceBeforeWhileLeftBrace, getDefaultAsBoolean(spaceBeforeWhileLeftBrace));
 148.539 +    }
 148.540 +
 148.541 +    public boolean spaceBeforeForLeftBrace() {
 148.542 +    return preferences.getBoolean(spaceBeforeForLeftBrace, getDefaultAsBoolean(spaceBeforeForLeftBrace));
 148.543 +    }
 148.544 +
 148.545 +    public boolean spaceBeforeDoLeftBrace() {
 148.546 +    return preferences.getBoolean(spaceBeforeDoLeftBrace, getDefaultAsBoolean(spaceBeforeDoLeftBrace));
 148.547 +    }
 148.548 +
 148.549 +    public boolean spaceBeforeSwitchLeftBrace() {
 148.550 +    return preferences.getBoolean(spaceBeforeSwitchLeftBrace, getDefaultAsBoolean(spaceBeforeSwitchLeftBrace));
 148.551 +    }
 148.552 +
 148.553 +    public boolean spaceBeforeTryLeftBrace() {
 148.554 +    return preferences.getBoolean(spaceBeforeTryLeftBrace, getDefaultAsBoolean(spaceBeforeTryLeftBrace));
 148.555 +    }
 148.556 +
 148.557 +    public boolean spaceBeforeCatchLeftBrace() {
 148.558 +    return preferences.getBoolean(spaceBeforeCatchLeftBrace, getDefaultAsBoolean(spaceBeforeCatchLeftBrace));
 148.559 +    }
 148.560 +
 148.561 +    public boolean spaceBeforeFinallyLeftBrace() {
 148.562 +    return preferences.getBoolean(spaceBeforeFinallyLeftBrace, getDefaultAsBoolean(spaceBeforeFinallyLeftBrace));
 148.563 +    }
 148.564 +
 148.565 +    public boolean spaceBeforeSynchronizedLeftBrace() {
 148.566 +    return preferences.getBoolean(spaceBeforeSynchronizedLeftBrace, getDefaultAsBoolean(spaceBeforeSynchronizedLeftBrace));
 148.567 +    }
 148.568 +
 148.569 +    public boolean spaceBeforeStaticInitLeftBrace() {
 148.570 +    return preferences.getBoolean(spaceBeforeStaticInitLeftBrace, getDefaultAsBoolean(spaceBeforeStaticInitLeftBrace));
 148.571 +    }
 148.572 +
 148.573 +    public boolean spaceBeforeArrayInitLeftBrace() {
 148.574 +    return preferences.getBoolean(spaceBeforeArrayInitLeftBrace, getDefaultAsBoolean(spaceBeforeArrayInitLeftBrace));
 148.575 +    }
 148.576 +
 148.577 +    public boolean spaceWithinParens() {
 148.578 +    return preferences.getBoolean(spaceWithinParens, getDefaultAsBoolean(spaceWithinParens));
 148.579 +    }
 148.580 +
 148.581 +    public boolean spaceWithinMethodDeclParens() {
 148.582 +    return preferences.getBoolean(spaceWithinMethodDeclParens, getDefaultAsBoolean(spaceWithinMethodDeclParens));
 148.583 +    }
 148.584 +
 148.585 +    public boolean spaceWithinMethodCallParens() {
 148.586 +    return preferences.getBoolean(spaceWithinMethodCallParens, getDefaultAsBoolean(spaceWithinMethodCallParens));
 148.587 +    }
 148.588 +
 148.589 +    public boolean spaceWithinIfParens() {
 148.590 +    return preferences.getBoolean(spaceWithinIfParens, getDefaultAsBoolean(spaceWithinIfParens));
 148.591 +    }
 148.592 +
 148.593 +    public boolean spaceWithinForParens() {
 148.594 +    return preferences.getBoolean(spaceWithinForParens, getDefaultAsBoolean(spaceWithinForParens));
 148.595 +    }
 148.596 +
 148.597 +    public boolean spaceWithinWhileParens() {
 148.598 +    return preferences.getBoolean(spaceWithinWhileParens, getDefaultAsBoolean(spaceWithinWhileParens));
 148.599 +    }
 148.600 +
 148.601 +    public boolean spaceWithinSwitchParens() {
 148.602 +    return preferences.getBoolean(spaceWithinSwitchParens, getDefaultAsBoolean(spaceWithinSwitchParens));
 148.603 +    }
 148.604 +
 148.605 +    public boolean spaceWithinCatchParens() {
 148.606 +    return preferences.getBoolean(spaceWithinCatchParens, getDefaultAsBoolean(spaceWithinCatchParens));
 148.607 +    }
 148.608 +
 148.609 +    public boolean spaceWithinSynchronizedParens() {
 148.610 +    return preferences.getBoolean(spaceWithinSynchronizedParens, getDefaultAsBoolean(spaceWithinSynchronizedParens));
 148.611 +    }
 148.612 +
 148.613 +    public boolean spaceWithinTypeCastParens() {
 148.614 +    return preferences.getBoolean(spaceWithinTypeCastParens, getDefaultAsBoolean(spaceWithinTypeCastParens));
 148.615 +    }
 148.616 +
 148.617 +    public boolean spaceWithinAnnotationParens() {
 148.618 +    return preferences.getBoolean(spaceWithinAnnotationParens, getDefaultAsBoolean(spaceWithinAnnotationParens));
 148.619 +    }
 148.620 +
 148.621 +    public boolean spaceWithinBraces() {
 148.622 +    return preferences.getBoolean(spaceWithinBraces, getDefaultAsBoolean(spaceWithinBraces));
 148.623 +    }
 148.624 +
 148.625 +    public boolean spaceWithinArrayInitBrackets() {
 148.626 +    return preferences.getBoolean(spaceWithinArrayInitBrackets, getDefaultAsBoolean(spaceWithinArrayInitBrackets));
 148.627 +    }
 148.628 +
 148.629 +    public boolean spaceBeforeComma() {
 148.630 +    return preferences.getBoolean(spaceBeforeComma, getDefaultAsBoolean(spaceBeforeComma));
 148.631 +    }
 148.632 +
 148.633 +    public boolean spaceAfterComma() {
 148.634 +    return preferences.getBoolean(spaceAfterComma, getDefaultAsBoolean(spaceAfterComma));
 148.635 +    }
 148.636 +
 148.637 +    public boolean spaceBeforeSemi() {
 148.638 +    return preferences.getBoolean(spaceBeforeSemi, getDefaultAsBoolean(spaceBeforeSemi));
 148.639 +    }
 148.640 +
 148.641 +    public boolean spaceAfterSemi() {
 148.642 +    return preferences.getBoolean(spaceAfterSemi, getDefaultAsBoolean(spaceAfterSemi));
 148.643 +    }
 148.644 +
 148.645 +    public boolean spaceBeforeColon() {
 148.646 +    return preferences.getBoolean(spaceBeforeColon, getDefaultAsBoolean(spaceBeforeColon));
 148.647 +    }
 148.648 +
 148.649 +    public boolean spaceAfterColon() {
 148.650 +    return preferences.getBoolean(spaceAfterColon, getDefaultAsBoolean(spaceAfterColon));
 148.651 +    }
 148.652 +
 148.653 +    public boolean spaceAfterTypeCast() {
 148.654 +    return preferences.getBoolean(spaceAfterTypeCast, getDefaultAsBoolean(spaceAfterTypeCast));
 148.655 +    }
 148.656 +
 148.657 +     */
 148.658 +    // Spaces -----------------------------------------------------------------
 148.659 +    public boolean addSpaceAroundOperators() {
 148.660 +        return preferences.getBoolean(addSpaceAroundOperators, getDefaultAsBoolean(addSpaceAroundOperators));
 148.661 +    }
 148.662 +
 148.663 +    public boolean removeSpaceInsideParens() {
 148.664 +        return preferences.getBoolean(removeSpaceInParens, getDefaultAsBoolean(removeSpaceInParens));
 148.665 +    }
 148.666 +
 148.667 +    public boolean addSpaceAfterComma() {
 148.668 +        return preferences.getBoolean(addSpaceAfterComma, getDefaultAsBoolean(addSpaceAfterComma));
 148.669 +    }
 148.670 +
 148.671 +    public boolean removeSpaceBeforeSep() {
 148.672 +        return preferences.getBoolean(removeSpaceBeforeSep, getDefaultAsBoolean(removeSpaceBeforeSep));
 148.673 +    }
 148.674 +
 148.675 +    public boolean removeSpaceInParamAssign() {
 148.676 +        return preferences.getBoolean(removeSpaceInParamAssign, getDefaultAsBoolean(removeSpaceInParamAssign));
 148.677 +    }
 148.678 +
 148.679 +    public boolean collapseSpaces() {
 148.680 +        return preferences.getBoolean(collapseSpaces, getDefaultAsBoolean(collapseSpaces));
 148.681 +    }
 148.682 +
 148.683 +    // Imports -----------------------------------------------------------------
 148.684 +    public boolean formatImports() {
 148.685 +        return preferences.getBoolean(formatImports, getDefaultAsBoolean(formatImports));
 148.686 +    }
 148.687 +
 148.688 +    public boolean oneImportPerLine() {
 148.689 +        return preferences.getBoolean(oneImportPerLine, getDefaultAsBoolean(oneImportPerLine));
 148.690 +    }
 148.691 +
 148.692 +    public boolean removeDuplicates() {
 148.693 +        return preferences.getBoolean(removeDuplicates, getDefaultAsBoolean(removeDuplicates));
 148.694 +    }
 148.695 +
 148.696 +    public boolean systemLibsFirst() {
 148.697 +        return preferences.getBoolean(systemLibsFirst, getDefaultAsBoolean(systemLibsFirst));
 148.698 +    }
 148.699 +
 148.700 +    public boolean preferSymbolImports() {
 148.701 +        return preferences.getBoolean(preferSymbolImports, getDefaultAsBoolean(preferSymbolImports));
 148.702 +    }
 148.703 +
 148.704 +    public boolean sortImports() {
 148.705 +        return preferences.getBoolean(sortImports, getDefaultAsBoolean(sortImports));
 148.706 +    }
 148.707 +
 148.708 +    public boolean separateFromImps() {
 148.709 +        return preferences.getBoolean(separateFromImps, getDefaultAsBoolean(separateFromImps));
 148.710 +    }
 148.711 +
 148.712 +    public ImportCleanupStyle cleanupImports() {
 148.713 +        String cleanup = preferences.get(cleanupUnusedImports, getDefaultAsString(cleanupUnusedImports));
 148.714 +        return ImportCleanupStyle.valueOf(cleanup);
 148.715 +    }
 148.716 +
 148.717 +    public String[] getPackagesForStarImport() {
 148.718 +        return null;
 148.719 +    }
 148.720 +
 148.721 +    // Nested classes ----------------------------------------------------------
 148.722 +    public enum WrapStyle {
 148.723 +        WRAP_ALWAYS,
 148.724 +        WRAP_IF_LONG,
 148.725 +        WRAP_NEVER
 148.726 +    }
 148.727 +
 148.728 +    public enum ImportCleanupStyle {
 148.729 +        LEAVE_ALONE,
 148.730 +        COMMENT_OUT,
 148.731 +        DELETE
 148.732 +    }
 148.733 +
 148.734 +    // Communication with non public packages ----------------------------------
 148.735 +    private static class Producer implements FmtOptions.CodeStyleProducer {
 148.736 +        @Override
 148.737 +        public CodeStyle create(Preferences preferences) {
 148.738 +            return new CodeStyle(preferences);
 148.739 +        }
 148.740 +    }
 148.741 +}
   149.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   149.2 +++ b/python.source/src/org/netbeans/modules/python/source/ImportEntry.java	Mon Sep 21 13:01:16 2015 +0200
   149.3 @@ -0,0 +1,171 @@
   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 + * The Original Software is NetBeans. The Initial Developer of the Original
  149.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  149.34 + * Microsystems, Inc. All Rights Reserved.
  149.35 + *
  149.36 + * If you wish your version of this file to be governed by only the CDDL
  149.37 + * or only the GPL Version 2, indicate your decision by adding
  149.38 + * "[Contributor] elects to include this software in this distribution
  149.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  149.40 + * single choice of license, a recipient has the option to distribute
  149.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  149.42 + * to extend the choice of license to its licensees as provided above.
  149.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  149.44 + * Version 2 license, then the option applies only if the new code is
  149.45 + * made subject to such option by the copyright holder.
  149.46 + */
  149.47 +package org.netbeans.modules.python.source;
  149.48 +
  149.49 +import org.python.antlr.PythonTree;
  149.50 +
  149.51 +/**
  149.52 + * State about a single atomic import. (A single import statement in Python
  149.53 + *  can correspond to many atomic imports: one for each symbol or module
  149.54 + *  imported)
  149.55 + *
  149.56 + * @author Tor Norbye
  149.57 + */
  149.58 +public class ImportEntry implements Comparable<ImportEntry> {
  149.59 +    public final String module;
  149.60 +    public final String asName;
  149.61 +    public final String symbol;
  149.62 +    public final boolean isSystem;
  149.63 +    public final boolean isFromImport;
  149.64 +    /**
  149.65 +     * Natural order of import statements (in the source). This will be non zero if
  149.66 +     * we want to preserve the original order rather than the alphabetical order.
  149.67 +     */
  149.68 +    public int ordinal;
  149.69 +    /** 
  149.70 +     * Corresponding import statement node. This will be non null if we want to consider
  149.71 +     * duplicate import statements as different 
  149.72 +     */
  149.73 +    public PythonTree node;
  149.74 +    /**
  149.75 +     * Whether we have a symbol import AND we're sorting by symbol imports.
  149.76 +     * Will be false even for symbol imports when we're not sorting by symbols.
  149.77 +     */
  149.78 +    public boolean sortedFrom;
  149.79 +
  149.80 +    public ImportEntry(String module, String symbol, String asName, boolean isSystem, PythonTree node, int ordinal) {
  149.81 +        super();
  149.82 +        this.module = module;
  149.83 +        this.symbol = symbol;
  149.84 +        this.asName = asName;
  149.85 +        this.isSystem = isSystem;
  149.86 +        this.isFromImport = symbol != null;
  149.87 +        this.node = node;
  149.88 +        this.ordinal = ordinal;
  149.89 +
  149.90 +        this.sortedFrom = symbol != null;
  149.91 +    }
  149.92 +
  149.93 +    public ImportEntry(String module, String asName, boolean isSystem, PythonTree node, int ordinal) {
  149.94 +        this(module, null, asName, isSystem, node, ordinal);
  149.95 +    }
  149.96 +
  149.97 +    @Override
  149.98 +    public boolean equals(Object obj) {
  149.99 +        if (obj == null) {
 149.100 +            return false;
 149.101 +        }
 149.102 +        if (getClass() != obj.getClass()) {
 149.103 +            return false;
 149.104 +        }
 149.105 +        final ImportEntry other = (ImportEntry)obj;
 149.106 +        if (this.node != other.node) {
 149.107 +            return false;
 149.108 +        }
 149.109 +        if ((this.module == null) ? (other.module != null) : !this.module.equals(other.module)) {
 149.110 +            return false;
 149.111 +        }
 149.112 +        if ((this.asName == null) ? (other.asName != null) : !this.asName.equals(other.asName)) {
 149.113 +            return false;
 149.114 +        }
 149.115 +        if ((this.symbol == null) ? (other.symbol != null) : !this.symbol.equals(other.symbol)) {
 149.116 +            return false;
 149.117 +        }
 149.118 +        return true;
 149.119 +    }
 149.120 +
 149.121 +    @Override
 149.122 +    public int hashCode() {
 149.123 +        int hash = 7;
 149.124 +        hash = 29 * hash + (this.module != null ? this.module.hashCode() : 0);
 149.125 +        return hash;
 149.126 +    }
 149.127 +
 149.128 +    @Override
 149.129 +    public int compareTo(ImportEntry other) {
 149.130 +        boolean thisIsFuture = "__future__".equals(module); // NOI18N
 149.131 +        boolean otherIsFuture = "__future__".equals(other.module); // NOI18N
 149.132 +        if (thisIsFuture != otherIsFuture) {
 149.133 +            return thisIsFuture ? -1 : 1;
 149.134 +        }
 149.135 +        if (isSystem != other.isSystem) {
 149.136 +            return isSystem ? -1 : 1;
 149.137 +        }
 149.138 +        if (sortedFrom != other.sortedFrom) {
 149.139 +            return sortedFrom ? 1 : -1;
 149.140 +        }
 149.141 +        if (ordinal != other.ordinal) {
 149.142 +            return ordinal - other.ordinal;
 149.143 +        }
 149.144 +        // Then we sort by module name
 149.145 +        int result = module.compareTo(other.module);
 149.146 +        if (result != 0) {
 149.147 +            return result;
 149.148 +        }
 149.149 +        // And then, for each module, first the imports, then the from imports
 149.150 +        if (isFromImport != other.isFromImport) {
 149.151 +            return isFromImport ? 1 : -1;
 149.152 +        }
 149.153 +        if (symbol != null) {
 149.154 +            assert other.symbol != null;
 149.155 +            // since isFromImport==
 149.156 +            result = symbol.compareTo(other.symbol);
 149.157 +            if (result != 0) {
 149.158 +                return result;
 149.159 +            }
 149.160 +        }
 149.161 +        if (asName == null) {
 149.162 +            return (other.asName == null) ? 0 : 1;
 149.163 +        }
 149.164 +        if (other.asName == null) {
 149.165 +            return -1;
 149.166 +        }
 149.167 +        return asName.compareTo(other.asName);
 149.168 +    }
 149.169 +
 149.170 +    @Override
 149.171 +    public String toString() {
 149.172 +        return "ImportEntry(" + module + ", " + symbol + ", " + asName + ")"; // NOI18N
 149.173 +    }
 149.174 +}
   150.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   150.2 +++ b/python.source/src/org/netbeans/modules/python/source/ImportManager.java	Mon Sep 21 13:01:16 2015 +0200
   150.3 @@ -0,0 +1,1048 @@
   150.4 +/*
   150.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   150.6 + *
   150.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   150.8 + *
   150.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  150.10 + * Other names may be trademarks of their respective owners.
  150.11 + *
  150.12 + * The contents of this file are subject to the terms of either the GNU
  150.13 + * General Public License Version 2 only ("GPL") or the Common
  150.14 + * Development and Distribution License("CDDL") (collectively, the
  150.15 + * "License"). You may not use this file except in compliance with the
  150.16 + * License. You can obtain a copy of the License at
  150.17 + * http://www.netbeans.org/cddl-gplv2.html
  150.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  150.19 + * specific language governing permissions and limitations under the
  150.20 + * License.  When distributing the software, include this License Header
  150.21 + * Notice in each file and include the License file at
  150.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  150.23 + * particular file as subject to the "Classpath" exception as provided
  150.24 + * by Oracle in the GPL Version 2 section of the License file that
  150.25 + * accompanied this code. If applicable, add the following below the
  150.26 + * License Header, with the fields enclosed by brackets [] replaced by
  150.27 + * your own identifying information:
  150.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  150.29 + *
  150.30 + * If you wish your version of this file to be governed by only the CDDL
  150.31 + * or only the GPL Version 2, indicate your decision by adding
  150.32 + * "[Contributor] elects to include this software in this distribution
  150.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  150.34 + * single choice of license, a recipient has the option to distribute
  150.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  150.36 + * to extend the choice of license to its licensees as provided above.
  150.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  150.38 + * Version 2 license, then the option applies only if the new code is
  150.39 + * made subject to such option by the copyright holder.
  150.40 + *
  150.41 + * Contributor(s):
  150.42 + *
  150.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  150.44 + */
  150.45 +package org.netbeans.modules.python.source;
  150.46 +
  150.47 +import java.awt.Toolkit;
  150.48 +import java.util.ArrayList;
  150.49 +import java.util.Collection;
  150.50 +import java.util.Collections;
  150.51 +import java.util.HashMap;
  150.52 +import java.util.HashSet;
  150.53 +import java.util.List;
  150.54 +import java.util.Map;
  150.55 +import java.util.Set;
  150.56 +import javax.swing.text.BadLocationException;
  150.57 +import org.netbeans.api.editor.EditorRegistry;
  150.58 +import org.netbeans.editor.BaseDocument;
  150.59 +import org.netbeans.editor.Utilities;
  150.60 +import org.netbeans.modules.csl.api.EditList;
  150.61 +import org.netbeans.modules.csl.api.OffsetRange;
  150.62 +import org.netbeans.modules.csl.spi.GsfUtilities;
  150.63 +import org.netbeans.modules.editor.indent.api.IndentUtils;
  150.64 +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
  150.65 +import org.netbeans.modules.python.source.ImportEntry;
  150.66 +import org.netbeans.modules.python.source.PythonAstUtils;
  150.67 +import org.netbeans.modules.python.source.PythonIndex;
  150.68 +import org.netbeans.modules.python.source.PythonParserResult;
  150.69 +import org.netbeans.modules.python.source.elements.IndexedElement;
  150.70 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  150.71 +import org.netbeans.modules.python.source.CodeStyle;
  150.72 +import org.netbeans.modules.python.source.CodeStyle.ImportCleanupStyle;
  150.73 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  150.74 +import org.netbeans.modules.python.source.scopes.SymInfo;
  150.75 +import org.openide.util.Exceptions;
  150.76 +import org.openide.util.NbBundle;
  150.77 +import org.python.antlr.PythonTree;
  150.78 +import org.python.antlr.ast.Import;
  150.79 +import org.python.antlr.ast.ImportFrom;
  150.80 +import org.python.antlr.ast.Str;
  150.81 +import org.python.antlr.ast.alias;
  150.82 +
  150.83 +/**
  150.84 + * Computations regarding module imports.
  150.85 + *
  150.86 + * @todo Handle commenting out portions of imports
  150.87 + * @todo If I can make this fast, consider highlighting unused imports.
  150.88 + * @todo On code completion I should import the corresponding package+class (make the
  150.89 + *   class part optional)
  150.90 + * @todo Watch out for commented out imports getting wiped out in organize imports
  150.91 + *   because it's between imports. These need to be moved to the end!!!
  150.92 + * @todo Offer to group imports
  150.93 + * @todo Don't import functions
  150.94 + *
  150.95 + * @author Tor Norbye
  150.96 + */
  150.97 +public final class ImportManager {
  150.98 +
  150.99 +    private PythonParserResult info;
 150.100 +    private List<Import> imports;
 150.101 +    private List<ImportFrom> importsFrom;
 150.102 +    private PythonTree root;
 150.103 +    private BaseDocument doc;
 150.104 +    private List<PythonTree> mainImports;
 150.105 +    private Set<PythonTree> topLevelImports;
 150.106 +
 150.107 +    // Settings
 150.108 +    private boolean systemLibsFirst = true;
 150.109 +    private boolean splitImports = true;
 150.110 +    private boolean sortImports = true;
 150.111 +    private boolean separateFromImps = false;
 150.112 +    private ImportCleanupStyle cleanup = ImportCleanupStyle.COMMENT_OUT;
 150.113 +    private boolean removeDuplicates;
 150.114 +    private int rightMargin;
 150.115 +
 150.116 +    public ImportManager(PythonParserResult info) {
 150.117 +        this(info, GsfUtilities.getDocument(info.getSnapshot().getSource().getFileObject(), false), null);
 150.118 +    }
 150.119 +
 150.120 +    public ImportManager(PythonParserResult info, BaseDocument doc) {
 150.121 +        this(info, doc, null);
 150.122 +    }
 150.123 +
 150.124 +    public ImportManager(PythonParserResult info, BaseDocument doc, CodeStyle codeStyle) {
 150.125 +        this.info = info;
 150.126 +
 150.127 +        root = PythonAstUtils.getRoot(info);
 150.128 +
 150.129 +        SymbolTable symbolTable = PythonAstUtils.getParseResult(info).getSymbolTable();
 150.130 +        imports = symbolTable.getImports();
 150.131 +        importsFrom = symbolTable.getImportsFrom();
 150.132 +        topLevelImports = symbolTable.getTopLevelImports();
 150.133 +        mainImports = symbolTable.getMainImports();
 150.134 +
 150.135 +        this.doc = doc;
 150.136 +
 150.137 +        if (codeStyle == null) {
 150.138 +            codeStyle = CodeStyle.getDefault(doc);
 150.139 +        }
 150.140 +        systemLibsFirst = codeStyle.systemLibsFirst();
 150.141 +        splitImports = codeStyle.oneImportPerLine();
 150.142 +        cleanup = codeStyle.cleanupImports();
 150.143 +        sortImports = codeStyle.sortImports();
 150.144 +        separateFromImps = codeStyle.separateFromImps();
 150.145 +        if (separateFromImps) {
 150.146 +            sortImports = true;
 150.147 +        }
 150.148 +        removeDuplicates = codeStyle.removeDuplicates();
 150.149 +        rightMargin = codeStyle.getRightMargin();
 150.150 +
 150.151 +    }
 150.152 +
 150.153 +    public static boolean isFutureImport(ImportFrom fromStatement) {
 150.154 +        return "__future__".equals(fromStatement.getInternalModule()); // NOI18N
 150.155 +    }
 150.156 +
 150.157 +    public void setCleanup(ImportCleanupStyle cleanup) {
 150.158 +        this.cleanup = cleanup;
 150.159 +    }
 150.160 +
 150.161 +    public void cleanup(EditList edits, int startOffset, int endOffset, boolean force) {
 150.162 +        OffsetRange lexRange = getMainImportsRange();
 150.163 +        if (lexRange == OffsetRange.NONE ||
 150.164 +                !(new OffsetRange(startOffset, endOffset).overlaps(lexRange))) {
 150.165 +            // Not touching imports
 150.166 +            return;
 150.167 +        }
 150.168 +
 150.169 +        if (cleanup != ImportCleanupStyle.LEAVE_ALONE) {
 150.170 +            List<String> ambiguousSymbols = new ArrayList<>();
 150.171 +            Map<String, String> defaultLists = new HashMap<>();
 150.172 +            Map<String, List<String>> alternatives = new HashMap<>();
 150.173 +            Set<ImportEntry> unused = new HashSet<>();
 150.174 +            Set<ImportEntry> duplicates = new HashSet<>();
 150.175 +
 150.176 +            computeImports(ambiguousSymbols, defaultLists, alternatives, unused, duplicates);
 150.177 +            if (ambiguousSymbols.size() == 0 || force) {
 150.178 +                apply(edits, new String[0], unused, duplicates);
 150.179 +                return;
 150.180 +            }
 150.181 +        } else if (removeDuplicates) {
 150.182 +            Set<ImportEntry> duplicates = findDuplicates();
 150.183 +            apply(edits, new String[0], Collections.<ImportEntry>emptySet(), duplicates);
 150.184 +            return;
 150.185 +        }
 150.186 +
 150.187 +        apply(edits, new String[0], Collections.<ImportEntry>emptySet(), Collections.<ImportEntry>emptySet());
 150.188 +    }
 150.189 +
 150.190 +    public List<Import> getImports() {
 150.191 +        return imports;
 150.192 +    }
 150.193 +
 150.194 +    public List<ImportFrom> getImportsFrom() {
 150.195 +        return importsFrom;
 150.196 +    }
 150.197 +
 150.198 +    private Set<ImportEntry> findDuplicates() {
 150.199 +        Set<ImportEntry> duplicates = new HashSet<>();
 150.200 +        // TODO!
 150.201 +
 150.202 +        return duplicates;
 150.203 +    }
 150.204 +
 150.205 +    public boolean computeImports(
 150.206 +            List<String> ambiguousSymbols,
 150.207 +            Map<String, String> defaults,
 150.208 +            Map<String, List<String>> alternatives, Set<ImportEntry> unused, Set<ImportEntry> duplicates) {
 150.209 +
 150.210 +        boolean ambiguous = false;
 150.211 +
 150.212 +        SymbolTable symbolTable = new SymbolTable(PythonAstUtils.getRoot(info), info.getSnapshot().getSource().getFileObject());
 150.213 +        Map<String, SymInfo> unresolved = symbolTable.getUnresolvedNames(info);
 150.214 +
 150.215 +        if (unresolved.size() > 0) {
 150.216 +            ambiguousSymbols.addAll(unresolved.keySet());
 150.217 +            Collections.sort(ambiguousSymbols);
 150.218 +
 150.219 +            // Try to compute suggestions.
 150.220 +            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 150.221 +            Set<IndexedElement> modules = index.getModules("", QuerySupport.Kind.PREFIX);
 150.222 +            for (IndexedElement module : modules) {
 150.223 +                String name = module.getName();
 150.224 +                if (unresolved.containsKey(name)) {
 150.225 +                    List<String> list = new ArrayList<>(4);
 150.226 +                    list.add(name);
 150.227 +                    defaults.put(name, name);
 150.228 +                    alternatives.put(name, list);
 150.229 +                }
 150.230 +            }
 150.231 +
 150.232 +            List<String> unresolvedList = new ArrayList<>(unresolved.keySet());
 150.233 +            Collections.sort(unresolvedList);
 150.234 +            for (String symbol : unresolvedList) {
 150.235 +                // TODO - determine if it's a call or variable
 150.236 +                // TODO - track import usages too!
 150.237 +                Collection<String> importsFor = index.getImportsFor(symbol, true);
 150.238 +                // TODO - insert symbols   + " (whole module)"
 150.239 +                if (importsFor.size() > 0) {
 150.240 +                    if (importsFor.size() > 1) {
 150.241 +                        List<String> l = new ArrayList<>(importsFor);
 150.242 +                        Collections.sort(l);
 150.243 +                        importsFor = l;
 150.244 +                    }
 150.245 +                    List<String> list = alternatives.get(symbol);
 150.246 +                    if (list == null) {
 150.247 +                        list = new ArrayList<>();
 150.248 +                        alternatives.put(symbol, list);
 150.249 +                    }
 150.250 +                    for (String s : importsFor) {
 150.251 +                        if (!list.contains(s)) {
 150.252 +                            list.add(s);
 150.253 +                        }
 150.254 +                    }
 150.255 +                    if (list.size() > 1) {
 150.256 +                        ambiguous = true;
 150.257 +                    }
 150.258 +
 150.259 +                // TODO - if it's a call, try to match functions instead of imported symbols
 150.260 +                } else {
 150.261 +                    ambiguous = true;
 150.262 +                }
 150.263 +            }
 150.264 +
 150.265 +        // TODO - look up -functions- and -data- defined across all modules
 150.266 +        // that might define these guys
 150.267 +
 150.268 +        }
 150.269 +
 150.270 +        List<String> unambiguousNames = new ArrayList<>();
 150.271 +        for (Map.Entry<String, List<String>> entry : alternatives.entrySet()) {
 150.272 +            List<String> list = entry.getValue();
 150.273 +            if (list == null || list.size() == 0) {
 150.274 +                ambiguous = true;
 150.275 +            } else if (list.size() == 1) {
 150.276 +                String key = entry.getKey();
 150.277 +                unambiguousNames.add(key);
 150.278 +            }
 150.279 +        }
 150.280 +
 150.281 +        // If we've had to choose certain libraries (e.g. because they're the
 150.282 +        // only choice available in some cases) then make those libraries default
 150.283 +        // for all the ambiguous cases as well
 150.284 +        if (!unambiguousNames.isEmpty()) {
 150.285 +            for (String name : alternatives.keySet()) {
 150.286 +                List<String> list = alternatives.get(name);
 150.287 +                for (String choice : list) {
 150.288 +                    if (unambiguousNames.contains(choice)) {
 150.289 +                        defaults.put(name, choice);
 150.290 +                    }
 150.291 +                }
 150.292 +            }
 150.293 +        }
 150.294 +
 150.295 +        unused.addAll(symbolTable.getUnusedImports());
 150.296 +
 150.297 +// During development
 150.298 +//ambiguous = true;
 150.299 +
 150.300 +        return ambiguous;
 150.301 +    }
 150.302 +
 150.303 +    public void apply(EditList edits, String[] selections, Set<ImportEntry> removeEntries, Set<ImportEntry> duplicates) {
 150.304 +        // Update the imports
 150.305 +        // Sort the imports
 150.306 +        // Delete the unused imports
 150.307 +        boolean apply = false;
 150.308 +        if (edits == null) {
 150.309 +            edits = new EditList(doc);
 150.310 +            apply = true;
 150.311 +        }
 150.312 +
 150.313 +        Set<PythonTree> removedAlready = new HashSet<>();
 150.314 +
 150.315 +        Set<PythonTree> mainImport;
 150.316 +        //if (sortImports) {
 150.317 +        mainImport = new HashSet<>(mainImports);
 150.318 +        //} else {
 150.319 +        //    mainImport = Collections.<PythonTree>emptySet();
 150.320 +        //}
 150.321 +        Set<PythonTree> topLevel = topLevelImports;
 150.322 +
 150.323 +//
 150.324 +//        // Remove duplicates. Note - these are always removed, not just commented out.
 150.325 +//        if (duplicates.size() > 0 && cleanup != ImportCleanupStyle.LEAVE_ALONE) {
 150.326 +//            Set<PythonTree> candidates = new HashSet<PythonTree>();
 150.327 +//            // Map from import node to list of names that should be removed, if only some are duplicates
 150.328 +//            Map<PythonTree,List<String>> names = new HashMap<PythonTree,List<String>>();
 150.329 +//            // Find the corresponding import
 150.330 +//            //List<PythonTree> candidates = new ArrayList<PythonTree>();
 150.331 +//            boolean foundFirst = false;
 150.332 +//            for (Import imp : imports) {
 150.333 +//                if (imp.names != null) {
 150.334 +//                    boolean all = true;
 150.335 +//                    boolean some = false;
 150.336 +//                    for (alias at : imp.getInternalNames()) {
 150.337 +//                        if (duplicates.contains(at.getInternalName())) {
 150.338 +//                            if (!foundFirst) {
 150.339 +//                                foundFirst = true;
 150.340 +//                            } else {
 150.341 +//                                some = true;
 150.342 +//                                List<String> nameList = names.get(imp);
 150.343 +//                                if (nameList == null) {
 150.344 +//                                    nameList = new ArrayList<String>();
 150.345 +//                                    names.put(imp, nameList);
 150.346 +//                                }
 150.347 +//                                nameList.add(at.getInternalName());
 150.348 +//                            }
 150.349 +//                            break;
 150.350 +//                        } else {
 150.351 +//                            all = false;
 150.352 +//                        }
 150.353 +//                    }
 150.354 +//                    if (some) {
 150.355 +//                        candidates.add(imp);
 150.356 +//                        if (all) {
 150.357 +//                            // No need to limit deletion to just one
 150.358 +//                            names.put(imp, null);
 150.359 +//                        }
 150.360 +//                    }
 150.361 +//                }
 150.362 +//            }
 150.363 +//
 150.364 +//            for (ImportFrom from : importsFrom) {
 150.365 +//                if (from.names != null) {
 150.366 +//                    boolean all = true;
 150.367 +//                    boolean some = false;
 150.368 +//                    for (alias at : from.names) {
 150.369 +//                        assert at.getInternalName() != null;
 150.370 +//                        String value;
 150.371 +//                        if (at.getInternalAsname() != null) {
 150.372 +//                            value = from.module + ":" + at.getInternalName() + ":" + at.getInternalAsname();
 150.373 +//                        } else {
 150.374 +//                            value = from.module + ":" + at.getInternalName();
 150.375 +//                        }
 150.376 +//                        if (duplicates.contains(value)) {
 150.377 +//                            if (!foundFirst) {
 150.378 +//                                foundFirst = true;
 150.379 +//                            } else {
 150.380 +//                                some = true;
 150.381 +//                                List<String> nameList = names.get(from);
 150.382 +//                                if (nameList == null) {
 150.383 +//                                    nameList = new ArrayList<String>();
 150.384 +//                                    names.put(from, nameList);
 150.385 +//                                }
 150.386 +//                                nameList.add(at.getInternalName());
 150.387 +//                            }
 150.388 +//                        } else {
 150.389 +//                            all = false;
 150.390 +//                        }
 150.391 +//                    }
 150.392 +//                    if (some) {
 150.393 +//                        candidates.add(from);
 150.394 +//                        if (all) {
 150.395 +//                            // No need to limit deletion to just one
 150.396 +//                            names.put(from, null);
 150.397 +//                        }
 150.398 +//                    }
 150.399 +//                }
 150.400 +//            }
 150.401 +//
 150.402 +//            Set<PythonTree> filtered = new HashSet<PythonTree>();
 150.403 +//            for (PythonTree node : candidates) {
 150.404 +//                if (!mainImport.contains(node) && topLevel.contains(node)) {
 150.405 +//                    filtered.add(node);
 150.406 +//                }
 150.407 +//            }
 150.408 +//
 150.409 +//            removedAlready.addAll(filtered);
 150.410 +//
 150.411 +//            // Note - we always REMOVE duplicate imports rather than just commenting
 150.412 +//            // them out. We may sometimes be wrong about unused imports, so we let
 150.413 +//            // users leave them commented out when we clean up to make it easier
 150.414 +//            // to backtrack if we were wrong. However, duplicate imports is something
 150.415 +//            // we can accurately detect and leaving them commented out isn't something
 150.416 +//            // users will probably want.
 150.417 +//            removeImports(edits, filtered, /*commentOut*/false, names);
 150.418 +//        }
 150.419 +
 150.420 +        if (cleanup == ImportCleanupStyle.LEAVE_ALONE) {
 150.421 +            removeEntries.clear();
 150.422 +        } else {
 150.423 +            Set<ImportEntry> newSet = new HashSet<>();
 150.424 +            Set<PythonTree> filtered = new HashSet<>();
 150.425 +            for (ImportEntry entry : removeEntries) {
 150.426 +                PythonTree node = entry.node;
 150.427 +                if (!mainImport.contains(node) && topLevel.contains(node)) {
 150.428 +                    filtered.add(node);
 150.429 +                } else {
 150.430 +                    if (removeDuplicates) {
 150.431 +                        entry.node = null;
 150.432 +                    }
 150.433 +                    if (sortImports) {
 150.434 +                        entry.ordinal = 0;
 150.435 +                    }
 150.436 +                    if (!separateFromImps) {
 150.437 +                        entry.sortedFrom = false;
 150.438 +                    }
 150.439 +                }
 150.440 +
 150.441 +                newSet.add(entry);
 150.442 +            }
 150.443 +            removeEntries = newSet;
 150.444 +//        int ordinal = 0;
 150.445 +//        if (unused.size() > 0 && cleanup != ImportCleanupStyle.LEAVE_ALONE) {
 150.446 +//            Set<PythonTree> candidates = new HashSet<PythonTree>();
 150.447 +//            Map<PythonTree,List<String>> names = new HashMap<PythonTree,List<String>>();
 150.448 +//            // Find the corresponding import
 150.449 +//            //List<PythonTree> candidates = new ArrayList<PythonTree>();
 150.450 +//            for (Import imp : imports) {
 150.451 +//                if (imp.names != null) {
 150.452 +//                    boolean all = true;
 150.453 +//                    boolean some = false;
 150.454 +//                    for (alias at : imp.getInternalNames()) {
 150.455 +//                        if (unused.contains(at.getInternalName())) {
 150.456 +//                            some = true;
 150.457 +//                            List<String> nameList = names.get(imp);
 150.458 +//                            if (nameList == null) {
 150.459 +//                                nameList = new ArrayList<String>();
 150.460 +//                                names.put(imp, nameList);
 150.461 +//                            }
 150.462 +//                            nameList.add(at.getInternalName());
 150.463 +//
 150.464 +//                            boolean isSystem = false; // Don't care what it is for deletion
 150.465 +//                            removeEntries.add(new ImportEntry(at.getInternalName(), at.getInternalAsname(), isSystem,
 150.466 +//                                    removeDuplicates ? null : imp,
 150.467 +//                                    sortImports ? 0 : ordinal++));
 150.468 +//                          break;
 150.469 +//                        } else {
 150.470 +//                            all = false;
 150.471 +//                        }
 150.472 +//                    }
 150.473 +//
 150.474 +//                    if (some) {
 150.475 +//                        candidates.add(imp);
 150.476 +//                        if (all) {
 150.477 +//                            // No need to limit deletion to just one
 150.478 +//                            names.put(imp, null);
 150.479 +//                        }
 150.480 +//                    }
 150.481 +//                }
 150.482 +//            }
 150.483 +//
 150.484 +//            for (ImportFrom from : importsFrom) {
 150.485 +//                if (from.names != null) {
 150.486 +//                    boolean all = true;
 150.487 +//                    boolean some = false;
 150.488 +//                    for (alias at : from.names) {
 150.489 +//                        boolean isSystem = false; // Don't care what it is for deletion
 150.490 +//
 150.491 +//                        assert at.getInternalName() != null;
 150.492 +//                        String value;
 150.493 +//                        if (at.getInternalAsname() != null) {
 150.494 +//                            value = from.module + ":" + at.getInternalName() + ":" + at.getInternalAsname();
 150.495 +//                        } else {
 150.496 +//                            value = from.module + ":" + at.getInternalName();
 150.497 +//                        }
 150.498 +//                        if (unused.contains(value)) {
 150.499 +//                            removeEntries.add(new ImportEntry(from.module, at.getInternalName(), at.getInternalAsname(), isSystem,
 150.500 +//                                    removeDuplicates ? null : from,
 150.501 +//                                    sortImports ? 0 : ordinal++));
 150.502 +//                            some = true;
 150.503 +//                            List<String> nameList = names.get(from);
 150.504 +//                            if (nameList == null) {
 150.505 +//                                nameList = new ArrayList<String>();
 150.506 +//                                names.put(from, nameList);
 150.507 +//                            }
 150.508 +//                            nameList.add(at.getInternalName());
 150.509 +//                        } else {
 150.510 +//                            all = false;
 150.511 +//                        }
 150.512 +//                    }
 150.513 +//                    if (some) {
 150.514 +//                        candidates.add(from);
 150.515 +//                        if (all) {
 150.516 +//                            // No need to limit deletion to just one
 150.517 +//                            names.put(from, null);
 150.518 +//                        }
 150.519 +//                    }
 150.520 +//                }
 150.521 +//            }
 150.522 +//
 150.523 +//            // Don't try to delete nodes we've already deleted or commented out
 150.524 +//            // because they are unused
 150.525 +//
 150.526 +//            candidates.removeAll(removedAlready);
 150.527 +//
 150.528 +//            Set<PythonTree> filtered = new HashSet<PythonTree>();
 150.529 +//            for (PythonTree node : candidates) {
 150.530 +//                if (!mainImport.contains(node) && topLevel.contains(node)) {
 150.531 +//                    filtered.add(node);
 150.532 +//                }
 150.533 +//            }
 150.534 +
 150.535 +            removeImports(edits, filtered, cleanup == ImportCleanupStyle.COMMENT_OUT, null);
 150.536 +        }
 150.537 +
 150.538 +        PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 150.539 +
 150.540 +        Collection<ImportEntry> newEntries = new ArrayList<>();
 150.541 +        if (selections != null) {
 150.542 +            for (String module : selections) {
 150.543 +                if (module.startsWith("<html>")) { // NOI18N
 150.544 +                    // Skip cannot resolve stuff
 150.545 +                    continue;
 150.546 +                }
 150.547 +                int colon = module.indexOf(':');
 150.548 +                if (colon != -1) {
 150.549 +                    int end = module.indexOf('(', colon + 1);
 150.550 +                    if (end == -1) {
 150.551 +                        end = module.indexOf(';', colon + 1);
 150.552 +                        if (end == -1) {
 150.553 +                            end = module.length();
 150.554 +                        }
 150.555 +                    }
 150.556 +                    String symbol = module.substring(colon + 1, end).trim();
 150.557 +                    module = module.substring(0, colon).trim();
 150.558 +                    boolean isSystem = systemLibsFirst && index.isSystemModule(module);
 150.559 +                    ImportEntry importEntry = new ImportEntry(module, symbol, null, isSystem, null, 0);
 150.560 +                    if (!separateFromImps) {
 150.561 +                        importEntry.sortedFrom = false;
 150.562 +                    }
 150.563 +                    newEntries.add(importEntry);
 150.564 +                } else {
 150.565 +                    boolean isSystem = systemLibsFirst && index.isSystemModule(module);
 150.566 +                    ImportEntry importEntry = new ImportEntry(module, null, null, isSystem, null, 0);
 150.567 +                    if (!separateFromImps) {
 150.568 +                        importEntry.sortedFrom = false;
 150.569 +                    }
 150.570 +                    newEntries.add(importEntry);
 150.571 +                }
 150.572 +            }
 150.573 +        }
 150.574 +
 150.575 +        rewriteMainImports(edits, newEntries, removeEntries);
 150.576 +
 150.577 +        if (apply) {
 150.578 +            edits.apply();
 150.579 +        }
 150.580 +    }
 150.581 +
 150.582 +    public boolean isTopLevel(PythonTree node) {
 150.583 +        return topLevelImports.contains(node);
 150.584 +    }
 150.585 +
 150.586 +    /**
 150.587 +     * Remove or comment out the given import statements (Import or ImportFrom).
 150.588 +     * @param edits The edit list to add edits for comment or removal
 150.589 +     * @param candidates The set of Import or ImportFrom nodes
 150.590 +     * @param commentOut If true, comment out the import, or else, delete it
 150.591 +     * @param onlyNames A map from nodes to lists where if the list is null,
 150.592 +     *   remove or comment out the entire import, otherwise comment
 150.593 +     *   or delete only the specified name portions.
 150.594 +     */
 150.595 +    public void removeImports(EditList edits, Set<PythonTree> candidates, boolean commentOut, Map<PythonTree, List<String>> onlyNames) {
 150.596 +        for (PythonTree node : candidates) {
 150.597 +            // Don't touch imports that aren't top level!!!
 150.598 +            // These can be inside If blocks and such so we don't
 150.599 +            // have enough knowledge to mess with them
 150.600 +            if (!isTopLevel(node)) {
 150.601 +                continue;
 150.602 +            }
 150.603 +
 150.604 +            OffsetRange astRange = PythonAstUtils.getRange(node);
 150.605 +            OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 150.606 +            if (lexRange == OffsetRange.NONE) {
 150.607 +                continue;
 150.608 +            }
 150.609 +
 150.610 +            List<String> names = onlyNames.get(node);
 150.611 +            if (names != null) {
 150.612 +
 150.613 +                // TODO Handle commenting out portions of a line! An idea which
 150.614 +                // might work is to replace the whole import with a new import
 150.615 +                // that moves the commented out portions to the end!!
 150.616 +
 150.617 +                // Only delete/comment out a portion of the line
 150.618 +//                if (commentOut) {
 150.619 +// TODO
 150.620 +//                } else {
 150.621 +                // Determine offsets within the line
 150.622 +                List<OffsetRange> ranges = new ArrayList<>();
 150.623 +                try {
 150.624 +                    int start = lexRange.getStart();
 150.625 +                    int end = lexRange.getEnd();
 150.626 +                    if (end > doc.getLength()) {
 150.627 +                        end = doc.getLength();
 150.628 +                        if (start > doc.getLength()) {
 150.629 +                            start = doc.getLength();
 150.630 +                        }
 150.631 +                    }
 150.632 +                    String line = doc.getText(start, end - start);
 150.633 +                    for (String name : names) {
 150.634 +                        int index = line.indexOf(name);
 150.635 +                        if (index != -1) {
 150.636 +                            int nameEnd = index + name.length();
 150.637 +                            boolean removedComma = false;
 150.638 +                            for (int i = nameEnd; i < line.length(); i++) {
 150.639 +                                char c = line.charAt(i);
 150.640 +                                if (c == ',') {
 150.641 +                                    removedComma = true;
 150.642 +                                    nameEnd = i + 1;
 150.643 +                                    if (nameEnd < line.length() && line.charAt(nameEnd) == ' ') {
 150.644 +                                        // Include space after comma in deletion
 150.645 +                                        nameEnd++;
 150.646 +                                    }
 150.647 +                                    break;
 150.648 +                                } else if (c == ' ' || c == '\t') {
 150.649 +                                    continue;
 150.650 +                                } else {
 150.651 +                                    break;
 150.652 +                                }
 150.653 +                            }
 150.654 +                            if (!removedComma) {
 150.655 +                                // If I removed the last name on the line there is no
 150.656 +                                // comma at the end, so I should try removing one -before-
 150.657 +                                // the name instead
 150.658 +                                for (int i = index - 1; i >= 0; i--) {
 150.659 +                                    char c = line.charAt(i);
 150.660 +                                    if (c == ',') {
 150.661 +                                        index = i;
 150.662 +                                        break;
 150.663 +                                    } else if (c == ' ' || c == '\t') {
 150.664 +                                        continue;
 150.665 +                                    } else {
 150.666 +                                        break;
 150.667 +                                    }
 150.668 +                                }
 150.669 +                            }
 150.670 +                            OffsetRange remove = new OffsetRange(start + index, start + nameEnd);
 150.671 +
 150.672 +                            // Prevent overlaps
 150.673 +                            for (OffsetRange range : ranges) {
 150.674 +                                if (range.overlaps(remove)) {
 150.675 +                                    if (range.getStart() < remove.getStart()) {
 150.676 +                                        remove = new OffsetRange(range.getEnd(), Math.max(remove.getEnd(), range.getEnd()));
 150.677 +                                    } else {
 150.678 +                                        remove = new OffsetRange(Math.min(remove.getStart(), range.getStart()), range.getStart());
 150.679 +                                    }
 150.680 +                                }
 150.681 +                            }
 150.682 +
 150.683 +                            ranges.add(remove);
 150.684 +                        }
 150.685 +                    }
 150.686 +                    int prio = 0;
 150.687 +                    for (OffsetRange range : ranges) {
 150.688 +                        edits.replace(range.getStart(), range.getLength(), null, false, prio++);
 150.689 +                    }
 150.690 +                } catch (BadLocationException ex) {
 150.691 +                    Exceptions.printStackTrace(ex);
 150.692 +                }
 150.693 +//                }
 150.694 +            } else {
 150.695 +                int start = lexRange.getStart();
 150.696 +                if (commentOut) {
 150.697 +                    edits.replace(start, 0, "#", false, 0); // NOI18N
 150.698 +                } else {
 150.699 +                    int length = lexRange.getLength();
 150.700 +                    // See if this leaves an empty line and if so remove it
 150.701 +                    int endPos = lexRange.getEnd();
 150.702 +                    if (endPos < doc.getLength()) {
 150.703 +                        try {
 150.704 +                            char c = doc.getText(endPos, 1).charAt(0);
 150.705 +                            if (c == '\n') {
 150.706 +                                length++;
 150.707 +                            }
 150.708 +                        } catch (BadLocationException ex) {
 150.709 +                            Exceptions.printStackTrace(ex);
 150.710 +                        }
 150.711 +                    }
 150.712 +                    edits.replace(start, length, null, false, 0);
 150.713 +                }
 150.714 +            }
 150.715 +        }
 150.716 +    }
 150.717 +
 150.718 +    private OffsetRange getMainImportsRange() {
 150.719 +        // Compute editor range required
 150.720 +        int begin = Integer.MAX_VALUE;
 150.721 +        int end = Integer.MIN_VALUE;
 150.722 +        OffsetRange lexRange;
 150.723 +        if (mainImports.size() == 0) {
 150.724 +            if (mainImports.size() == 1) {
 150.725 +                OffsetRange astRange = PythonAstUtils.getRange(mainImports.get(0));
 150.726 +                lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 150.727 +            } else {
 150.728 +                assert mainImports.size() == 0;
 150.729 +                begin = getImportsLexOffset(null);
 150.730 +                end = begin;
 150.731 +                lexRange = new OffsetRange(begin, end);
 150.732 +            }
 150.733 +        } else {
 150.734 +            for (PythonTree node : mainImports) {
 150.735 +                OffsetRange range = PythonAstUtils.getRange(node);
 150.736 +                if (range.getStart() < begin) {
 150.737 +                    begin = range.getStart();
 150.738 +                }
 150.739 +                if (range.getEnd() > end) {
 150.740 +                    end = range.getEnd();
 150.741 +                }
 150.742 +            }
 150.743 +            OffsetRange astReplace = new OffsetRange(begin, end);
 150.744 +            lexRange = PythonLexerUtils.getLexerOffsets(info, astReplace);
 150.745 +        }
 150.746 +
 150.747 +        return lexRange;
 150.748 +    }
 150.749 +
 150.750 +    public void rewriteMainImports(EditList edits, Collection<ImportEntry> newEntries, Set<ImportEntry> remove) {
 150.751 +        // Items to be deleted should be deleted after this
 150.752 +
 150.753 +        PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 150.754 +
 150.755 +        // TODO:
 150.756 +        // Look for comments to preserve
 150.757 +        // Replace the entire editor block
 150.758 +        Set<ImportEntry> entries = new HashSet<>();
 150.759 +        int ordinal = 0;
 150.760 +        for (PythonTree node : mainImports) {
 150.761 +            if (node instanceof Import) {
 150.762 +                Import imp = (Import)node;
 150.763 +                // TODO - look up for at.getInternalName()!
 150.764 +                List<alias> names = imp.getInternalNames();
 150.765 +                if (names != null) {
 150.766 +                    for (alias at : names) {
 150.767 +                        ImportEntry importEntry = new ImportEntry(at.getInternalName(), at.getInternalAsname(), systemLibsFirst && index.isSystemModule(at.getInternalName()),
 150.768 +                                removeDuplicates ? null : imp, sortImports ? 0 : ordinal++);
 150.769 +                        if (!separateFromImps) {
 150.770 +                            importEntry.sortedFrom = false;
 150.771 +                        }
 150.772 +                        entries.add(importEntry);
 150.773 +                    }
 150.774 +                }
 150.775 +            } else {
 150.776 +                assert node instanceof ImportFrom;
 150.777 +                ImportFrom imp = (ImportFrom)node;
 150.778 +                List<alias> names = imp.getInternalNames();
 150.779 +                if (names != null && names.size() > 0) {
 150.780 +                    // TODO - look up for imp.getInternalModule()!
 150.781 +                    boolean isSystemLibrary = systemLibsFirst && index.isSystemModule(imp.getInternalModule());
 150.782 +                    for (alias at : names) {
 150.783 +                        ImportEntry importEntry = new ImportEntry(imp.getInternalModule(), at.getInternalName(), at.getInternalAsname(), isSystemLibrary,
 150.784 +                                removeDuplicates ? null : imp, sortImports ? 0 : ordinal++);
 150.785 +                        if (!separateFromImps) {
 150.786 +                            importEntry.sortedFrom = false;
 150.787 +                        }
 150.788 +                        entries.add(importEntry);
 150.789 +                    }
 150.790 +                }
 150.791 +            }
 150.792 +        }
 150.793 +
 150.794 +        // Add in entries discovered as needed by the import manager
 150.795 +        if (newEntries.size() > 0) {
 150.796 +            entries.addAll(newEntries);
 150.797 +        }
 150.798 +
 150.799 +        // Remove any items that needs to be removed
 150.800 +        if (remove.size() > 0) {
 150.801 +            entries.removeAll(remove);
 150.802 +        }
 150.803 +
 150.804 +        // Sort imports -- first by system/nonsystem, then alphabetically
 150.805 +        List<ImportEntry> sortedEntries = new ArrayList<>(entries);
 150.806 +        Collections.sort(sortedEntries);
 150.807 +
 150.808 +        // Write out existing imports
 150.809 +        StringBuilder sb = new StringBuilder();
 150.810 +        int size = sortedEntries.size();
 150.811 +        if (size > 0) {
 150.812 +            boolean prevSystem = sortedEntries.get(0).isSystem;
 150.813 +
 150.814 +            for (int i = 0; i < size; i++) {
 150.815 +                ImportEntry entry = sortedEntries.get(i);
 150.816 +                if (systemLibsFirst && entry.isSystem != prevSystem) {
 150.817 +                    prevSystem = entry.isSystem;
 150.818 +                    sb.append("\n"); // NOI18N Separate system and regular libs
 150.819 +                }
 150.820 +
 150.821 +                if (entry.isFromImport) {
 150.822 +                    int start = sb.length();
 150.823 +                    sb.append("from "); // NOI18N
 150.824 +                    sb.append(entry.module);
 150.825 +                    sb.append(" import "); // NOI18N
 150.826 +                    sb.append(entry.symbol);
 150.827 +                    if (entry.asName != null) {
 150.828 +                        sb.append(" as "); // NOI18N
 150.829 +                        sb.append(entry.asName);
 150.830 +                    }
 150.831 +
 150.832 +                    if (!splitImports) {
 150.833 +                        // Look ahead and combine subsequent entries
 150.834 +                        int lookahead = i + 1;
 150.835 +                        for (; lookahead < size; lookahead++) {
 150.836 +                            ImportEntry next = sortedEntries.get(lookahead);
 150.837 +                            if (next.isFromImport != entry.isFromImport ||
 150.838 +                                    !next.module.equals(entry.module)) {
 150.839 +                                break;
 150.840 +                            }
 150.841 +                            sb.append(", "); // NOI18N
 150.842 +
 150.843 +                            if (sb.length() - start > rightMargin && (rightMargin > 30)) {
 150.844 +                                sb.append("\\\n");
 150.845 +                                start = sb.length();
 150.846 +                                sb.append(IndentUtils.createIndentString(doc, IndentUtils.indentLevelSize(doc)));
 150.847 +                            }
 150.848 +
 150.849 +                            sb.append(next.symbol);
 150.850 +                            if (next.asName != null) {
 150.851 +                                sb.append(" as ");
 150.852 +                                sb.append(next.asName);
 150.853 +                            }
 150.854 +                        }
 150.855 +                        i = lookahead - 1;
 150.856 +                    }
 150.857 +                    sb.append("\n"); // NOI18N
 150.858 +                } else {
 150.859 +                    // Plain import
 150.860 +                    // We never combine imports
 150.861 +                    sb.append("import "); // NOI18N
 150.862 +                    sb.append(entry.module);
 150.863 +                    if (entry.asName != null) {
 150.864 +                        sb.append(" as "); // NOI18N
 150.865 +                        sb.append(entry.asName);
 150.866 +                    }
 150.867 +                    sb.append("\n"); // NOI18N
 150.868 +                }
 150.869 +            }
 150.870 +        }
 150.871 +
 150.872 +        // Write commented out deleted entries as well
 150.873 +        if (remove.size() > 0 && cleanup == ImportCleanupStyle.COMMENT_OUT) {
 150.874 +            size = remove.size();
 150.875 +            List<ImportEntry> sortedRemove = new ArrayList<>();
 150.876 +            sortedRemove.addAll(remove);
 150.877 +            Collections.sort(sortedRemove);
 150.878 +            for (ImportEntry entry : sortedRemove) {
 150.879 +                if (entry.isFromImport) {
 150.880 +                    sb.append("#from "); // NOI18N
 150.881 +                    sb.append(entry.module);
 150.882 +                    sb.append(" import "); // NOI18N
 150.883 +                    sb.append(entry.symbol);
 150.884 +                    if (entry.asName != null) {
 150.885 +                        sb.append(" as "); // NOI18N
 150.886 +                        sb.append(entry.asName);
 150.887 +                    }
 150.888 +                    sb.append("\n"); // NOI18N
 150.889 +                } else {
 150.890 +                    sb.append("#import "); // NOI18N
 150.891 +                    sb.append(entry.module);
 150.892 +                    if (entry.asName != null) {
 150.893 +                        sb.append(" as "); // NOI18N
 150.894 +                        sb.append(entry.asName);
 150.895 +                    }
 150.896 +                    sb.append("\n"); // NOI18N
 150.897 +                }
 150.898 +            }
 150.899 +        }
 150.900 +
 150.901 +        // Compute editor range required
 150.902 +        OffsetRange lexRange = getMainImportsRange();
 150.903 +
 150.904 +        // Replace final newline if it's there so we don't grow whitespace around the imports
 150.905 +        int lastNewlineDelta = 0;
 150.906 +        try {
 150.907 +            if (lexRange.getEnd() < doc.getLength() && doc.getText(lexRange.getEnd(), 1).charAt(0) == '\n') {
 150.908 +                lastNewlineDelta++;
 150.909 +            }
 150.910 +        } catch (BadLocationException ex) {
 150.911 +            Exceptions.printStackTrace(ex);
 150.912 +        }
 150.913 +
 150.914 +        edits.replace(lexRange.getStart(), lexRange.getLength() + lastNewlineDelta, sb.toString(), false, 0);
 150.915 +    }
 150.916 +
 150.917 +    /** Compute the location where the main import block should be located */
 150.918 +    public int getImportsLexOffset(String module) {
 150.919 +        int begin = 0;
 150.920 +
 150.921 +        // First try computing a position in the standard imports
 150.922 +        if (module != null) {
 150.923 +            PythonTree last = null;
 150.924 +            for (PythonTree node : mainImports) {
 150.925 +                boolean stop = false;
 150.926 +                if (node instanceof Import) {
 150.927 +                    Import imp = (Import)node;
 150.928 +                    List<alias> names = imp.getInternalNames();
 150.929 +                    if (names != null && names.size() > 0 &&
 150.930 +                            names.get(0).getInternalName().compareTo(module) >= 0) {
 150.931 +                        stop = true;
 150.932 +                    }
 150.933 +                } else {
 150.934 +                    assert node instanceof ImportFrom;
 150.935 +                    ImportFrom imp = (ImportFrom)node;
 150.936 +                    if (imp.getInternalModule().compareTo(module) >= 0) {
 150.937 +                        stop = true;
 150.938 +                    }
 150.939 +                }
 150.940 +
 150.941 +                if (stop) {
 150.942 +                    return PythonLexerUtils.getLexerOffsets(info,
 150.943 +                            PythonAstUtils.getRange(node)).getStart();
 150.944 +                }
 150.945 +
 150.946 +                last = node;
 150.947 +            }
 150.948 +
 150.949 +            if (last != null) {
 150.950 +                return PythonLexerUtils.getLexerOffsets(info,
 150.951 +                        PythonAstUtils.getRange(last)).getStart();
 150.952 +            }
 150.953 +        }
 150.954 +
 150.955 +        Str documentationNode = PythonAstUtils.getDocumentationNode(root);
 150.956 +        if (documentationNode != null) {
 150.957 +            int astEnd = documentationNode.getCharStopIndex();
 150.958 +            begin = PythonLexerUtils.getLexerOffset(info, astEnd);
 150.959 +            if (begin == -1) {
 150.960 +                begin = 0;
 150.961 +            } else {
 150.962 +                begin = Math.min(doc.getLength(), begin);
 150.963 +                try {
 150.964 +                    begin = Utilities.getRowEnd(doc, begin) + 1;
 150.965 +                    begin = Math.min(begin, doc.getLength());
 150.966 +                } catch (BadLocationException ex) {
 150.967 +                    Exceptions.printStackTrace(ex);
 150.968 +                    begin = 0;
 150.969 +                }
 150.970 +            }
 150.971 +        }
 150.972 +
 150.973 +        // TODO - I should even do a lexical lookup for this in case we're in an embedded scenario!
 150.974 +        return begin;
 150.975 +    }
 150.976 +
 150.977 +    /** Determine if the given module is imported (for the given symbol) */
 150.978 +    public boolean isImported(String module, String ident) {
 150.979 +        for (Import imp : imports) {
 150.980 +            List<alias> names = imp.getInternalNames();
 150.981 +            if (names != null) {
 150.982 +                for (alias at : names) {
 150.983 +                    if (module.equals(at.getInternalName()) && (ident == null || (ident.equals(module) || ident.equals(at.getInternalAsname())))) {
 150.984 +                        return true;
 150.985 +                    }
 150.986 +                }
 150.987 +            }
 150.988 +        }
 150.989 +
 150.990 +        for (ImportFrom from : importsFrom) {
 150.991 +            if (module.equals(from.getInternalModule())) {
 150.992 +                // Make sure -this- symbol hasn't been imported!
 150.993 +                if (ident != null) {
 150.994 +                    List<alias> names = from.getInternalNames();
 150.995 +                    if (names != null) {
 150.996 +                        for (alias at : names) {
 150.997 +                            if (at.getInternalAsname() == null) {
 150.998 +                                // If you have "from module1 import Class1 as Class2", then
 150.999 +                                // "Class1" is not already imported, and "Class2" is.
150.1000 +                                if (ident.equals(at.getInternalName())) {
150.1001 +                                    return true;
150.1002 +                                }
150.1003 +                            } else if (ident.equals(at.getInternalAsname())) {
150.1004 +                                return true;
150.1005 +                            }
150.1006 +                        }
150.1007 +                    }
150.1008 +                }
150.1009 +            }
150.1010 +        }
150.1011 +
150.1012 +        return false;
150.1013 +    }
150.1014 +
150.1015 +    public void ensureImported(String name, String ident, boolean packageImport, boolean useFqn, boolean warnIfExists) {
150.1016 +        // TODO - look up the splitImports setting and add to existing import if possible...
150.1017 +
150.1018 +        if (PythonIndex.isBuiltinModule(name)) {
150.1019 +            return;
150.1020 +        }
150.1021 +
150.1022 +        // Test whether already imported
150.1023 +        if (isImported(name, ident)) {
150.1024 +            if (warnIfExists) {
150.1025 +                Utilities.setStatusText(EditorRegistry.lastFocusedComponent(),
150.1026 +                        NbBundle.getMessage(
150.1027 +                        ImportManager.class,
150.1028 +                        packageImport ? "MSG_PackageAlreadyImported" : "MSG_ClassAlreadyImported",
150.1029 +                        name, ident));
150.1030 +                Toolkit.getDefaultToolkit().beep();
150.1031 +            }
150.1032 +            return;
150.1033 +        }
150.1034 +
150.1035 +        int begin = getImportsLexOffset(ident);
150.1036 +        try {
150.1037 +            // TODO - warp to the new import and let you edit the "AS" part??
150.1038 +
150.1039 +            if (useFqn || ident == null) {
150.1040 +                doc.insertString(begin, "import " + name + "\n", null); // NOI18N
150.1041 +            } else if (packageImport) {
150.1042 +                //doc.insertString(begin, "import " + name + "\n", null); // NOI18N
150.1043 +                doc.insertString(begin, "from " + name + " import *\n", null); // NOI18N
150.1044 +            } else {
150.1045 +                doc.insertString(begin, "from " + name + " import " + ident + "\n", null); // NOI18N
150.1046 +            }
150.1047 +        } catch (BadLocationException ble) {
150.1048 +            Exceptions.printStackTrace(ble);
150.1049 +        }
150.1050 +    }
150.1051 +}
   151.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   151.2 +++ b/python.source/src/org/netbeans/modules/python/source/NameStyle.java	Mon Sep 21 13:01:16 2015 +0200
   151.3 @@ -0,0 +1,198 @@
   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 +
  151.46 +package org.netbeans.modules.python.source;
  151.47 +
  151.48 +import org.openide.util.NbBundle;
  151.49 +
  151.50 +/**
  151.51 + *
  151.52 + * @author Tor Norbye
  151.53 + */
  151.54 +public enum NameStyle {
  151.55 +    NO_PREFERENCE(NbBundle.getMessage(NameStyle.class, "NoPreference")),
  151.56 +    LOWERCASE("lowercase"),
  151.57 +    LOWERCASE_WITH_UNDERSCORES("lowercase_with_underscores"),
  151.58 +    UPPERCASE("UPPERCASE"),
  151.59 +    UPPERCASE_WITH_UNDERSCORES("UPPERCASE_WITH_UNDERSCORES"),
  151.60 +    CAPITALIZED_WORDS("CapitalizedWords"),
  151.61 +    MIXED_CASE("mixedCase"),
  151.62 +    CAPITALIZED_WITH_UNDERSCORES("Capitalized_With_Underscores");
  151.63 +
  151.64 +    private String displayName;
  151.65 +
  151.66 +    NameStyle(String displayName) {
  151.67 +        this.displayName = displayName;
  151.68 +    }
  151.69 +
  151.70 +    public String getDisplayName() {
  151.71 +        return displayName;
  151.72 +    }
  151.73 +
  151.74 +    public boolean complies(String name) {
  151.75 +        if (name.length() == 0) {
  151.76 +            return true;
  151.77 +        }
  151.78 +
  151.79 +        // Always allow one or two "_" at the beginning and end of the name since
  151.80 +        // these are used to indicate private, builtin, etc.
  151.81 +        int start = 0;
  151.82 +        int end = name.length();
  151.83 +        if (name.startsWith("__")) { // NOI18N
  151.84 +            start = 2;
  151.85 +        } else if (name.startsWith("_")) { // NOI18N
  151.86 +            start = 1;
  151.87 +        }
  151.88 +
  151.89 +        if (name.endsWith("__")) { // NOI18N
  151.90 +            end -= 2;
  151.91 +        } else if (name.endsWith("_")) { // NOI18N
  151.92 +            end -= 1;
  151.93 +        }
  151.94 +
  151.95 +        if (start >= end) {
  151.96 +            return false;
  151.97 +        }
  151.98 +
  151.99 +        switch (this) {
 151.100 +            case NO_PREFERENCE:
 151.101 +                return true;
 151.102 +
 151.103 +            case LOWERCASE_WITH_UNDERSCORES:
 151.104 +            case LOWERCASE:
 151.105 +                for (int i = start; i < end; i++) {
 151.106 +                    char c = name.charAt(i);
 151.107 +                    if (c == '_') {
 151.108 +                        if (this != LOWERCASE_WITH_UNDERSCORES) {
 151.109 +                            return false;
 151.110 +                        }
 151.111 +                    } else if (Character.isDigit(c)) {
 151.112 +                    } else if (!Character.isLowerCase(c)) {
 151.113 +                        return false;
 151.114 +                    }
 151.115 +                }
 151.116 +                
 151.117 +                return true;
 151.118 +                
 151.119 +
 151.120 +            case UPPERCASE:
 151.121 +            case UPPERCASE_WITH_UNDERSCORES:
 151.122 +                for (int i = start; i < end; i++) {
 151.123 +                    char c = name.charAt(i);
 151.124 +                    if (c == '_') {
 151.125 +                        if (this != UPPERCASE_WITH_UNDERSCORES) {
 151.126 +                            return false;
 151.127 +                        }
 151.128 +                    } else if (Character.isDigit(c)) {
 151.129 +                    } else if (!Character.isUpperCase(c)) {
 151.130 +                        return false;
 151.131 +                    }
 151.132 +                }
 151.133 +
 151.134 +                return true;
 151.135 +
 151.136 +            case MIXED_CASE:
 151.137 +            // TODO - require that characters after _ are capitalized?
 151.138 +            case CAPITALIZED_WORDS:
 151.139 +            case CAPITALIZED_WITH_UNDERSCORES:
 151.140 +                if (this == MIXED_CASE) {
 151.141 +                    // Must begin with lowercase
 151.142 +                    if (!Character.isLowerCase(name.charAt(start))) {
 151.143 +                        return false;
 151.144 +                    }
 151.145 +                } else if (this == CAPITALIZED_WORDS || this == CAPITALIZED_WITH_UNDERSCORES) {
 151.146 +                    // Must begin with uppercase
 151.147 +                    if (!Character.isUpperCase(name.charAt(start))) {
 151.148 +                        return false;
 151.149 +                    }
 151.150 +                }
 151.151 +                for (int i = start+1; i < end; i++) {
 151.152 +                    char c = name.charAt(i);
 151.153 +                    if (c == '_') {
 151.154 +                        if (this != CAPITALIZED_WITH_UNDERSCORES) {
 151.155 +                           return false;
 151.156 +                        }
 151.157 +                    } else if (Character.isDigit(c)) {
 151.158 +                    } else if (!Character.isUpperCase(c) && !Character.isLowerCase(c)) {
 151.159 +                        return false;
 151.160 +                    }
 151.161 +
 151.162 +                    // What about digits?
 151.163 +                }
 151.164 +
 151.165 +                return true;
 151.166 +            default:
 151.167 +                assert false : this;
 151.168 +        }
 151.169 +        
 151.170 +        return true;
 151.171 +    }
 151.172 +    
 151.173 +    public static boolean isProtectedName(String name) {
 151.174 +        // Protected variable starts with a single _
 151.175 +        // this is a convention only
 151.176 +        if (!name.startsWith("__")) {
 151.177 +            // NOI18N
 151.178 +            if (name.startsWith("_")) {
 151.179 +                // NOI18N
 151.180 +                return true;
 151.181 +            }
 151.182 +        }
 151.183 +        return false;
 151.184 +    }
 151.185 +
 151.186 +    public static boolean isPrivateName(String name) {
 151.187 +        // Private variables: start with __ but doesn't end with __
 151.188 +        // Section 9.6 Private Variables - http://docs.python.org/tut/node11.html
 151.189 +        if (name != null && name.startsWith("__") && !name.endsWith("__")) {
 151.190 +            // NOI18N
 151.191 +            return true;
 151.192 +        } else if (name != null && name.startsWith("_") && !name.endsWith("_")) {
 151.193 +            // NOI18N
 151.194 +            // From PEP8: Single_leading_underscore: weak "internal use" indicator
 151.195 +            // (e.g. "from M import *" does not import objects whose name
 151.196 +            // starts with an underscore).
 151.197 +            return true;
 151.198 +        }
 151.199 +        return false;
 151.200 +    }
 151.201 +}
   152.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   152.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonAstUtils.java	Mon Sep 21 13:01:16 2015 +0200
   152.3 @@ -0,0 +1,1007 @@
   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.util.ArrayList;
  152.37 +import java.util.Collections;
  152.38 +import java.util.HashSet;
  152.39 +import java.util.Iterator;
  152.40 +import java.util.List;
  152.41 +import java.util.Set;
  152.42 +import java.util.logging.Level;
  152.43 +import java.util.logging.Logger;
  152.44 +import javax.swing.text.BadLocationException;
  152.45 +import javax.swing.text.Document;
  152.46 +import org.netbeans.api.lexer.LanguagePath;
  152.47 +import org.netbeans.api.lexer.TokenHierarchy;
  152.48 +import org.netbeans.api.lexer.TokenSequence;
  152.49 +import org.netbeans.api.lexer.TokenUtilities;
  152.50 +import org.netbeans.editor.BaseDocument;
  152.51 +import org.netbeans.editor.Finder;
  152.52 +import org.netbeans.editor.FinderFactory;
  152.53 +import org.netbeans.modules.csl.api.ElementKind;
  152.54 +import org.netbeans.modules.csl.api.OffsetRange;
  152.55 +import org.netbeans.modules.csl.api.StructureItem;
  152.56 +import org.netbeans.modules.csl.spi.GsfUtilities;
  152.57 +import org.netbeans.modules.csl.spi.ParserResult;
  152.58 +import org.netbeans.modules.parsing.api.ParserManager;
  152.59 +import org.netbeans.modules.parsing.api.ResultIterator;
  152.60 +import org.netbeans.modules.parsing.api.Source;
  152.61 +import org.netbeans.modules.parsing.api.UserTask;
  152.62 +import org.netbeans.modules.parsing.spi.ParseException;
  152.63 +import org.netbeans.modules.python.source.elements.IndexedElement;
  152.64 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  152.65 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
  152.66 +import org.netbeans.modules.python.source.lexer.PythonCommentTokenId;
  152.67 +import org.netbeans.modules.python.source.scopes.ScopeInfo;
  152.68 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  152.69 +import org.netbeans.modules.python.source.scopes.SymInfo;
  152.70 +import org.openide.filesystems.FileObject;
  152.71 +import org.openide.util.Exceptions;
  152.72 +import org.python.antlr.PythonTree;
  152.73 +import org.python.antlr.Visitor;
  152.74 +import org.python.antlr.ast.Assign;
  152.75 +import org.python.antlr.ast.Attribute;
  152.76 +import org.python.antlr.ast.Call;
  152.77 +import org.python.antlr.ast.ClassDef;
  152.78 +import org.python.antlr.ast.Expr;
  152.79 +import org.python.antlr.ast.FunctionDef;
  152.80 +import org.python.antlr.ast.Import;
  152.81 +import org.python.antlr.ast.ImportFrom;
  152.82 +import org.python.antlr.ast.Module;
  152.83 +import org.python.antlr.ast.Name;
  152.84 +import org.python.antlr.ast.Str;
  152.85 +import org.python.antlr.ast.arguments;
  152.86 +import org.python.antlr.base.expr;
  152.87 +import org.python.antlr.base.stmt;
  152.88 +
  152.89 +/**
  152.90 + * Utility functions for dealing with the Jython AST
  152.91 + *
  152.92 + * @author Tor Norbye
  152.93 + */
  152.94 +public class PythonAstUtils {
  152.95 +    private PythonAstUtils() {
  152.96 +        // This is just a utility class, no instances expected so private constructor
  152.97 +    }
  152.98 +
  152.99 +    public static int getAstOffset(ParserResult result, int lexOffset) {
 152.100 +        if (result != null) {
 152.101 +            return result.getSnapshot().getEmbeddedOffset(lexOffset);
 152.102 +        }
 152.103 +
 152.104 +        return lexOffset;
 152.105 +    }
 152.106 +
 152.107 +    public static OffsetRange getAstOffsets(ParserResult result, OffsetRange lexicalRange) {
 152.108 +        if (result != null) {
 152.109 +            int rangeStart = lexicalRange.getStart();
 152.110 +            int start = result.getSnapshot().getEmbeddedOffset(rangeStart);
 152.111 +            if (start == rangeStart) {
 152.112 +                return lexicalRange;
 152.113 +            } else if (start == -1) {
 152.114 +                return OffsetRange.NONE;
 152.115 +            } else {
 152.116 +                // Assumes the translated range maintains size
 152.117 +                return new OffsetRange(start, start + lexicalRange.getLength());
 152.118 +            }
 152.119 +        }
 152.120 +        return lexicalRange;
 152.121 +    }
 152.122 +
 152.123 +    public static PythonParserResult getParseResult(ParserResult result) {
 152.124 +        if(result == null || !(result instanceof PythonParserResult)) {
 152.125 +            return null;
 152.126 +        } else {
 152.127 +            return ((PythonParserResult)result);
 152.128 +        }
 152.129 +    }
 152.130 +
 152.131 +    public static PythonTree getRoot(ParserResult r) {
 152.132 +        assert r instanceof PythonParserResult;
 152.133 +
 152.134 +        PythonParserResult result = (PythonParserResult)r;
 152.135 +
 152.136 +        return result.getRoot();
 152.137 +    }
 152.138 +
 152.139 +    /**
 152.140 +     * Return a range that matches the given node's source buffer range
 152.141 +     */
 152.142 +    @SuppressWarnings("unchecked")
 152.143 +    public static OffsetRange getNameRange(PythonParserResult info, PythonTree node) {
 152.144 +//        final int type = node.getType();
 152.145 +//        switch (type) {
 152.146 +//        case Token.FUNCTION: {
 152.147 +//            if (node.hasChildren()) {
 152.148 +//                for (PythonTree child = node.getFirstChild(); child != null; child = child.getNext()) {
 152.149 +//                    if (child.getType() == Token.FUNCNAME) {
 152.150 +//                        return getNameRange(child);
 152.151 +//                    }
 152.152 +//                }
 152.153 +//            }
 152.154 +//
 152.155 +//            return getRange(node);
 152.156 +//        }
 152.157 +//        case Token.NAME:
 152.158 +//        case Token.BINDNAME:
 152.159 +//        case Token.FUNCNAME:
 152.160 +//        case Token.PARAMETER:
 152.161 +//        case Token.OBJLITNAME:
 152.162 +//            int start = node.getSourceStart();
 152.163 +//            String name = node.getString();
 152.164 +//            return new OffsetRange(start, start+name.length());
 152.165 +//        case Token.CALL:
 152.166 +//            PythonTree namePythonTree = findCallNamePythonTree(node);
 152.167 +//            if (namePythonTree != null) {
 152.168 +//                return getNameRange(namePythonTree);
 152.169 +//            }
 152.170 +//        }
 152.171 +
 152.172 +        // XXX Is there a faster way to determine if it's a function,
 152.173 +        // e.g. some kind of "kind" or "id" or "type" enum attribute on the tree node
 152.174 +        if (node instanceof FunctionDef) {
 152.175 +            FunctionDef def = (FunctionDef)node;
 152.176 +            //node.getType();
 152.177 +
 152.178 +            int defStart = def.getCharStartIndex();
 152.179 +
 152.180 +            // Turns out that when you have decorators, the function start offset
 152.181 +            // -includes- the decorators which precede the "def" keyword, thus we
 152.182 +            // have to scan forwards to find the true beginning.
 152.183 +            List<expr> decorators = def.getInternalDecorator_list();
 152.184 +            if (decorators != null && decorators.size() > 0) {
 152.185 +                int maxEnd = 0;
 152.186 +                for (expr expr : decorators) {
 152.187 +                    int exprEnd = expr.getCharStopIndex();
 152.188 +                    if (exprEnd > maxEnd) {
 152.189 +                        maxEnd = exprEnd;
 152.190 +                    }
 152.191 +                }
 152.192 +                if (decorators.size() > 1) {
 152.193 +                    maxEnd++;
 152.194 +                }
 152.195 +                defStart = maxEnd;
 152.196 +
 152.197 +                // At first I was justlooking for the largest end offset of the decorators,
 152.198 +                // but if you have additional comments etc. that won't work right, so
 152.199 +                // in this case, go and look at the actual document
 152.200 +                if (info != null) {
 152.201 +                    BaseDocument doc = GsfUtilities.getDocument(info.getSnapshot().getSource().getFileObject(), false);
 152.202 +                    if (doc != null) {
 152.203 +                        int lexOffset = PythonLexerUtils.getLexerOffset(info, defStart);
 152.204 +                        int limitOffset = PythonLexerUtils.getLexerOffset(info, def.getCharStopIndex());
 152.205 +                        if (lexOffset != -1 && limitOffset != -1) {
 152.206 +                            Finder finder = new FinderFactory.StringFwdFinder("def ", true);
 152.207 +                            try {
 152.208 +                                int foundOffset = doc.find(finder, lexOffset, limitOffset);
 152.209 +                                if (foundOffset != -1) {
 152.210 +                                    defStart = foundOffset;
 152.211 +                                }
 152.212 +                            } catch (BadLocationException ex) {
 152.213 +                                Exceptions.printStackTrace(ex);
 152.214 +                            }
 152.215 +                        }
 152.216 +                    }
 152.217 +                }
 152.218 +            }
 152.219 +
 152.220 +            // HACK: There's no separate node for the name offset itself, so I need
 152.221 +            // to figure it out. For now assume that it's exactly 4 characters away
 152.222 +            // from the beginning of "def" - def plus space. If there are multiple spaces
 152.223 +            // this won't work. I ought to look in the document and ensure that the character
 152.224 +            // there in fact is the start of the name, and if not, search forwards for it.
 152.225 +            int DELTA = 4; // HACK:
 152.226 +            int start = defStart + DELTA;
 152.227 +            int end = start + def.getInternalName().length();
 152.228 +
 152.229 +            // TODO - look up offset
 152.230 +
 152.231 +            return new OffsetRange(start, end);
 152.232 +        } else if (node instanceof ClassDef) {
 152.233 +            ClassDef def = (ClassDef)node;
 152.234 +            //node.getType();
 152.235 +
 152.236 +            // HACK: There's no separate node for the name offset itself, so I need
 152.237 +            // to figure it out. For now assume that it's exactly 6 characters away
 152.238 +            // from the beginning of "class" - class plus space. If there are multiple spaces
 152.239 +            // this won't work. I ought to look in the document and ensure that the character
 152.240 +            // there in fact is the start of the name, and if not, search forwards for it.
 152.241 +            int DELTA = 6; // HACK:
 152.242 +            int start = def.getCharStartIndex() + DELTA;
 152.243 +            int end = start + def.getInternalName().length();
 152.244 +
 152.245 +            // TODO - look up offset
 152.246 +
 152.247 +            return new OffsetRange(start, end);
 152.248 +        } else if (node instanceof Attribute) {
 152.249 +            Attribute attr = (Attribute)node;
 152.250 +            return getNameRange(info, attr.getInternalValue());
 152.251 +        } else if (node instanceof Call) {
 152.252 +            Call call = (Call)node;
 152.253 +            if (call.getInternalFunc() instanceof Name) {
 152.254 +                return getNameRange(info, call.getInternalFunc());
 152.255 +            } else if (call.getInternalFunc() instanceof Attribute) {
 152.256 +                // The call name is in the value part of the name.value part
 152.257 +                Attribute attr = (Attribute)call.getInternalFunc();
 152.258 +                int start = attr.getInternalValue().getCharStopIndex() + 1; // +1: Skip .
 152.259 +                String name = attr.getInternalAttr();
 152.260 +                return new OffsetRange(start, start + name.length());
 152.261 +            } else {
 152.262 +                String name = getCallName(call);
 152.263 +                if (name != null) {
 152.264 +                    int start = call.getCharStartIndex();
 152.265 +                    return new OffsetRange(start, start + name.length());
 152.266 +                }
 152.267 +            }
 152.268 +        }
 152.269 +
 152.270 +        return getRange(node);
 152.271 +    }
 152.272 +
 152.273 +    /**
 152.274 +     * Return a range that matches the given node's source buffer range
 152.275 +     */
 152.276 +    @SuppressWarnings("unchecked")
 152.277 +    public static OffsetRange getRange(PythonTree node) {
 152.278 +        final int start = node.getCharStartIndex();
 152.279 +        final int end = node.getCharStopIndex();
 152.280 +
 152.281 +//        assert end >= start : "Invalid offsets for " + node + ": start=" + start + " and end=" + end;
 152.282 +        if (end < start) {
 152.283 +            Logger logger = Logger.getLogger(PythonAstUtils.class.getName());
 152.284 +            logger.log(Level.WARNING, "Invalid offsets for " + node + ": start=" + start + " and end=" + end);
 152.285 +            return new OffsetRange(start, start);
 152.286 +        }
 152.287 +
 152.288 +        return new OffsetRange(start, end);
 152.289 +    }
 152.290 +
 152.291 +    public static boolean isNameNode(PythonTree node) {
 152.292 +        if (node instanceof Name) {
 152.293 +            return true;
 152.294 +        }
 152.295 +
 152.296 +        return false;
 152.297 +    }
 152.298 +
 152.299 +    /** Return if a function is a staticmethod **/
 152.300 +    public static boolean isStaticMethod(PythonTree node) {
 152.301 +        if (node instanceof FunctionDef) {
 152.302 +            FunctionDef def = (FunctionDef)node;
 152.303 +            List<expr> decorators = def.getInternalDecorator_list();
 152.304 +            if (decorators != null && decorators.size() > 0) {
 152.305 +                for (expr decorator : decorators) {
 152.306 +                    if (decorator instanceof Name) {
 152.307 +                        String decoratorName = ((Name)decorator).getText();
 152.308 +                        if (decoratorName.equals("staticmethod")) { // NOI18N
 152.309 +                            return true;
 152.310 +                        }
 152.311 +                    }
 152.312 +                }
 152.313 +            }
 152.314 +        }
 152.315 +
 152.316 +        return false;
 152.317 +    }
 152.318 +
 152.319 +    /** Compute the module/class name for the given node path */
 152.320 +    public static String getFqnName(AstPath path) {
 152.321 +        StringBuilder sb = new StringBuilder();
 152.322 +
 152.323 +        Iterator<PythonTree> it = path.rootToLeaf();
 152.324 +
 152.325 +        while (it.hasNext()) {
 152.326 +            PythonTree node = it.next();
 152.327 +
 152.328 +            if (node instanceof ClassDef) {
 152.329 +                if (sb.length() > 0) {
 152.330 +                    sb.append('.'); // NOI18N
 152.331 +                }
 152.332 +                ClassDef cls = (ClassDef)node;
 152.333 +                sb.append(cls.getInternalName());
 152.334 +            }
 152.335 +        }
 152.336 +
 152.337 +        return sb.toString();
 152.338 +    }
 152.339 +
 152.340 +    /** Return the node for the local scope containing the given node */
 152.341 +    public static PythonTree getLocalScope(AstPath path) {
 152.342 +        for (PythonTree node : path) {
 152.343 +            if (node instanceof FunctionDef) {
 152.344 +                return node;
 152.345 +            }
 152.346 +        }
 152.347 +
 152.348 +        return path.root();
 152.349 +    }
 152.350 +
 152.351 +    public static PythonTree getClassScope(AstPath path) {
 152.352 +        for (PythonTree node : path) {
 152.353 +            if (node instanceof ClassDef) {
 152.354 +                return node;
 152.355 +            }
 152.356 +        }
 152.357 +
 152.358 +        return path.root();
 152.359 +    }
 152.360 +
 152.361 +    public static ClassDef getClassDef(AstPath path) {
 152.362 +        for (PythonTree node : path) {
 152.363 +            if (node instanceof ClassDef) {
 152.364 +                return (ClassDef)node;
 152.365 +            }
 152.366 +        }
 152.367 +
 152.368 +        return null;
 152.369 +    }
 152.370 +
 152.371 +    public static boolean isClassMethod(AstPath path, FunctionDef def) {
 152.372 +        // Check to see if (a) the function is inside a class, and (b) it's
 152.373 +        // not nested in a function
 152.374 +        for (PythonTree node : path) {
 152.375 +            if (node instanceof ClassDef) {
 152.376 +                return true;
 152.377 +            }
 152.378 +            // Nested method private to this one?
 152.379 +            if (node instanceof FunctionDef && node != def) {
 152.380 +                return false;
 152.381 +            }
 152.382 +        }
 152.383 +
 152.384 +        return false;
 152.385 +    }
 152.386 +
 152.387 +    public static FunctionDef getFuncDef(AstPath path) {
 152.388 +        for (PythonTree node : path) {
 152.389 +            if (node instanceof FunctionDef) {
 152.390 +                return (FunctionDef)node;
 152.391 +            }
 152.392 +        }
 152.393 +
 152.394 +        return null;
 152.395 +    }
 152.396 +
 152.397 +    /**
 152.398 +     * Return true iff this call looks like a "getter". If we're not sure,
 152.399 +     * return the default value passed into this method, unknownDefault. 
 152.400 +     */
 152.401 +    public static boolean isGetter(Call call, boolean unknownDefault) {
 152.402 +        String name = PythonAstUtils.getCallName(call);
 152.403 +        if (name == null) {
 152.404 +            return unknownDefault;
 152.405 +        }
 152.406 +
 152.407 +        return name.startsWith("get") || name.startsWith("_get"); // NOI18N
 152.408 +    }
 152.409 +
 152.410 +    public static String getCallName(Call call) {
 152.411 +        expr func = call.getInternalFunc();
 152.412 +
 152.413 +        return getExprName(func);
 152.414 +    }
 152.415 +
 152.416 +    public static String getExprName(expr type) {
 152.417 +        if (type instanceof Attribute) {
 152.418 +            Attribute attr = (Attribute)type;
 152.419 +            return attr.getInternalAttr();
 152.420 +        } else if (type instanceof Name) {
 152.421 +            return ((Name)type).getInternalId();
 152.422 +        } else if (type instanceof Call) {
 152.423 +            Call call = (Call)type;
 152.424 +            return getExprName(call.getInternalFunc());
 152.425 +            //} else if (type instanceof Str) {
 152.426 +            //    return ((Str)type).getText();
 152.427 +        } else {
 152.428 +            return null;
 152.429 +        }
 152.430 +    }
 152.431 +
 152.432 +    public static String getName(PythonTree node) {
 152.433 +        if (node instanceof Name) {
 152.434 +            return ((Name)node).getInternalId();
 152.435 +        }
 152.436 +        if (node instanceof Attribute) {
 152.437 +            Attribute attrib = (Attribute)node;
 152.438 +            String prefix = getName(attrib.getInternalValue());
 152.439 +            return (prefix + '.' + attrib.getInternalAttr());
 152.440 +        }
 152.441 +        NameVisitor visitor = new NameVisitor();
 152.442 +        try {
 152.443 +            Object result = visitor.visit(node);
 152.444 +            if (result instanceof String) {
 152.445 +                return (String)result;
 152.446 +            } else {
 152.447 +                // TODO HANDLE THIS!
 152.448 +            }
 152.449 +        } catch (Exception ex) {
 152.450 +            Exceptions.printStackTrace(ex);
 152.451 +        }
 152.452 +
 152.453 +        return null;
 152.454 +    }
 152.455 +
 152.456 +    public static List<String> getParameters(FunctionDef def) {
 152.457 +        arguments args = def.getInternalArgs();
 152.458 +        List<String> params = new ArrayList<>();
 152.459 +
 152.460 +        NameVisitor visitor = new NameVisitor();
 152.461 +
 152.462 +        for (expr e : args.getInternalArgs()) {
 152.463 +            try {
 152.464 +                Object result = visitor.visit(e);
 152.465 +                if (result instanceof String) {
 152.466 +                    params.add((String)result);
 152.467 +                } else {
 152.468 +                    // TODO HANDLE THIS!
 152.469 +                }
 152.470 +            } catch (Exception ex) {
 152.471 +                Exceptions.printStackTrace(ex);
 152.472 +            }
 152.473 +        }
 152.474 +
 152.475 +        String vararg = args.getInternalVararg();
 152.476 +        if (vararg != null) {
 152.477 +            params.add(vararg);
 152.478 +        }
 152.479 +        String kwarg = args.getInternalKwarg();
 152.480 +        if (kwarg != null) {
 152.481 +            params.add(kwarg);
 152.482 +        }
 152.483 +
 152.484 +        return params;
 152.485 +    }
 152.486 +
 152.487 +    private static Str searchForDocNode(stmt stmt) {
 152.488 +        if (stmt instanceof Expr) {
 152.489 +            Expr expr = (Expr)stmt;
 152.490 +            expr value = expr.getInternalValue();
 152.491 +            if (value instanceof Str) {
 152.492 +                return (Str)value;
 152.493 +            }
 152.494 +        }
 152.495 +
 152.496 +        return null;
 152.497 +    }
 152.498 +
 152.499 +    public static Str getDocumentationNode(PythonTree node) {
 152.500 +        // DocString processing.
 152.501 +        // See http://www.python.org/dev/peps/pep-0257/
 152.502 +
 152.503 +        // For modules, it's the first Str in the document.
 152.504 +        // For classes and methods, it's the first Str in the object.
 152.505 +        // For others, nothing.
 152.506 +
 152.507 +        if (node instanceof FunctionDef) {
 152.508 +            // Function
 152.509 +            FunctionDef def = (FunctionDef)node;
 152.510 +            List<stmt> body = def.getInternalBody();
 152.511 +            if (body != null && body.size() > 0) {
 152.512 +                return searchForDocNode(body.get(0));
 152.513 +            }
 152.514 +        } else if (node instanceof ClassDef) {
 152.515 +            // Class
 152.516 +            ClassDef def = (ClassDef)node;
 152.517 +            List<stmt> body = def.getInternalBody();
 152.518 +            if (body != null && body.size() > 0) {
 152.519 +                return searchForDocNode(body.get(0));
 152.520 +            }
 152.521 +        } else if (node instanceof Module) {
 152.522 +            // Module
 152.523 +            Module module = (Module)node;
 152.524 +            List<stmt> body = module.getInternalBody();
 152.525 +            if (body != null && body.size() > 0) {
 152.526 +                return searchForDocNode(body.get(0));
 152.527 +            }
 152.528 +        }
 152.529 +        // TODO: As per http://www.python.org/dev/peps/pep-0257/ I should
 152.530 +        // also look for "additional docstrings" (Str node following a Str node)
 152.531 +        // and Assign str nodes
 152.532 +
 152.533 +        return null;
 152.534 +    }
 152.535 +
 152.536 +    public static String getStrContent(Str str) {
 152.537 +        String doc = str.getText();
 152.538 +
 152.539 +        // Strip quotes
 152.540 +        // and U and/or R for unicode/raw string. U must always preceede r if present.
 152.541 +        if (doc.startsWith("ur") || doc.startsWith("UR") || // NOI18N
 152.542 +                doc.startsWith("Ur") || doc.startsWith("uR")) { // NOI18N
 152.543 +            doc = doc.substring(2);
 152.544 +        } else if (doc.startsWith("r") || doc.startsWith("u") || // NOI18N
 152.545 +                doc.startsWith("R") || doc.startsWith("U")) { // NOI18N
 152.546 +            doc = doc.substring(1);
 152.547 +        }
 152.548 +
 152.549 +        if (doc.startsWith("\"\"\"") && doc.endsWith("\"\"\"")) { // NOI18N
 152.550 +            doc = doc.substring(3, doc.length() - 3);
 152.551 +        } else if (doc.startsWith("r\"\"\"") && doc.endsWith("\"\"\"")) { // NOI18N
 152.552 +            doc = doc.substring(4, doc.length() - 3);
 152.553 +        } else if (doc.startsWith("'''") && doc.endsWith("'''")) { // NOI18N
 152.554 +            doc = doc.substring(3, doc.length() - 3);
 152.555 +        } else if (doc.startsWith("r'''") && doc.endsWith("'''")) { // NOI18N
 152.556 +            doc = doc.substring(4, doc.length() - 3);
 152.557 +        } else if (doc.startsWith("\"") && doc.endsWith("\"")) { // NOI18N
 152.558 +            doc = doc.substring(1, doc.length() - 1);
 152.559 +        } else if (doc.startsWith("'") && doc.endsWith("'")) { // NOI18N
 152.560 +            doc = doc.substring(1, doc.length() - 1);
 152.561 +        }
 152.562 +
 152.563 +        return doc;
 152.564 +    }
 152.565 +
 152.566 +    public static String getDocumentation(PythonTree node) {
 152.567 +        Str str = getDocumentationNode(node);
 152.568 +        if (str != null) {
 152.569 +            return getStrContent(str);
 152.570 +        }
 152.571 +
 152.572 +        return null;
 152.573 +    }
 152.574 +
 152.575 +    public static PythonTree getForeignNode(final IndexedElement o, PythonParserResult[] parserResultRet) {
 152.576 +        FileObject fo = o.getFileObject();
 152.577 +
 152.578 +        if (fo == null) {
 152.579 +            return null;
 152.580 +        }
 152.581 +        
 152.582 +        Source source = Source.create(fo);
 152.583 +        if(source == null) {
 152.584 +            return null;
 152.585 +        }
 152.586 +        final PythonParserResult[] resultHolder = new PythonParserResult[1];
 152.587 +        try {
 152.588 +            ParserManager.parse(Collections.singleton(source), new UserTask() {
 152.589 +                
 152.590 +                @Override
 152.591 +                public void run(ResultIterator resultIterator) throws Exception {
 152.592 +                    resultHolder[0] = (PythonParserResult) resultIterator.getParserResult();
 152.593 +                }
 152.594 +            });
 152.595 +        } catch (ParseException ex) {
 152.596 +            Exceptions.printStackTrace(ex);
 152.597 +        }
 152.598 +
 152.599 +        PythonParserResult info = resultHolder[0];
 152.600 +        if (parserResultRet != null) {
 152.601 +            parserResultRet[0] = info;
 152.602 +        }
 152.603 +        PythonParserResult result = getParseResult(info);
 152.604 +        if (result == null) {
 152.605 +            return null;
 152.606 +        }
 152.607 +
 152.608 +        PythonTree root = getRoot(result);
 152.609 +        if (root == null) {
 152.610 +            return null;
 152.611 +        }
 152.612 +
 152.613 +        if (o.getKind() == ElementKind.MODULE && root instanceof Module) {
 152.614 +            return root;
 152.615 +        }
 152.616 +
 152.617 +        String signature = o.getSignature();
 152.618 +
 152.619 +        if (signature == null) {
 152.620 +            return null;
 152.621 +        }
 152.622 +
 152.623 +        SymbolTable symbolTable = result.getSymbolTable();
 152.624 +        SymInfo sym = symbolTable.findBySignature(o.getKind(), signature);
 152.625 +        if (sym != null && sym.node != null) {
 152.626 +            // Temporary diagnostic checking
 152.627 +            //assert ((o.getKind() != ElementKind.CONSTRUCTOR && o.getKind() != ElementKind.METHOD) ||
 152.628 +            //        sym.node instanceof FunctionDef);
 152.629 +            //assert o.getKind() != ElementKind.CLASS || sym.node instanceof ClassDef;
 152.630 +
 152.631 +            return sym.node;
 152.632 +        }
 152.633 +
 152.634 +        // TODO - check args etc.
 152.635 +//        String name = o.getName();
 152.636 +//        boolean lookForFunction = o.getKind() == ElementKind.CONSTRUCTOR || o.getKind() == ElementKind.METHOD;
 152.637 +//        if (lookForFunction) {
 152.638 +//            for (AstElement element : result.getStructure().getElements()) {
 152.639 +//                if (element.getName().equals(name) && element.getSignature().equals(signature)) {
 152.640 +//                        return element.getNode();
 152.641 +//                    }
 152.642 +//                }
 152.643 +//            }
 152.644 +//        }
 152.645 +
 152.646 +        ElementKind kind = o.getKind();
 152.647 +        List<PythonStructureItem> items = PythonStructureScanner.analyze(info).getElements();
 152.648 +        if (items != null) {
 152.649 +            return find(items, signature, kind);
 152.650 +        } else {
 152.651 +            return null;
 152.652 +        }
 152.653 +    }
 152.654 +
 152.655 +    private static PythonTree find(List<? extends StructureItem> items, String signature, ElementKind kind) {
 152.656 +        for (StructureItem item : items) {
 152.657 +            ElementKind childKind = item.getKind();
 152.658 +            if (childKind == kind &&
 152.659 +                    item instanceof PythonStructureItem &&
 152.660 +                    signature.equals(((PythonStructureItem)item).getSignature())) {
 152.661 +                return ((PythonStructureItem)item).getNode();
 152.662 +            }
 152.663 +            if (childKind == ElementKind.CLASS && signature.contains(item.getName())) {
 152.664 +                @SuppressWarnings("unchecked")
 152.665 +                List<? extends StructureItem> children = item.getNestedItems();
 152.666 +                PythonTree result = find(children, signature, kind);
 152.667 +                if (result != null) {
 152.668 +                    return result;
 152.669 +                }
 152.670 +            }
 152.671 +        }
 152.672 +
 152.673 +        return null;
 152.674 +    }
 152.675 +
 152.676 +    public static Set<OffsetRange> getAllOffsets(PythonParserResult info, AstPath path, int lexOffset, String name, boolean abortOnFree) {
 152.677 +        if (path == null) {
 152.678 +            path = AstPath.get(PythonAstUtils.getRoot(info), lexOffset);
 152.679 +        }
 152.680 +        PythonTree scope = PythonAstUtils.getLocalScope(path);
 152.681 +        SymbolTable symbolTable = PythonAstUtils.getParseResult(info).getSymbolTable();
 152.682 +        List<PythonTree> nodes = symbolTable.getOccurrences(scope, name, abortOnFree);
 152.683 +        if (nodes == null) {
 152.684 +            return null;
 152.685 +        }
 152.686 +        Set<OffsetRange> offsets = new HashSet<>();
 152.687 +        Document doc = GsfUtilities.getDocument(info.getSnapshot().getSource().getFileObject(), false);
 152.688 +        if (doc == null) {
 152.689 +            return Collections.emptySet();
 152.690 +        }
 152.691 +        for (PythonTree node : nodes) {
 152.692 +            OffsetRange astRange = PythonAstUtils.getNameRange(info, node);
 152.693 +            OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 152.694 +
 152.695 +            if (node instanceof Import || node instanceof ImportFrom) {
 152.696 +                // Try to find the exact spot
 152.697 +                if (abortOnFree) {
 152.698 +                    return null;
 152.699 +                } else {
 152.700 +                    lexRange = PythonLexerUtils.getImportNameOffset((BaseDocument)doc, lexRange, node, name);
 152.701 +                }
 152.702 +            } else if (abortOnFree && (node instanceof FunctionDef || node instanceof ClassDef)) {
 152.703 +                return null;
 152.704 +            }
 152.705 +
 152.706 +            if (lexRange != OffsetRange.NONE) {
 152.707 +                offsets.add(lexRange);
 152.708 +            }
 152.709 +        }
 152.710 +        // Look for type variables
 152.711 +        ScopeInfo scopeInfo = symbolTable.getScopeInfo(scope);
 152.712 +        if (scopeInfo != null) {
 152.713 +            SymInfo sym = scopeInfo.tbl.get(name);
 152.714 +            if (sym != null && sym.isVariable(false)) {
 152.715 +                // Look for type declarations that can apply to this variable
 152.716 +                OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, PythonAstUtils.getRange(scope));
 152.717 +                if (lexRange != OffsetRange.NONE) {
 152.718 +                    BaseDocument bdoc = (BaseDocument)doc;
 152.719 +                    try {
 152.720 +                        bdoc.readLock(); // For TokenHierarchy usage
 152.721 +                        TokenHierarchy hi = TokenHierarchy.get(doc);
 152.722 +                        LanguagePath languagePath = LanguagePath.get(LanguagePath.get(PythonTokenId.language()), PythonCommentTokenId.language());
 152.723 +                        int startOffset = Math.min(lexRange.getStart(), doc.getLength());
 152.724 +                        if (scope instanceof Module) {
 152.725 +                            startOffset = 0; // Pick up comments before code starts
 152.726 +                        }
 152.727 +                        int endOffset = Math.min(lexRange.getEnd(), doc.getLength());
 152.728 +                        @SuppressWarnings("unchecked")
 152.729 +                        List<TokenSequence<? extends PythonCommentTokenId>> tsl = hi.tokenSequenceList(languagePath, startOffset, endOffset);
 152.730 +                        for (TokenSequence<? extends PythonCommentTokenId> ts : tsl) {
 152.731 +                            ts.moveStart();
 152.732 +                            while (ts.moveNext()) {
 152.733 +                                PythonCommentTokenId id = ts.token().id();
 152.734 +                                if (id == PythonCommentTokenId.TYPEKEY) {
 152.735 +                                    if (ts.moveNext() && // skip separator
 152.736 +                                            ts.moveNext()) {
 152.737 +                                        if (ts.token().id() == PythonCommentTokenId.VARNAME) {
 152.738 +                                            if (TokenUtilities.equals(ts.token().text(), name)) {
 152.739 +                                                int start = ts.offset();
 152.740 +                                                OffsetRange nameRange = new OffsetRange(start, start + name.length());
 152.741 +                                                offsets.add(nameRange);
 152.742 +                                            }
 152.743 +                                        }
 152.744 +                                    }
 152.745 +                                }
 152.746 +                            }
 152.747 +                        }
 152.748 +                    } finally {
 152.749 +                        bdoc.readUnlock();
 152.750 +                    }
 152.751 +
 152.752 +                }
 152.753 +            }
 152.754 +        }
 152.755 +
 152.756 +        return offsets;
 152.757 +    }
 152.758 +
 152.759 +    private static final class NameVisitor extends Visitor {
 152.760 +        @Override
 152.761 +        public Object visitName(Name name) throws Exception {
 152.762 +            return name.getInternalId();
 152.763 +        }
 152.764 +    }
 152.765 +
 152.766 +    public static Set<OffsetRange> getLocalVarOffsets(PythonParserResult info, int lexOffset) {
 152.767 +        int astOffset = getAstOffset(info, lexOffset);
 152.768 +        if (astOffset != -1) {
 152.769 +            PythonTree root = getRoot(info);
 152.770 +            if (root != null) {
 152.771 +                AstPath path = AstPath.get(root, astOffset);
 152.772 +                if (path != null) {
 152.773 +                    PythonTree closest = path.leaf();
 152.774 +                    PythonTree scope = getLocalScope(path);
 152.775 +                    String name = ((Name)closest).getInternalId();
 152.776 +
 152.777 +                    return getLocalVarOffsets(info, scope, name);
 152.778 +                }
 152.779 +            }
 152.780 +        }
 152.781 +
 152.782 +        return Collections.emptySet();
 152.783 +    }
 152.784 +
 152.785 +    public static Set<OffsetRange> getLocalVarOffsets(PythonParserResult info, PythonTree scope, String name) {
 152.786 +        LocalVarVisitor visitor = new LocalVarVisitor(info, name, false, true);
 152.787 +        try {
 152.788 +            visitor.visit(scope);
 152.789 +            return visitor.getOffsets();
 152.790 +        } catch (Exception ex) {
 152.791 +            Exceptions.printStackTrace(ex);
 152.792 +            return Collections.emptySet();
 152.793 +        }
 152.794 +    }
 152.795 +
 152.796 +    public static List<Name> getLocalVarNodes(PythonParserResult info, PythonTree scope, String name) {
 152.797 +        LocalVarVisitor visitor = new LocalVarVisitor(info, name, true, false);
 152.798 +        try {
 152.799 +            visitor.visit(scope);
 152.800 +            return visitor.getVars();
 152.801 +        } catch (Exception ex) {
 152.802 +            Exceptions.printStackTrace(ex);
 152.803 +            return Collections.emptyList();
 152.804 +        }
 152.805 +    }
 152.806 +
 152.807 +    public static List<Name> getLocalVarAssignNodes(PythonParserResult info, PythonTree scope, String name) {
 152.808 +        LocalVarAssignVisitor visitor = new LocalVarAssignVisitor(info, name, true, false);
 152.809 +        try {
 152.810 +            visitor.visit(scope);
 152.811 +            return visitor.getVars();
 152.812 +        } catch (Exception ex) {
 152.813 +            Exceptions.printStackTrace(ex);
 152.814 +            return Collections.emptyList();
 152.815 +        }
 152.816 +    }
 152.817 +
 152.818 +    private static class LocalVarVisitor extends Visitor {
 152.819 +        private List<Name> vars = new ArrayList<>();
 152.820 +        private Set<OffsetRange> offsets = new HashSet<>();
 152.821 +        private String name;
 152.822 +        private PythonParserResult info;
 152.823 +        private boolean collectNames;
 152.824 +        private boolean collectOffsets;
 152.825 +        private PythonTree parent;
 152.826 +
 152.827 +        private LocalVarVisitor(PythonParserResult info, String name, boolean collectNames, boolean collectOffsets) {
 152.828 +            this.info = info;
 152.829 +            this.name = name;
 152.830 +            this.collectNames = collectNames;
 152.831 +            this.collectOffsets = collectOffsets;
 152.832 +        }
 152.833 +
 152.834 +        @Override
 152.835 +        public void traverse(PythonTree node) throws Exception {
 152.836 +            PythonTree oldParent = parent;
 152.837 +            parent = node;
 152.838 +            super.traverse(node);
 152.839 +            parent = oldParent;
 152.840 +        }
 152.841 +
 152.842 +        @Override
 152.843 +        public Object visitName(Name node) throws Exception {
 152.844 +            if (parent instanceof Call && ((Call)parent).getInternalFunc() == node) {
 152.845 +                return super.visitName(node);
 152.846 +            }
 152.847 +
 152.848 +            if ((name == null && !PythonUtils.isClassName(node.getInternalId(), false)) ||
 152.849 +                    (name != null && name.equals(node.getInternalId()))) {
 152.850 +                if (collectOffsets) {
 152.851 +                    OffsetRange astRange = PythonAstUtils.getNameRange(info, node);
 152.852 +                    OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 152.853 +                    if (lexRange != OffsetRange.NONE) {
 152.854 +                        offsets.add(astRange);
 152.855 +                    }
 152.856 +                }
 152.857 +                if (collectNames) {
 152.858 +                    vars.add(node);
 152.859 +                }
 152.860 +            }
 152.861 +
 152.862 +            return super.visitName(node);
 152.863 +        }
 152.864 +
 152.865 +        public Set<OffsetRange> getOffsets() {
 152.866 +            return offsets;
 152.867 +        }
 152.868 +
 152.869 +        public List<Name> getVars() {
 152.870 +            return vars;
 152.871 +        }
 152.872 +    }
 152.873 +
 152.874 +    private static class LocalVarAssignVisitor extends Visitor {
 152.875 +        private List<Name> vars = new ArrayList<>();
 152.876 +        private Set<OffsetRange> offsets = new HashSet<>();
 152.877 +        private String name;
 152.878 +        private PythonParserResult info;
 152.879 +        private boolean collectNames;
 152.880 +        private boolean collectOffsets;
 152.881 +        private PythonTree parent;
 152.882 +
 152.883 +        private LocalVarAssignVisitor(PythonParserResult info, String name, boolean collectNames, boolean collectOffsets) {
 152.884 +            this.info = info;
 152.885 +            this.name = name;
 152.886 +            this.collectNames = collectNames;
 152.887 +            this.collectOffsets = collectOffsets;
 152.888 +        }
 152.889 +
 152.890 +        @Override
 152.891 +        public Object visitName(Name node) throws Exception {
 152.892 +            if (parent instanceof FunctionDef || parent instanceof Assign) {
 152.893 +                if ((name == null && !PythonUtils.isClassName(node.getInternalId(), false)) ||
 152.894 +                        (name != null && name.equals(node.getInternalId()))) {
 152.895 +                    if (collectOffsets) {
 152.896 +                        OffsetRange astRange = PythonAstUtils.getNameRange(info, node);
 152.897 +                        OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 152.898 +                        if (lexRange != OffsetRange.NONE) {
 152.899 +                            offsets.add(astRange);
 152.900 +                        }
 152.901 +                    }
 152.902 +                    if (collectNames) {
 152.903 +                        vars.add(node);
 152.904 +                    }
 152.905 +                }
 152.906 +            }
 152.907 +
 152.908 +            return super.visitName(node);
 152.909 +        }
 152.910 +
 152.911 +        @Override
 152.912 +        public void traverse(PythonTree node) throws Exception {
 152.913 +            PythonTree oldParent = parent;
 152.914 +            parent = node;
 152.915 +            super.traverse(node);
 152.916 +            parent = oldParent;
 152.917 +        }
 152.918 +
 152.919 +        public Set<OffsetRange> getOffsets() {
 152.920 +            return offsets;
 152.921 +        }
 152.922 +
 152.923 +        public List<Name> getVars() {
 152.924 +            return vars;
 152.925 +        }
 152.926 +    }
 152.927 +
 152.928 +    /** Collect nodes of the given types (node.nodeId==NodeTypes.x) under the given root */
 152.929 +    public static void addNodesByType(PythonTree root, Class[] nodeClasses, List<PythonTree> result) {
 152.930 +        try {
 152.931 +            new NodeTypeVisitor(result, nodeClasses).visit(root);
 152.932 +        } catch (Exception ex) {
 152.933 +            Exceptions.printStackTrace(ex);
 152.934 +        }
 152.935 +    }
 152.936 +
 152.937 +    private static class NodeTypeVisitor extends Visitor {
 152.938 +        private Class[] nodeClasses;
 152.939 +        private List<PythonTree> result;
 152.940 +
 152.941 +        NodeTypeVisitor(List<PythonTree> result, Class[] nodeClasses) {
 152.942 +            this.result = result;
 152.943 +            this.nodeClasses = nodeClasses;
 152.944 +        }
 152.945 +
 152.946 +        @Override
 152.947 +        public void traverse(PythonTree node) throws Exception {
 152.948 +            for (Class nodeClasse : nodeClasses) {
 152.949 +                if (node.getClass() == nodeClasse) {
 152.950 +                    result.add(node);
 152.951 +                    break;
 152.952 +                }
 152.953 +            }
 152.954 +
 152.955 +            super.traverse(node);
 152.956 +        }
 152.957 +    }
 152.958 +
 152.959 +    public static Name getParentClassFromNode(AstPath path, PythonTree from, String name) {
 152.960 +        ClassDef curClass = (ClassDef)path.getTypedAncestor(ClassDef.class, from);
 152.961 +        if (curClass == null) {
 152.962 +            return null;
 152.963 +        }
 152.964 +
 152.965 +        List<expr> baseClasses = curClass.getInternalBases();
 152.966 +        if (baseClasses == null) {
 152.967 +            return null; // no inheritance ;
 152.968 +        }
 152.969 +        int ii = 0;
 152.970 +        while (ii < baseClasses.size()) {
 152.971 +            if (baseClasses.get(ii) instanceof Name) {
 152.972 +                Name cur = (Name)baseClasses.get(ii);
 152.973 +                if (cur.getInternalId().equals(name)) {
 152.974 +                    return cur;
 152.975 +                }
 152.976 +            }
 152.977 +            ii++;
 152.978 +        }
 152.979 +        return null;
 152.980 +    }
 152.981 +
 152.982 +    /**
 152.983 +     * Look for the caret offset in the parameter list; return the
 152.984 +     * index of the parameter that contains it.
 152.985 +     */
 152.986 +    public static int findArgumentIndex(Call call, int astOffset, AstPath path) {
 152.987 +
 152.988 +        // On the name part in the call rather than the args?
 152.989 +        if (astOffset <= call.getInternalFunc().getCharStopIndex()) {
 152.990 +            return -1;
 152.991 +        }
 152.992 +        List<expr> args = call.getInternalArgs();
 152.993 +        if (args != null) {
 152.994 +            int index = 0;
 152.995 +            for (; index < args.size(); index++) {
 152.996 +                expr et = args.get(index);
 152.997 +                if (et.getCharStopIndex() >= astOffset) {
 152.998 +                    return index;
 152.999 +                }
152.1000 +            }
152.1001 +        }
152.1002 +
152.1003 +        // TODO what about the other stuff in there -- 
152.1004 +        //call.keywords;
152.1005 +        //call.kwargs;
152.1006 +        //call.starargs;
152.1007 +
152.1008 +        return -1;
152.1009 +    }
152.1010 +}
   153.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   153.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonExample.py	Mon Sep 21 13:01:16 2015 +0200
   153.3 @@ -0,0 +1,10 @@
   153.4 +"""Sample Module"""
   153.5 +import foo
   153.6 +CONSTANT = "VALUE"
   153.7 +
   153.8 +class Foo(Bar):
   153.9 +    """Class doc"""
  153.10 +
  153.11 +    def __init__(self,args=''):
  153.12 +        # Comment
  153.13 +        print 1+2.0
   154.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   154.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonFormatter.java	Mon Sep 21 13:01:16 2015 +0200
   154.3 @@ -0,0 +1,655 @@
   154.4 +/*
   154.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   154.6 + *
   154.7 + * Copyright 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 + * If you wish your version of this file to be governed by only the CDDL
  154.31 + * or only the GPL Version 2, indicate your decision by adding
  154.32 + * "[Contributor] elects to include this software in this distribution
  154.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  154.34 + * single choice of license, a recipient has the option to distribute
  154.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  154.36 + * to extend the choice of license to its licensees as provided above.
  154.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  154.38 + * Version 2 license, then the option applies only if the new code is
  154.39 + * made subject to such option by the copyright holder.
  154.40 + *
  154.41 + * Contributor(s):
  154.42 + *
  154.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  154.44 + */
  154.45 +package org.netbeans.modules.python.source;
  154.46 +
  154.47 +import java.util.ArrayList;
  154.48 +import java.util.Collections;
  154.49 +import java.util.HashMap;
  154.50 +import java.util.List;
  154.51 +import java.util.Map;
  154.52 +import javax.swing.text.BadLocationException;
  154.53 +import javax.swing.text.Document;
  154.54 +import javax.swing.text.JTextComponent;
  154.55 +import org.netbeans.api.editor.EditorRegistry;
  154.56 +import org.netbeans.api.lexer.TokenSequence;
  154.57 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  154.58 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
  154.59 +import org.netbeans.api.lexer.Token;
  154.60 +import org.netbeans.api.lexer.TokenId;
  154.61 +import org.netbeans.api.lexer.TokenUtilities;
  154.62 +import org.netbeans.editor.BaseDocument;
  154.63 +import org.netbeans.editor.Utilities;
  154.64 +import org.netbeans.modules.csl.api.EditList;
  154.65 +import org.netbeans.modules.csl.api.Formatter;
  154.66 +import org.netbeans.modules.csl.spi.GsfUtilities;
  154.67 +import org.netbeans.modules.csl.spi.ParserResult;
  154.68 +import org.netbeans.modules.editor.indent.api.IndentUtils;
  154.69 +import org.netbeans.modules.editor.indent.spi.Context;
  154.70 +import org.openide.util.Exceptions;
  154.71 +
  154.72 +/**
  154.73 + * Implement formatting for Python. Since there are no {}'s etc. to uniquely
  154.74 + * impose indentation on Python, this formatter really just tries to enforce
  154.75 + * spaces-versus-tabs, and indentation width. E.g. it uses the existing indentation
  154.76 + * to determine whether the next line should be idented more, same or less as the
  154.77 + * current line and then enforces the current space and indent size settings.
  154.78 + *
  154.79 + * @todo Implement pretty printing: inserting newlines, removing spaces inside
  154.80 + *  parentheses, etc. See the recommendations in
  154.81 + *   http://www.python.org/dev/peps/pep-0008/
  154.82 + *  Do import statement cleanup too.
  154.83 + * @todo Line up comment lines (# as a suffix, continued from a previous line)
  154.84 + * @todo Handle continuation lines with extra indentation
  154.85 + * @todo Line up list initializations better?
  154.86 + * 
  154.87 + * @author Tor Norbye
  154.88 + */
  154.89 +public class PythonFormatter implements Formatter {
  154.90 +    private int indentSize;
  154.91 +    private int continuationIndentSize;
  154.92 +    private CodeStyle codeStyle;
  154.93 +
  154.94 +    public PythonFormatter() {
  154.95 +    }
  154.96 +
  154.97 +    public PythonFormatter(CodeStyle codeStyle) {
  154.98 +        this.codeStyle = codeStyle;
  154.99 +    }
 154.100 +
 154.101 +    @Override
 154.102 +    public void reformat(Context context, ParserResult compilationInfo) {
 154.103 +
 154.104 +        // No AST pretty printing yet
 154.105 +        // I should offer to go and do space insert/removal around commas, parentheses, etc.
 154.106 +        //  as well as balancing long argument lists across lines
 154.107 +        Document document = context.document();
 154.108 +        int startOffset = context.startOffset();
 154.109 +        int endOffset = context.endOffset();
 154.110 +
 154.111 +        reformat(context, document, startOffset, endOffset, (PythonParserResult) compilationInfo);
 154.112 +    }
 154.113 +
 154.114 +    public void reformat(final Context context, Document document, int startOffset, int endOffset, PythonParserResult info) {
 154.115 +        if (codeStyle == null) {
 154.116 +            codeStyle = CodeStyle.getDefault(context.document());
 154.117 +        }
 154.118 +        if (info != null && codeStyle != null && codeStyle.formatImports() && !GsfUtilities.isCodeTemplateEditing(document) &&
 154.119 +                PythonAstUtils.getParseResult(info) != null) {
 154.120 +            new ImportManager(info, (BaseDocument)document, codeStyle).cleanup(null, startOffset, endOffset, false);
 154.121 +        }
 154.122 +
 154.123 +        if (codeStyle != null) {
 154.124 +            cleanup(document, info, startOffset, endOffset);
 154.125 +        }
 154.126 +
 154.127 +        reindent(context, document, startOffset, endOffset);
 154.128 +    }
 154.129 +
 154.130 +    @Override
 154.131 +    public boolean needsParserResult() {
 154.132 +//        if (SourceUtils.isScanInProgress()) {
 154.133 +//            return false;
 154.134 +//        }
 154.135 +
 154.136 +        // If we're going to format imports, then yes, we need the parser result
 154.137 +        JTextComponent target = EditorRegistry.lastFocusedComponent();
 154.138 +        if (target != null) {
 154.139 +            CodeStyle cs = CodeStyle.getDefault(target.getDocument());
 154.140 +            return cs != null ? cs.formatImports() : false;
 154.141 +        }
 154.142 +        return false;
 154.143 +    }
 154.144 +
 154.145 +    @Override
 154.146 +    public int indentSize() {
 154.147 +        // 4 spaces: See http://www.python.org/dev/peps/pep-0008/
 154.148 +        return 4;
 154.149 +    }
 154.150 +
 154.151 +    @Override
 154.152 +    public int hangingIndentSize() {
 154.153 +        return 4;
 154.154 +    }
 154.155 +
 154.156 +    // Challenge: Two inconsistently formatted
 154.157 +    // Idea: Given a list of offsets and indentation, produce a graph (or recurse) where I mark all
 154.158 +    // siblings the exact same level
 154.159 +
 154.160 +    // Algorithm:
 154.161 +    //   Find smallest indent: That's the top level
 154.162 +    //   Build a graph? Each indent line.
 154.163 +    //
 154.164 +    @Override
 154.165 +    public void reindent(final Context context) {
 154.166 +        Document document = context.document();
 154.167 +        int startOffset = context.startOffset();
 154.168 +        int endOffset = context.endOffset();
 154.169 +
 154.170 +        reindent(context, document, startOffset, endOffset);
 154.171 +    }
 154.172 +
 154.173 +    @SuppressWarnings("deprecation") // For doc.getFormatter()
 154.174 +    public void reindent(final Context context, Document document, int startOffset, int endOffset) {
 154.175 +        endOffset = Math.min(endOffset, document.getLength());
 154.176 +        startOffset = Math.min(startOffset, endOffset);
 154.177 +
 154.178 +        continuationIndentSize = indentSize = IndentUtils.indentLevelSize(document);
 154.179 +
 154.180 +
 154.181 +        final BaseDocument doc = (BaseDocument)document;
 154.182 +        try {
 154.183 +            // Plan: Go through the lines, one by one, and compute the indentation levels relative to each other,
 154.184 +            // then normalize them (except inside strings), then apply!!
 154.185 +            // Also track whether we are used for newline indentation and if so, do smart bracket stuff
 154.186 +
 154.187 +            // Current indentation for the given line. -1 means that it should be left alone (e.g.
 154.188 +            // we don't mess with multiline string literals.
 154.189 +            final List<Integer> offsets = new ArrayList<>();
 154.190 +
 154.191 +            // Current indentation for the given line. -1 means that it should be left alone (e.g.
 154.192 +            // we don't mess with multiline string literals. Other negative numbers are offsets
 154.193 +            // pointing at a particular left parenthesis that this line should be aligned with
 154.194 +            final List<Integer> indentation = new ArrayList<>();
 154.195 +            final List<Integer> lParenOffsets = new ArrayList<>();
 154.196 +
 154.197 +            try {
 154.198 +                doc.readLock(); // For token hierarchy usage
 154.199 +
 154.200 +                TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(doc, startOffset);
 154.201 +
 154.202 +                int currentOffset = Utilities.getRowStart(doc, startOffset);
 154.203 +                int balance = 0;
 154.204 +                while (currentOffset <= endOffset) {
 154.205 +                    if (!(Utilities.isRowEmpty(doc, currentOffset) || Utilities.isRowWhite(doc, currentOffset))) {
 154.206 +                        Token<? extends PythonTokenId> token = PythonLexerUtils.getToken(doc, currentOffset);
 154.207 +                        int indent = GsfUtilities.getLineIndent(doc, currentOffset);
 154.208 +                        if (token != null) {
 154.209 +                            if (token.id() == PythonTokenId.STRING_LITERAL || token.id() == PythonTokenId.STRING_END) {
 154.210 +                                indent = -1;
 154.211 +                            }
 154.212 +                        }
 154.213 +
 154.214 +                        if (indent != -1) {
 154.215 +                            if (balance <= 0) {
 154.216 +                                indentation.add(indent);
 154.217 +                                offsets.add(currentOffset);
 154.218 +                            } else {
 154.219 +                                assert balance <= lParenOffsets.size();
 154.220 +                                int parenOffset = lParenOffsets.get(lParenOffsets.size()-balance);
 154.221 +                                indentation.add(-parenOffset);
 154.222 +                                offsets.add(currentOffset);
 154.223 +                            }
 154.224 +                        }
 154.225 +                    }
 154.226 +
 154.227 +                    // TODO - look up the tokens to make sure we don't have a problem with literal nodes
 154.228 +
 154.229 +                    if (currentOffset > doc.getLength()) {
 154.230 +                        break;
 154.231 +                    }
 154.232 +
 154.233 +                    // Update the line balance
 154.234 +                    int begin = Utilities.getRowStart(doc, currentOffset);
 154.235 +                    int end = Utilities.getRowEnd(doc, currentOffset);
 154.236 +
 154.237 +                    ts.move(begin);
 154.238 +
 154.239 +                    if (ts.moveNext()) {
 154.240 +                        do {
 154.241 +                            Token<? extends PythonTokenId> token = ts.token();
 154.242 +                            TokenId id = token.id();
 154.243 +
 154.244 +                            if (id == PythonTokenId.LPAREN) {
 154.245 +                                balance++;
 154.246 +                                lParenOffsets.add(ts.offset());
 154.247 +                            } else if (id == PythonTokenId.RPAREN) {
 154.248 +                                balance--;
 154.249 +                                if (!lParenOffsets.isEmpty()) {
 154.250 +                                    lParenOffsets.remove(lParenOffsets.size()-1);
 154.251 +                                }
 154.252 +                            }
 154.253 +                        } while (ts.moveNext() && (ts.offset() <= end));
 154.254 +                    }
 154.255 +
 154.256 +                    currentOffset = Utilities.getRowEnd(doc, currentOffset) + 1;
 154.257 +                }
 154.258 +            } finally {
 154.259 +                doc.readUnlock();
 154.260 +            }
 154.261 +
 154.262 +            // Nothing to do
 154.263 +            if (offsets.size() == 0) {
 154.264 +                return;
 154.265 +            }
 154.266 +
 154.267 +            assert indentation.size() == offsets.size();
 154.268 +
 154.269 +            final Map<Integer, Integer> offsetToLevel = new HashMap<>();
 154.270 +            final Map<Integer,Integer> offsetToIndex = new HashMap<>();
 154.271 +            List<Integer> parentIndentations = new ArrayList<>();
 154.272 +            int currentParentIndent = -1;
 154.273 +            int currentLevel = -1;
 154.274 +
 154.275 +            int firstIndent = indentation.get(0);
 154.276 +            List<Integer> sorted = new ArrayList<>(indentation);
 154.277 +            Collections.sort(sorted);
 154.278 +            // Attempt to shift the computed indentation to fit the right indentation levels
 154.279 +            // that are currently in the file?
 154.280 +            int firstNonNeg = 0;
 154.281 +            for (; firstNonNeg < sorted.size(); firstNonNeg++) {
 154.282 +                if (sorted.get(firstNonNeg) >= 0) {
 154.283 +                    break;
 154.284 +                }
 154.285 +            }
 154.286 +            boolean shiftToCurrent = true;
 154.287 +            if (firstIndent > sorted.get(firstNonNeg)) {
 154.288 +                shiftToCurrent = false;
 154.289 +                // The start is not at the top level... e.g. we have something like
 154.290 +                //      foo
 154.291 +                //   else
 154.292 +                //      bar
 154.293 +                // (e.g. we are formatting a fragment of code which doesn't include
 154.294 +                // the top). Here we need to find the "true" top levels, so we
 154.295 +                // push levels on to the stack
 154.296 +                int prev = -1;
 154.297 +                for (int indent : sorted) {
 154.298 +                    if (prev == indent) {
 154.299 +                        continue;
 154.300 +                    }
 154.301 +                    prev = indent;
 154.302 +                    if (indent < firstIndent) {
 154.303 +                        parentIndentations.add(currentParentIndent);
 154.304 +                        currentParentIndent = indent;
 154.305 +                        currentLevel++;
 154.306 +                    } else {
 154.307 +                        break;
 154.308 +                    }
 154.309 +                }
 154.310 +            }
 154.311 +
 154.312 +
 154.313 +            // TODO: What if I start in the middle of an expression such that I outdent
 154.314 +            // more than I indent? I have to build up the index levels if necessary
 154.315 +            // Go count popping levels
 154.316 +
 154.317 +            for (int i = 0, n = offsets.size(); i < n; i++) {
 154.318 +                int offset = offsets.get(i);
 154.319 +                int indent = indentation.get(i);
 154.320 +                if (indent == -1) {
 154.321 +                    // Leave line alone
 154.322 +                    offsetToLevel.put(offset, -1);
 154.323 +                    continue;
 154.324 +                }
 154.325 +                offsetToIndex.put(offset, i);
 154.326 +
 154.327 +                if (indent < 0) {
 154.328 +                    // Want to keep everything the same as the prev, plus delta
 154.329 +                } else if (indent > currentParentIndent) {
 154.330 +                    // New level
 154.331 +                    currentLevel++;
 154.332 +                    parentIndentations.add(currentParentIndent);
 154.333 +                    currentParentIndent = indent;
 154.334 +                } else if (indent < currentParentIndent) {
 154.335 +                    while (currentParentIndent > indent) {
 154.336 +                        currentLevel--;
 154.337 +                        if (parentIndentations.size() > 0) {
 154.338 +                            currentParentIndent = parentIndentations.remove(parentIndentations.size() - 1);
 154.339 +                        } else {
 154.340 +                            currentParentIndent = indent;
 154.341 +                        }
 154.342 +                    }
 154.343 +                }
 154.344 +
 154.345 +                offsetToLevel.put(offset, currentLevel);
 154.346 +            }
 154.347 +
 154.348 +            // Compute relative shift
 154.349 +            int firstLineIndent = indentation.get(0);
 154.350 +            int firstLineLevel = offsetToLevel.get(offsets.get(0));
 154.351 +            int computedIndent = firstLineLevel * indentSize;
 154.352 +            final int relativeShift = shiftToCurrent ? computedIndent - firstLineIndent : 0;
 154.353 +
 154.354 +            doc.runAtomic(new Runnable() {
 154.355 +                @Override
 154.356 +                public void run() {
 154.357 +                    int[] computedIndents = new int[offsets.size()];
 154.358 +                    // Process backwards so I don't have to worry about updating offsets affected by
 154.359 +                    // indentation changes
 154.360 +                    for (int i = offsets.size() - 1; i >= 0; i--) {
 154.361 +                        int indent = indentation.get(i);
 154.362 +                        if (indent == -1) {
 154.363 +                            // Leave line alone
 154.364 +                            continue;
 154.365 +                        }
 154.366 +                        if (indent >= 0) {
 154.367 +                            int offset = offsets.get(i);
 154.368 +                            int level = offsetToLevel.get(offset);
 154.369 +                            int computedIndent = level * indentSize - relativeShift;
 154.370 +                            if (computedIndent < 0) {
 154.371 +                                computedIndent = 0;
 154.372 +                            }
 154.373 +                            computedIndents[i] =computedIndent;
 154.374 +                        } else {
 154.375 +                            computedIndents[i] = -1;
 154.376 +                        }
 154.377 +                    }
 154.378 +
 154.379 +                    for (int i = offsets.size() - 1; i >= 0; i--) {
 154.380 +                        int indent = indentation.get(i);
 154.381 +                        if (indent < -1) {
 154.382 +                            try {
 154.383 +                                // Negative offset pointing to a left parenthesis we should align with
 154.384 +                                int parenOffset = -indent;
 154.385 +                                int lineStart = Utilities.getRowStart(doc, parenOffset);
 154.386 +                                if (lineStart != -1) {
 154.387 +                                    int parenLineIndent = computedIndents[offsetToIndex.get(lineStart)];
 154.388 +                                    assert parenLineIndent >= 0;
 154.389 +                                    int textBegin = Utilities.getRowFirstNonWhite(doc, lineStart);
 154.390 +                                    assert textBegin != -1;
 154.391 +                                    // Indent to new indentation + text up to paren plus the paren itself
 154.392 +                                    int newIndent = parenLineIndent + (parenOffset-textBegin) + 1;
 154.393 +                                    computedIndents[i] = newIndent;
 154.394 +                                }
 154.395 +                            } catch (BadLocationException ble) {
 154.396 +                                Exceptions.printStackTrace(ble);
 154.397 +                            }
 154.398 +                        }
 154.399 +                    }
 154.400 +
 154.401 +                    // Process backwards so I don't have to worry about updating offsets affected by
 154.402 +                    // indentation changes
 154.403 +                    for (int i = offsets.size() - 1; i >= 0; i--) {
 154.404 +                        int indent = indentation.get(i);
 154.405 +                        if (indent == -1) {
 154.406 +                            // Leave line alone
 154.407 +                            continue;
 154.408 +                        }
 154.409 +                        int offset = offsets.get(i);
 154.410 +                        int computedIndent = computedIndents[i];
 154.411 +                        if (computedIndent < 0) {
 154.412 +                            computedIndent = 0;
 154.413 +                        }
 154.414 +
 154.415 +                        if (computedIndent != indent) {
 154.416 +                            try {
 154.417 +                                context.modifyIndent(offset, computedIndent);
 154.418 +                            } catch (BadLocationException ex) {
 154.419 +                                Exceptions.printStackTrace(ex);
 154.420 +                            }
 154.421 +                        }
 154.422 +                    }
 154.423 +                }
 154.424 +            });
 154.425 +        } catch (BadLocationException ble) {
 154.426 +            Exceptions.printStackTrace(ble);
 154.427 +        }
 154.428 +    }
 154.429 +
 154.430 +    private boolean isLinePrefix(BaseDocument doc, int offset) throws BadLocationException {
 154.431 +        return Utilities.getRowFirstNonWhite(doc, offset) == offset;
 154.432 +    }
 154.433 +
 154.434 +    private void cleanup(Document document, PythonParserResult info, int startOffset, int endOffset) {
 154.435 +        BaseDocument doc = (BaseDocument)document;
 154.436 +        final EditList edits = new EditList(doc);
 154.437 +        try {
 154.438 +            doc.readLock(); // For token hierarchy usage
 154.439 +
 154.440 +            TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(doc, startOffset);
 154.441 +            if (ts == null) {
 154.442 +                return;
 154.443 +            }
 154.444 +
 154.445 +            ts.move(startOffset);
 154.446 +
 154.447 +
 154.448 +
 154.449 +            // TODO:
 154.450 +            // Control whether I collapse spaces to a single space, or just ensure there is at least one
 154.451 +            // "None", "1", "At least 1", "Leave Alone"
 154.452 +
 154.453 +            // TODO: Insert and remove needed or unnecessary parentheses!
 154.454 +            // TODO: Alignment! Especially of trailing line comments on adjacent lines!
 154.455 +            // TODO: Collapse blank newlines!
 154.456 +            boolean addSpaceAroundOperators = true;
 154.457 +            boolean removeSpaceInsideParens = true; // also applies to braces and brackets
 154.458 +            boolean addSpaceAfterComma = true;
 154.459 +            //    boolean spaceArondParens = false;
 154.460 +            //    boolean spaceBeforeArgs = false; // before parentheses in a call
 154.461 +            boolean removeSpaceBeforeSep = true; // before comma, semicolon or colon
 154.462 +            //    boolean alignAssignments = false; // Only one space around assignments
 154.463 +            boolean removeSpaceInParamAssign = true; // Around assignment in parameter list, e.g.
 154.464 +            boolean collapseSpaces = true;
 154.465 +            //def complex(real, imag=0.0):
 154.466 +            //       return magic(r=real, i=imag)
 154.467 +            if (codeStyle != null) {
 154.468 +                addSpaceAroundOperators = codeStyle.addSpaceAroundOperators();
 154.469 +                removeSpaceInsideParens = codeStyle.removeSpaceInsideParens();
 154.470 +                addSpaceAfterComma = codeStyle.addSpaceAfterComma();
 154.471 +                removeSpaceBeforeSep = codeStyle.removeSpaceBeforeSep();
 154.472 +                removeSpaceInParamAssign = codeStyle.removeSpaceInParamAssign();
 154.473 +                collapseSpaces = codeStyle.collapseSpaces();
 154.474 +            }
 154.475 +
 154.476 +            // TODO - back up to the nearest function or class or beginning of the document to get the right
 154.477 +            // parenthesis balance.
 154.478 +            int parenBalance = 0;
 154.479 +
 154.480 +            Token<? extends PythonTokenId> prev = null;
 154.481 +            Token<? extends PythonTokenId> token = null;
 154.482 +            Token<? extends PythonTokenId> next = null;
 154.483 +            int tokenOffset = 0;
 154.484 +            int nextOffset = 0;
 154.485 +            int prevOffset = -1;
 154.486 +            if (ts.moveNext()) {
 154.487 +                token = ts.token();
 154.488 +                tokenOffset = ts.offset();
 154.489 +                if (ts.moveNext()) {
 154.490 +                    next = ts.token();
 154.491 +                    nextOffset = ts.offset();
 154.492 +                } else {
 154.493 +                    return;
 154.494 +                }
 154.495 +            }
 154.496 +            boolean prevRemoved = false;
 154.497 +            boolean tokenRemoved = false;
 154.498 +            boolean nextRemoved = false;
 154.499 +            while (token != null) {
 154.500 +                TokenId prevId = prev != null ? prev.id() : null;
 154.501 +                TokenId id = token.id();
 154.502 +                TokenId nextId = next != null ? next.id() : null;
 154.503 +
 154.504 +                if (id == PythonTokenId.LPAREN) {
 154.505 +                    parenBalance++;
 154.506 +                } else if (id == PythonTokenId.RPAREN) {
 154.507 +                    parenBalance--;
 154.508 +                }
 154.509 +
 154.510 +                if (removeSpaceInsideParens) {
 154.511 +                    if (id == PythonTokenId.LPAREN) {
 154.512 +                        if (nextId == PythonTokenId.WHITESPACE && !nextRemoved) {
 154.513 +                            edits.replace(nextOffset, next.length(), null, false, 0);
 154.514 +                            nextRemoved = true;
 154.515 +                        }
 154.516 +                    } else if (id == PythonTokenId.RPAREN) {
 154.517 +                        if (prevId == PythonTokenId.WHITESPACE && !prevRemoved && !isLinePrefix(doc, tokenOffset)) {
 154.518 +                            // I don't remove space in front of paren's at the beginning of the line; these might have
 154.519 +                            // been aligned with indented content above
 154.520 +                            edits.replace(prevOffset, prev.length(), null, false, 0);
 154.521 +                            prevRemoved = true;
 154.522 +                        }
 154.523 +                    } else if (id == PythonTokenId.LBRACKET) {
 154.524 +                        if (nextId == PythonTokenId.WHITESPACE && !nextRemoved) {
 154.525 +                            edits.replace(nextOffset, next.length(), null, false, 0);
 154.526 +                            nextRemoved = true;
 154.527 +                        }
 154.528 +                    } else if (id == PythonTokenId.RBRACKET) {
 154.529 +                        if (prevId == PythonTokenId.WHITESPACE && !prevRemoved && !isLinePrefix(doc, tokenOffset)) {
 154.530 +                            edits.replace(prevOffset, prev.length(), null, false, 0);
 154.531 +                            prevRemoved = true;
 154.532 +                        }
 154.533 +                    } else if (id == PythonTokenId.LBRACE) {
 154.534 +                        if (nextId == PythonTokenId.WHITESPACE && !nextRemoved) {
 154.535 +                            edits.replace(nextOffset, next.length(), null, false, 0);
 154.536 +                            nextRemoved = true;
 154.537 +                        }
 154.538 +                    } else if (id == PythonTokenId.RBRACE) {
 154.539 +                        if (prevId == PythonTokenId.WHITESPACE && !prevRemoved && !isLinePrefix(doc, tokenOffset)) {
 154.540 +                            edits.replace(prevOffset, prev.length(), null, false, 0);
 154.541 +                            prevRemoved = true;
 154.542 +                        }
 154.543 +                    }
 154.544 +                }
 154.545 +
 154.546 +                if (addSpaceAfterComma) {
 154.547 +                    if (id == PythonTokenId.COMMA) {
 154.548 +                        if (collapseSpaces && nextId == PythonTokenId.WHITESPACE && next.length() > 1) {
 154.549 +                            edits.replace(nextOffset, next.length() - 1, null, false, 1); // NOI18N
 154.550 +                        } else if (next == null ||
 154.551 +                                (nextId != PythonTokenId.WHITESPACE && nextId != PythonTokenId.NEWLINE)) {
 154.552 +                            edits.replace(nextOffset, 0, " ", false, 1); // NOI18N
 154.553 +                        }
 154.554 +                    }
 154.555 +                }
 154.556 +
 154.557 +                if (removeSpaceBeforeSep &&
 154.558 +                        (id == PythonTokenId.COMMA || id == PythonTokenId.COLON ||
 154.559 +                        (id == PythonTokenId.ANY_OPERATOR && TokenUtilities.equals(token.text(), ";"))) && // NOI18N
 154.560 +                        prevId == PythonTokenId.WHITESPACE && !prevRemoved && !isLinePrefix(doc, tokenOffset)) {
 154.561 +                    edits.replace(prevOffset, prev.length(), null, false, 2);
 154.562 +                    prevRemoved = true;
 154.563 +                }
 154.564 +
 154.565 +                if (addSpaceAroundOperators && id == PythonTokenId.ANY_OPERATOR) {
 154.566 +                    CharSequence seq = token.text();
 154.567 +
 154.568 +                    // These aren't binary, and ; isn't really an operator and has its own setting
 154.569 +                    if (!(TokenUtilities.equals(seq, "@") || // NOI18N
 154.570 +                            TokenUtilities.equals(seq, "`") || // NOI18N
 154.571 +                            TokenUtilities.equals(seq, ";"))) { // NOI18N
 154.572 +
 154.573 +                        boolean insertSpace = true;
 154.574 +                        if (removeSpaceInParamAssign && TokenUtilities.equals(seq, "=")) { // NOI18N
 154.575 +                            // Special handling: keyword arguments should typically NOT
 154.576 +                            // have space inserted
 154.577 +                            if (parenBalance > 0) {
 154.578 +                                insertSpace = false;
 154.579 +                                // Remove spaces around the =
 154.580 +                                if (prevId == PythonTokenId.WHITESPACE && !prevRemoved) {
 154.581 +                                    edits.replace(prevOffset, prev.length(), null, false, 5); // NOI18N
 154.582 +                                    prevRemoved = true;
 154.583 +                                }
 154.584 +                                if (nextId == PythonTokenId.WHITESPACE && !nextRemoved) {
 154.585 +                                    edits.replace(nextOffset, next.length(), null, false, 6); // NOI18N
 154.586 +                                    nextRemoved = true;
 154.587 +                                }
 154.588 +                            }
 154.589 +                        }
 154.590 +
 154.591 +                        if (insertSpace && TokenUtilities.equals(seq, "-")/* && (nextId == PythonTokenId.FLOAT_LITERAL || nextId == PythonTokenId.INT_LITERAL)*/) {
 154.592 +                            // Leave -'s alone for now. The code is a little unclear on the difference between
 154.593 +                            //  x-1 and =-1 etc. For numbers (floating and integer) the minus isn't part of the lexical token for the number;
 154.594 +                            // it's a separate operator. However, it's tricky to tell this apart from the binary subtraction, since it depends
 154.595 +                            // on what came before. For now play it safe an leave these alone.
 154.596 +                            // TODO - implement this properly.
 154.597 +                            insertSpace = false;
 154.598 +                        }
 154.599 +
 154.600 +                        if (insertSpace && TokenUtilities.equals(seq, "*")) { // NOI18N
 154.601 +                            // "*" in (*foo) doesn't mean multiplication; it's not a binary operator here,
 154.602 +                            // it's many args.
 154.603 +                            if (prevId == PythonTokenId.COMMA || prevId == PythonTokenId.LPAREN) {
 154.604 +                                insertSpace = false;
 154.605 +                            }
 154.606 +                        }
 154.607 +
 154.608 +                        if (insertSpace) {
 154.609 +                            // Ensure that we have space on both sides
 154.610 +                            if (collapseSpaces && prevId == PythonTokenId.WHITESPACE && next.length() > 1 &&
 154.611 +                                    !isLinePrefix(doc, tokenOffset)) {
 154.612 +                                edits.replace(prevOffset, prev.length() - 1, null, false, 1); // NOI18N
 154.613 +                            } else if (prevId != PythonTokenId.WHITESPACE) {
 154.614 +                                edits.replace(tokenOffset, 0, " ", false, 3); // NOI18N
 154.615 +                            }
 154.616 +
 154.617 +                            if (collapseSpaces && nextId == PythonTokenId.WHITESPACE && next.length() > 1) {
 154.618 +                                edits.replace(nextOffset, next.length() - 1, null, false, 1); // NOI18N
 154.619 +                            } else if (nextId != PythonTokenId.WHITESPACE && nextId != PythonTokenId.NEWLINE) {
 154.620 +                                edits.replace(nextOffset, 0, " ", false, 4); // NOI18N
 154.621 +                            }
 154.622 +                        }
 154.623 +                    }
 154.624 +                }
 154.625 +
 154.626 +                if (tokenOffset + token.length() >= endOffset) {
 154.627 +                    break;
 154.628 +                }
 154.629 +
 154.630 +                prevRemoved = tokenRemoved;
 154.631 +                tokenRemoved = nextRemoved;
 154.632 +                nextRemoved = false;
 154.633 +
 154.634 +                prev = token;
 154.635 +                token = next;
 154.636 +                prevOffset = tokenOffset;
 154.637 +                tokenOffset = nextOffset;
 154.638 +                if (ts.moveNext()) {
 154.639 +                    next = ts.token();
 154.640 +                    nextOffset = ts.offset();
 154.641 +                } else {
 154.642 +                    next = null;
 154.643 +                }
 154.644 +            }
 154.645 +        } catch (BadLocationException ble) {
 154.646 +            Exceptions.printStackTrace(ble);
 154.647 +        } finally {
 154.648 +            doc.readUnlock();
 154.649 +        }
 154.650 +
 154.651 +        doc.runAtomic(new Runnable() {
 154.652 +            @Override
 154.653 +            public void run() {
 154.654 +                edits.apply();
 154.655 +            }
 154.656 +        });
 154.657 +    }
 154.658 +}
   155.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   155.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonIndex.java	Mon Sep 21 13:01:16 2015 +0200
   155.3 @@ -0,0 +1,1470 @@
   155.4 +/*
   155.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   155.6 + *
   155.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   155.8 + *
   155.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  155.10 + * Other names may be trademarks of their respective owners.
  155.11 + *
  155.12 + * The contents of this file are subject to the terms of either the GNU
  155.13 + * General Public License Version 2 only ("GPL") or the Common
  155.14 + * Development and Distribution License("CDDL") (collectively, the
  155.15 + * "License"). You may not use this file except in compliance with the
  155.16 + * License. You can obtain a copy of the License at
  155.17 + * http://www.netbeans.org/cddl-gplv2.html
  155.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  155.19 + * specific language governing permissions and limitations under the
  155.20 + * License.  When distributing the software, include this License Header
  155.21 + * Notice in each file and include the License file at
  155.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  155.23 + * particular file as subject to the "Classpath" exception as provided
  155.24 + * by Oracle in the GPL Version 2 section of the License file that
  155.25 + * accompanied this code. If applicable, add the following below the
  155.26 + * License Header, with the fields enclosed by brackets [] replaced by
  155.27 + * your own identifying information:
  155.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  155.29 + *
  155.30 + * Contributor(s):
  155.31 + *
  155.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  155.33 + */
  155.34 +package org.netbeans.modules.python.source;
  155.35 +
  155.36 +import java.io.File;
  155.37 +import java.io.IOException;
  155.38 +import java.net.MalformedURLException;
  155.39 +import java.net.URL;
  155.40 +import java.util.ArrayList;
  155.41 +import java.util.Arrays;
  155.42 +import java.util.Collection;
  155.43 +import java.util.Collections;
  155.44 +import java.util.EnumSet;
  155.45 +import java.util.HashMap;
  155.46 +import java.util.HashSet;
  155.47 +import java.util.Iterator;
  155.48 +import java.util.List;
  155.49 +import java.util.Map;
  155.50 +import java.util.Set;
  155.51 +import java.util.WeakHashMap;
  155.52 +import java.util.logging.Level;
  155.53 +import java.util.logging.Logger;
  155.54 +import org.netbeans.api.project.Project;
  155.55 +import org.netbeans.modules.csl.api.ElementKind;
  155.56 +import org.netbeans.modules.parsing.spi.indexing.PathRecognizer;
  155.57 +import org.netbeans.modules.parsing.spi.indexing.support.IndexResult;
  155.58 +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
  155.59 +import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.CAMEL_CASE;
  155.60 +import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.CASE_INSENSITIVE_PREFIX;
  155.61 +import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.CASE_INSENSITIVE_REGEXP;
  155.62 +import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.PREFIX;
  155.63 +import static org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind.REGEXP;
  155.64 +import org.netbeans.modules.python.source.elements.IndexedElement;
  155.65 +import org.netbeans.modules.python.api.PythonPlatform;
  155.66 +import org.netbeans.modules.python.api.PythonPlatformManager;
  155.67 +import org.netbeans.modules.python.source.impl.QuerySupportFactory;
  155.68 +import org.netbeans.modules.python.source.elements.IndexedPackage;
  155.69 +import org.openide.filesystems.FileObject;
  155.70 +import org.openide.filesystems.FileStateInvalidException;
  155.71 +import org.openide.filesystems.URLMapper;
  155.72 +import org.openide.modules.InstalledFileLocator;
  155.73 +import org.openide.util.Exceptions;
  155.74 +import org.openide.util.Lookup;
  155.75 +import org.python.antlr.ast.Import;
  155.76 +import org.python.antlr.ast.ImportFrom;
  155.77 +import org.python.antlr.ast.alias;
  155.78 +
  155.79 +/**
  155.80 + *
  155.81 + * @author alley
  155.82 + * @author Tor Norbye
  155.83 + */
  155.84 +public class PythonIndex {
  155.85 +//    public static final Set<SearchScope> ALL_SCOPE = EnumSet.allOf(SearchScope.class);
  155.86 +//    public static final Set<SearchScope> SOURCE_SCOPE = EnumSet.of(SearchScope.SOURCE);
  155.87 +    static final String CLUSTER_URL = "cluster:"; // NOI18N
  155.88 +    static final String PYTHONHOME_URL = "python:"; // NOI18N
  155.89 +    private static final String STUB_MISSING = "stub_missing"; // NOI18N
  155.90 +
  155.91 +    // The "functions" module is always imported by the interpreter, and ditto
  155.92 +    // for exceptions, constants, etc.
  155.93 +    public static Set<String> BUILTIN_MODULES = new HashSet<>();
  155.94 +
  155.95 +
  155.96 +    private static final Logger LOG = Logger.getLogger(PythonIndex.class.getName());
  155.97 +    public static final String OBJECT = "object"; // NOI18N
  155.98 +    static Map<String, Set<String>> wildcardImports = new HashMap<>();
  155.99 +    static Set<String> systemModules;
 155.100 +    // TODO - make weak?
 155.101 +    static Set<String> availableClasses;
 155.102 +    private static String clusterUrl = null;
 155.103 +    static {
 155.104 +        //BUILTIN_MODULES.add("objects"); // NOI18N -- just links to the others
 155.105 +        BUILTIN_MODULES.add("stdtypes"); // NOI18N
 155.106 +        //BUILTIN_MODULES.add("types"); // NOI18N
 155.107 +        BUILTIN_MODULES.add("exceptions"); // NOI18N
 155.108 +        BUILTIN_MODULES.add("functions"); // NOI18N
 155.109 +        BUILTIN_MODULES.add("constants"); // NOI18N
 155.110 +    }
 155.111 +
 155.112 +    public static PythonIndex get(Collection<FileObject> roots) {
 155.113 +        // XXX no cache - is it needed?
 155.114 +        LOG.log(Level.FINE, "PythonIndex for roots: {0}", roots); //NOI18N
 155.115 +        return new PythonIndex(QuerySupportFactory.getQuerySupport(roots), false);
 155.116 +    }
 155.117 +    
 155.118 +    public static PythonIndex get(Project project) {
 155.119 +        Set<String> sourceIds = new HashSet<>();
 155.120 +        Set<String> libraryIds = new HashSet<>();
 155.121 +        Collection<? extends PathRecognizer> lookupAll = Lookup.getDefault().lookupAll(PathRecognizer.class);
 155.122 +        for (PathRecognizer pathRecognizer : lookupAll) {
 155.123 +            Set<String> source = pathRecognizer.getSourcePathIds();
 155.124 +            if (source != null) {
 155.125 +                sourceIds.addAll(source);
 155.126 +            }
 155.127 +            Set<String> library = pathRecognizer.getLibraryPathIds();
 155.128 +            if (library != null) {
 155.129 +                libraryIds.addAll(library);
 155.130 +            }
 155.131 +        }
 155.132 +
 155.133 +        final Collection<FileObject> findRoots = QuerySupport.findRoots(project,
 155.134 +                sourceIds,
 155.135 +                libraryIds,
 155.136 +                Collections.<String>emptySet());
 155.137 +        return PythonIndex.get(findRoots);
 155.138 +    }
 155.139 +    
 155.140 +    private static final WeakHashMap<FileObject, PythonIndex> INDEX_CACHE = new WeakHashMap<>();
 155.141 +    public static PythonIndex get(FileObject fo) {
 155.142 +        PythonIndex index = INDEX_CACHE.get(fo);
 155.143 +        if (index == null) {
 155.144 +            LOG.log(Level.FINE, "Creating PythonIndex for FileObject: {0}", fo); //NOI18N
 155.145 +            index = new PythonIndex(QuerySupportFactory.getQuerySupport(fo), true);
 155.146 +            INDEX_CACHE.put(fo, index);
 155.147 +        }
 155.148 +        return index;
 155.149 +    }
 155.150 +
 155.151 +    public static boolean isBuiltinModule(String module) {
 155.152 +        return BUILTIN_MODULES.contains(module) || STUB_MISSING.equals(module);
 155.153 +    }
 155.154 +
 155.155 +    // For testing only
 155.156 +    public static void setClusterUrl(String url) {
 155.157 +        clusterUrl = url;
 155.158 +    }
 155.159 +
 155.160 +    static String getPreindexUrl(String url) {
 155.161 +        // TODO - look up the correct platform to use!
 155.162 +        final PythonPlatformManager manager = PythonPlatformManager.getInstance();
 155.163 +        final String platformName = manager.getDefaultPlatform();
 155.164 +        PythonPlatform platform = manager.getPlatform(platformName);
 155.165 +        if (platform != null) {
 155.166 +            String s = platform.getHomeUrl();
 155.167 +            if (s != null) {
 155.168 +                if (url.startsWith(s)) {
 155.169 +                    url = PYTHONHOME_URL + url.substring(s.length());
 155.170 +                    return url;
 155.171 +                }
 155.172 +            }
 155.173 +        }
 155.174 +        
 155.175 +        String s = getClusterUrl();
 155.176 +        
 155.177 +        if (url.startsWith(s)) {
 155.178 +            return CLUSTER_URL + url.substring(s.length());
 155.179 +        }
 155.180 +        
 155.181 +        if (url.startsWith("jar:file:")) { // NOI18N
 155.182 +            String sub = url.substring(4);
 155.183 +            if (sub.startsWith(s)) {
 155.184 +                return CLUSTER_URL + sub.substring(s.length());
 155.185 +            }
 155.186 +        }
 155.187 +        
 155.188 +        return url;
 155.189 +    }
 155.190 +
 155.191 +/** Get the FileObject corresponding to a URL returned from the index */
 155.192 +    public static FileObject getFileObject(String url) {
 155.193 +        return getFileObject(url, null);
 155.194 +    }
 155.195 +
 155.196 +    public static FileObject getFileObject(String url, FileObject context) {
 155.197 +        try {
 155.198 +            if (url.startsWith(PYTHONHOME_URL)) {
 155.199 +                Iterator<String> it = null;
 155.200 +                
 155.201 +                // TODO - look up the right platform for the given project
 155.202 +                //if (context != null) {
 155.203 +                //    Project project = FileOwnerQuery.getOwner(context);
 155.204 +                //    if (project != null) {
 155.205 +                //        PythonPlatform platform = PythonPlatform.platformFor(project);
 155.206 +                //        if (platform != null) {
 155.207 +                //            it = Collections.singleton(platform).iterator();
 155.208 +                //        }
 155.209 +                //    }
 155.210 +                //}
 155.211 +                
 155.212 +                PythonPlatformManager manager = PythonPlatformManager.getInstance();
 155.213 +                if (it == null) {
 155.214 +                    it = manager.getPlatformList().iterator();
 155.215 +                }
 155.216 +                while (it.hasNext()) {
 155.217 +                    String name = it.next();
 155.218 +                    PythonPlatform platform = manager.getPlatform(name);
 155.219 +                    if (platform != null) {
 155.220 +                        String u = platform.getHomeUrl();
 155.221 +                        if (u != null) {
 155.222 +                            try {
 155.223 +                                u = u + url.substring(PYTHONHOME_URL.length());
 155.224 +                                FileObject fo = URLMapper.findFileObject(new URL(u));
 155.225 +                                if (fo != null) {
 155.226 +                                    return fo;
 155.227 +                                }
 155.228 +                            } catch (MalformedURLException mue) {
 155.229 +                                Exceptions.printStackTrace(mue);
 155.230 +                            }
 155.231 +                        }
 155.232 +                    }
 155.233 +                }
 155.234 +                
 155.235 +                return null;
 155.236 +            } else if (url.startsWith(CLUSTER_URL)) {
 155.237 +                url = getClusterUrl() + url.substring(CLUSTER_URL.length()); // NOI18N
 155.238 +                if (url.contains(".egg!/")) { // NOI18N
 155.239 +                    url = "jar:" + url; // NOI18N
 155.240 +                }
 155.241 +            }
 155.242 +            
 155.243 +            return URLMapper.findFileObject(new URL(url));
 155.244 +        } catch (MalformedURLException ex) {
 155.245 +            Exceptions.printStackTrace(ex);
 155.246 +        }
 155.247 +        
 155.248 +        return null;
 155.249 +    }
 155.250 +    
 155.251 +    static String getClusterUrl() {
 155.252 +        if (clusterUrl == null) {
 155.253 +            File f =
 155.254 +                    InstalledFileLocator.getDefault().locate("modules/org-netbeans-modules-python-editor.jar", null, false); // NOI18N
 155.255 +            
 155.256 +            if (f == null) {
 155.257 +                throw new RuntimeException("Can't find cluster");
 155.258 +            }
 155.259 +            
 155.260 +            f = new File(f.getParentFile().getParentFile().getAbsolutePath());
 155.261 +            
 155.262 +            try {
 155.263 +                f = f.getCanonicalFile();
 155.264 +                clusterUrl = f.toURI().toURL().toExternalForm();
 155.265 +            } catch (IOException ioe) {
 155.266 +                Exceptions.printStackTrace(ioe);
 155.267 +            }
 155.268 +        }
 155.269 +
 155.270 +        return clusterUrl;
 155.271 +    }
 155.272 +
 155.273 +    private final QuerySupport index;
 155.274 +    private final boolean updateCache;
 155.275 +    
 155.276 +    /** Creates a new instance of PythonIndex */
 155.277 +    private PythonIndex(QuerySupport index, boolean updateCache) {
 155.278 +        this.index = index;
 155.279 +        this.updateCache = updateCache;
 155.280 +    }
 155.281 +    
 155.282 +    private boolean search(String fieldName, String fieldValue, QuerySupport.Kind kind, Set<? super IndexResult> result, final String... fieldsToLoad) {
 155.283 +        try {
 155.284 +            result.addAll(index.query(fieldName, fieldValue, kind, fieldsToLoad));
 155.285 +            return true;
 155.286 +        } catch (IOException ioe) {
 155.287 +            Exceptions.printStackTrace(ioe);
 155.288 +
 155.289 +            return false;
 155.290 +        } catch (UnsupportedOperationException iuoe) {
 155.291 +            return false;
 155.292 +        }
 155.293 +    }
 155.294 +
 155.295 +    public Set<IndexedElement> getModules(String name, final QuerySupport.Kind kind) {
 155.296 +        final Set<IndexResult> result = new HashSet<>();
 155.297 +
 155.298 +        //        if (!isValid()) {
 155.299 +        //            LOGGER.fine(String.format("LuceneIndex[%s] is invalid!\n", this.toString()));
 155.300 +        //            return;
 155.301 +        //        }
 155.302 +
 155.303 +        // TODO - handle case insensitive searches etc?
 155.304 +        String field = PythonIndexer.FIELD_MODULE_NAME;
 155.305 +
 155.306 +        search(field, name, kind, result, PythonIndexer.FIELD_MODULE_ATTR_NAME, PythonIndexer.FIELD_MODULE_NAME);
 155.307 +
 155.308 +        final Set<IndexedElement> modules = new HashSet<>();
 155.309 +
 155.310 +        for (IndexResult map : result) {
 155.311 +            URL url = map.getUrl();
 155.312 +            if (url == null) {
 155.313 +                continue;
 155.314 +            }
 155.315 +            String path = url.toExternalForm();
 155.316 +            String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
 155.317 +            if (STUB_MISSING.equals(module)) {
 155.318 +                continue;
 155.319 +            }
 155.320 +
 155.321 +            IndexedElement element = new IndexedElement(module, ElementKind.MODULE, path, null, null, null);
 155.322 +
 155.323 +            String attrs = map.getValue(PythonIndexer.FIELD_MODULE_ATTR_NAME);
 155.324 +            if (attrs != null && attrs.indexOf('D') != -1) {
 155.325 +                element.setFlags(IndexedElement.DEPRECATED);
 155.326 +            }
 155.327 +
 155.328 +            String rhs = path.substring(path.lastIndexOf('/') + 1);
 155.329 +            element.setRhs(rhs);
 155.330 +            modules.add(element);
 155.331 +        }
 155.332 +
 155.333 +        return modules;
 155.334 +    }
 155.335 +
 155.336 +    public Set<IndexedPackage> getPackages(String name, final QuerySupport.Kind kind) {
 155.337 +        final Set<IndexResult> result = new HashSet<>();
 155.338 +
 155.339 +        String field = PythonIndexer.FIELD_MODULE_NAME;
 155.340 +        search(field, name, kind, result, PythonIndexer.FIELD_MODULE_NAME);
 155.341 +
 155.342 +        final Set<IndexedPackage> packages = new HashSet<>();
 155.343 +
 155.344 +        for (IndexResult map : result) {
 155.345 +            String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
 155.346 +
 155.347 +            String pkgName = null;
 155.348 +            String pkg = null;
 155.349 +
 155.350 +            int nextNextDot = -1;
 155.351 +            int lastDot = module.lastIndexOf('.');
 155.352 +            int nameLength = name.length();
 155.353 +            if (nameLength < lastDot) {
 155.354 +                int nextDot = module.indexOf('.', nameLength);
 155.355 +                if (nextDot != -1) {
 155.356 +                    pkg = module.substring(0, nextDot);
 155.357 +                    nextNextDot = module.indexOf('.', nextDot + 1);
 155.358 +                    int start = module.lastIndexOf('.', name.length());
 155.359 +                    if (start == -1) {
 155.360 +                        start = 0;
 155.361 +                    } else {
 155.362 +                        start++;
 155.363 +                    }
 155.364 +                    pkgName = module.substring(start, nextDot);
 155.365 +                }
 155.366 +            } else if (lastDot != -1) {
 155.367 +                pkgName = module.substring(lastDot + 1);
 155.368 +                pkg = module;
 155.369 +            }
 155.370 +
 155.371 +            if (pkgName != null) {
 155.372 +                String url = map.getUrl().toExternalForm();
 155.373 +                IndexedPackage element = new IndexedPackage(pkgName, pkg, url, nextNextDot != -1);
 155.374 +                element.setRhs("");
 155.375 +                packages.add(element);
 155.376 +            }
 155.377 +        }
 155.378 +
 155.379 +        return packages;
 155.380 +    }
 155.381 +    
 155.382 +    public Set<IndexedElement> getClasses(String name, final QuerySupport.Kind kind, PythonParserResult context, boolean includeDuplicates) {
 155.383 +        final Set<IndexResult> result = new HashSet<>();
 155.384 +
 155.385 +        //        if (!isValid()) {
 155.386 +        //            LOGGER.fine(String.format("LuceneIndex[%s] is invalid!\n", this.toString()));
 155.387 +        //            return;
 155.388 +        //        }
 155.389 +        String field;
 155.390 +
 155.391 +        switch (kind) {
 155.392 +            case EXACT:
 155.393 +            case PREFIX:
 155.394 +            case CAMEL_CASE:
 155.395 +            case REGEXP:
 155.396 +                field = PythonIndexer.FIELD_CLASS_NAME;
 155.397 +                
 155.398 +                break;
 155.399 +                
 155.400 +            case CASE_INSENSITIVE_PREFIX:
 155.401 +            case CASE_INSENSITIVE_REGEXP:
 155.402 +            case CASE_INSENSITIVE_CAMEL_CASE:
 155.403 +                field = PythonIndexer.FIELD_CASE_INSENSITIVE_CLASS_NAME;
 155.404 +                
 155.405 +                break;
 155.406 +                
 155.407 +            default:
 155.408 +                throw new UnsupportedOperationException(kind.toString());
 155.409 +        }
 155.410 +
 155.411 +        search(field, name, kind, result, PythonIndexer.FIELD_IN, PythonIndexer.FIELD_CLASS_ATTR_NAME, PythonIndexer.FIELD_CLASS_NAME);
 155.412 +
 155.413 +        Set<String> uniqueClasses = includeDuplicates ? null : new HashSet<String>();
 155.414 +
 155.415 +        final Set<IndexedElement> classes = new HashSet<>();
 155.416 +
 155.417 +        for (IndexResult map : result) {
 155.418 +            String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
 155.419 +            if (clz == null) {
 155.420 +                // A module without classes
 155.421 +                continue;
 155.422 +            }
 155.423 +            String url = map.getUrl().toExternalForm();
 155.424 +            String module = map.getValue(PythonIndexer.FIELD_IN);
 155.425 +            boolean isBuiltin = isBuiltinModule(module);
 155.426 +
 155.427 +            String fqn = clz; // No further namespaces in Python, right?
 155.428 +            if (!includeDuplicates) {
 155.429 +                if (!uniqueClasses.contains(fqn)) { // use a map to point right to the class
 155.430 +                    uniqueClasses.add(fqn);
 155.431 +                    IndexedElement element = new IndexedElement(clz, ElementKind.CLASS, url, module, null, null);
 155.432 +                    if (isBuiltin) {
 155.433 +                        element.setRhs("<i>builtin</i>");
 155.434 +                    }
 155.435 +                    String attrs = map.getValue(PythonIndexer.FIELD_CLASS_ATTR_NAME);
 155.436 +                    if (attrs != null) {
 155.437 +                        int flags = IndexedElement.decode(attrs, 0, 0);
 155.438 +                        element.setFlags(flags);
 155.439 +                    }
 155.440 +                    element.setInherited(true);
 155.441 +
 155.442 +                    classes.add(element);
 155.443 +                } // else: Possibly pick the best version... based on which items have documentation attributes etc.
 155.444 +            } else {
 155.445 +                IndexedElement element = new IndexedElement(clz, ElementKind.CLASS, url, module, null, null);
 155.446 +                classes.add(element);
 155.447 +            }
 155.448 +        }
 155.449 +
 155.450 +        return classes;
 155.451 +    }
 155.452 +
 155.453 +//    /** Return the most distant method in the hierarchy that is overriding the given method, or null
 155.454 +//     * @todo Make this method actually compute most distant ancestor
 155.455 +//     * @todo Use arglist arity comparison to reject methods that are not overrides...
 155.456 +//     */
 155.457 +//    public IndexedMethod getOverridingMethod(String className, String methodName) {
 155.458 +//        Set<IndexedElement> methods = getInheritedElements(className, methodName, QuerySupport.Kind.EXACT);
 155.459 +//
 155.460 +//        // TODO - this is only returning ONE match, not the most distant one. I really need to
 155.461 +//        // produce a PythonIndex method for this which can walk in there and do a decent job!
 155.462 +//
 155.463 +//        for (IndexedElement method : methods) {
 155.464 +//            if (method.getKind() == ElementKind.METHOD || method.getKind() == ElementKind.CONSTRUCTOR) {
 155.465 +//                // getInheritedMethods may return methods ON fqn itself
 155.466 +//                if (!method.getIn().equals(className)) {
 155.467 +//                    return (IndexedMethod)method;
 155.468 +//                }
 155.469 +//            }
 155.470 +//        }
 155.471 +//
 155.472 +//        return null;
 155.473 +//    }
 155.474 +    /** Get the super implementation of the given method */
 155.475 +    public Set<IndexedElement> getOverridingMethods(String className, String function) {
 155.476 +        Set<IndexedElement> methods = getInheritedElements(className, function, QuerySupport.Kind.EXACT, true);
 155.477 +
 155.478 +        // TODO - remove all methods that are in the same file
 155.479 +        if (methods.size() > 0) {
 155.480 +            Set<IndexedElement> result = new HashSet<>(methods.size());
 155.481 +            for (IndexedElement element : methods) {
 155.482 +                if (!className.equals(element.getClz())) {
 155.483 +                    result.add(element);
 155.484 +                }
 155.485 +            }
 155.486 +            methods = result;
 155.487 +        }
 155.488 +
 155.489 +        return methods;
 155.490 +//        // TODO - this is only returning ONE match, not the most distant one. I really need to
 155.491 +//        // produce a PythonIndex method for this which can walk in there and do a decent job!
 155.492 +//
 155.493 +//        for (IndexedElement method : methods) {
 155.494 +//            if (method.getKind() == ElementKind.METHOD || method.getKind() == ElementKind.CONSTRUCTOR) {
 155.495 +//                // getInheritedMethods may return methods ON fqn itself
 155.496 +//                if (!method.getIn().equals(className)) {
 155.497 +//                    return (IndexedMethod)method;
 155.498 +//                }
 155.499 +//            }
 155.500 +//        }
 155.501 +//
 155.502 +//        return null;
 155.503 +    }
 155.504 +
 155.505 +    /** Get the super class of the given class */
 155.506 +    public Set<IndexedElement> getSuperClasses(String className) {
 155.507 +        final Set<IndexResult> result = new HashSet<>();
 155.508 +
 155.509 +        search(PythonIndexer.FIELD_CLASS_NAME, className, QuerySupport.Kind.EXACT, result, PythonIndexer.FIELD_EXTENDS_NAME, PythonIndexer.FIELD_CLASS_NAME);
 155.510 +
 155.511 +        Set<String> classNames = new HashSet<>();
 155.512 +        for (IndexResult map : result) {
 155.513 +            String[] extendsClasses = map.getValues(PythonIndexer.FIELD_EXTENDS_NAME);
 155.514 +            if (extendsClasses != null && extendsClasses.length > 0) {
 155.515 +                for (String clzName : extendsClasses) {
 155.516 +                    classNames.add(clzName);
 155.517 +                }
 155.518 +            }
 155.519 +        }
 155.520 +
 155.521 +        String[] terms = { PythonIndexer.FIELD_IN, PythonIndexer.FIELD_CLASS_NAME };
 155.522 +
 155.523 +        Set<IndexedElement> superClasses = new HashSet<>();
 155.524 +
 155.525 +        for (String superClz : classNames) {
 155.526 +            result.clear();
 155.527 +            search(PythonIndexer.FIELD_CLASS_NAME, superClz, QuerySupport.Kind.EXACT, result, terms);
 155.528 +            for (IndexResult map : result) {
 155.529 +                assert superClz.equals(map.getValue(PythonIndexer.FIELD_CLASS_NAME));
 155.530 +                String url = map.getUrl().toExternalForm();
 155.531 +                String module = map.getValue(PythonIndexer.FIELD_IN);
 155.532 +                IndexedElement clz = new IndexedElement(superClz, ElementKind.CLASS, url, module, null, null);
 155.533 +                superClasses.add(clz);
 155.534 +            }
 155.535 +        }
 155.536 +
 155.537 +        return superClasses;
 155.538 +    }
 155.539 +
 155.540 +    /**
 155.541 +     * Get the set of inherited (through super classes and mixins) for the given fully qualified class name.
 155.542 +     * @param classFqn FQN: module1::module2::moduleN::class
 155.543 +     * @param prefix If kind is QuerySupport.Kind.PREFIX/CASE_INSENSITIVE_PREFIX, a prefix to filter methods by. Else,
 155.544 +     *    if kind is QuerySupport.Kind.EXACT filter methods by the exact name.
 155.545 +     * @param kind Whether the prefix field should be taken as a prefix or a whole name
 155.546 +     */
 155.547 +    public Set<IndexedElement> getInheritedElements(String classFqn, String prefix, QuerySupport.Kind kind) {
 155.548 +        return getInheritedElements(classFqn, prefix, kind, false);
 155.549 +    }
 155.550 +
 155.551 +    public Set<IndexedElement> getInheritedElements(String classFqn, String prefix, QuerySupport.Kind kind, boolean includeOverrides) {
 155.552 +        boolean haveRedirected = false;
 155.553 +
 155.554 +        if (classFqn == null) {
 155.555 +            classFqn = OBJECT;
 155.556 +            haveRedirected = true;
 155.557 +        }
 155.558 +
 155.559 +        //String field = PythonIndexer.FIELD_FQN_NAME;
 155.560 +        Set<IndexedElement> elements = new HashSet<>();
 155.561 +        Set<String> scannedClasses = new HashSet<>();
 155.562 +        Set<String> seenSignatures = new HashSet<>();
 155.563 +
 155.564 +        if (prefix == null) {
 155.565 +            prefix = "";
 155.566 +        }
 155.567 +
 155.568 +//        String searchUrl = null;
 155.569 +//        if (context != null) {
 155.570 +//            try {
 155.571 +//                searchUrl = context.getFile().getFileObject().getURL().toExternalForm();
 155.572 +//            } catch (FileStateInvalidException ex) {
 155.573 +//                Exceptions.printStackTrace(ex);
 155.574 +//            }
 155.575 +//        }
 155.576 +
 155.577 +        addMethodsFromClass(prefix, kind, classFqn, elements, seenSignatures, scannedClasses,
 155.578 +                haveRedirected, false, includeOverrides, 0);
 155.579 +
 155.580 +        return elements;
 155.581 +    }
 155.582 +
 155.583 +    /** Return whether the specific class referenced (classFqn) was found or not. This is
 155.584 +     * not the same as returning whether any classes were added since it may add
 155.585 +     * additional methods from parents (Object/Class).
 155.586 +     */
 155.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) {
 155.588 +        // Prevent problems with circular includes or redundant includes
 155.589 +        if (scannedClasses.contains(classFqn)) {
 155.590 +            return false;
 155.591 +        }
 155.592 +
 155.593 +        scannedClasses.add(classFqn);
 155.594 +
 155.595 +        String searchField = PythonIndexer.FIELD_CLASS_NAME;
 155.596 +
 155.597 +        Set<IndexResult> result = new HashSet<>();
 155.598 +
 155.599 +        String[] terms = {PythonIndexer.FIELD_IN,
 155.600 +                          PythonIndexer.FIELD_EXTENDS_NAME,
 155.601 +                          PythonIndexer.FIELD_MEMBER,
 155.602 +                          PythonIndexer.FIELD_CLASS_NAME};
 155.603 +        
 155.604 +        
 155.605 +        search(searchField, classFqn, QuerySupport.Kind.EXACT, result, terms);
 155.606 +
 155.607 +        boolean foundIt = result.size() > 0;
 155.608 +
 155.609 +        // If this is a bogus class entry (no search rsults) don't continue
 155.610 +        if (!foundIt) {
 155.611 +            return foundIt;
 155.612 +        }
 155.613 +
 155.614 +        List<String> extendsClasses = null;
 155.615 +
 155.616 +        String classIn = null;
 155.617 +        int fqnIndex = classFqn.lastIndexOf("::"); // NOI18N
 155.618 +
 155.619 +        if (fqnIndex != -1) {
 155.620 +            classIn = classFqn.substring(0, fqnIndex);
 155.621 +        }
 155.622 +        int prefixLength = prefix.length();
 155.623 +
 155.624 +        for (IndexResult map : result) {
 155.625 +            assert map != null;
 155.626 +
 155.627 +            String url = map.getUrl().toExternalForm();
 155.628 +            String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
 155.629 +            String module = map.getValue(PythonIndexer.FIELD_IN);
 155.630 +
 155.631 +            if (extendsClasses == null) {
 155.632 +                String[] ext = map.getValues(PythonIndexer.FIELD_EXTENDS_NAME);
 155.633 +                if (ext != null && ext.length > 0) {
 155.634 +                    if (extendsClasses == null) {
 155.635 +                        extendsClasses = Arrays.asList(ext);
 155.636 +                    } else {
 155.637 +                        extendsClasses = new ArrayList<>(extendsClasses);
 155.638 +                        extendsClasses.addAll(Arrays.asList(ext));
 155.639 +                    }
 155.640 +                }
 155.641 +            }
 155.642 +
 155.643 +            String[] members = map.getValues(PythonIndexer.FIELD_MEMBER);
 155.644 +
 155.645 +            if (members != null) {
 155.646 +                for (String signature : members) {
 155.647 +                    // Prevent duplicates when method is redefined
 155.648 +                    if (includeOverrides || !seenSignatures.contains(signature)) {
 155.649 +                        if (signature.startsWith(prefix)) {
 155.650 +                            if (kind == QuerySupport.Kind.EXACT) {
 155.651 +                                if (signature.charAt(prefixLength) != ';') {
 155.652 +                                    continue;
 155.653 +                                }
 155.654 +                            } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !signature.regionMatches(true, 0, prefix, 0, prefix.length())) {
 155.655 +                                continue;
 155.656 +                            } else {
 155.657 +                                // REGEXP, CAMELCASE filtering etc. not supported here
 155.658 +                                assert (kind == QuerySupport.Kind.PREFIX) ||
 155.659 +                                        (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
 155.660 +                            }
 155.661 +
 155.662 +                            if (!includeOverrides) {
 155.663 +                                seenSignatures.add(signature);
 155.664 +                            }
 155.665 +                            IndexedElement element = IndexedElement.create(signature, module, url, clz);
 155.666 +                            // TODO - filter out private? Or let code completer do that? Probably should, in case
 155.667 +                            // we have more rights when inheriting
 155.668 +                            element.setSmart(!haveRedirected);
 155.669 +                            element.setInherited(inheriting);
 155.670 +                            if (includeOverrides) {
 155.671 +                                element.setOrder(depth);
 155.672 +                            }
 155.673 +                            elements.add(element);
 155.674 +                        }
 155.675 +                    }
 155.676 +                }
 155.677 +            }
 155.678 +        }
 155.679 +
 155.680 +        if (classFqn.equals(OBJECT)) {
 155.681 +            return foundIt;
 155.682 +        }
 155.683 +
 155.684 +        if (extendsClasses == null || extendsClasses.size() == 0) {
 155.685 +            addMethodsFromClass(prefix, kind, OBJECT, elements, seenSignatures, scannedClasses,
 155.686 +                    true, true, includeOverrides, depth + 1);
 155.687 +        } else {
 155.688 +            // We're not sure we have a fully qualified path, so try some different candidates
 155.689 +            for (String extendsClass : extendsClasses) {
 155.690 +                if (!addMethodsFromClass(prefix, kind, extendsClass, elements, seenSignatures,
 155.691 +                        scannedClasses, haveRedirected, true, includeOverrides, depth + 1)) {
 155.692 +                    // Search by classIn
 155.693 +                    String fqn = classIn;
 155.694 +
 155.695 +                    while (fqn != null) {
 155.696 +                        if (addMethodsFromClass(prefix, kind, fqn + "::" + extendsClass, elements,
 155.697 +                                seenSignatures, scannedClasses, haveRedirected, true, includeOverrides, depth + 1)) {
 155.698 +                            break;
 155.699 +                        }
 155.700 +
 155.701 +                        int f = fqn.lastIndexOf("::"); // NOI18N
 155.702 +
 155.703 +                        if (f == -1) {
 155.704 +                            break;
 155.705 +                        } else {
 155.706 +                            fqn = fqn.substring(0, f);
 155.707 +                        }
 155.708 +                    }
 155.709 +                }
 155.710 +            }
 155.711 +        }
 155.712 +
 155.713 +        return foundIt;
 155.714 +    }
 155.715 +    
 155.716 +    
 155.717 +    public Set<IndexedElement> getAllMembers(String name, QuerySupport.Kind kind, PythonParserResult context, boolean includeDuplicates) {
 155.718 +        final Set<IndexResult> result = new HashSet<>();
 155.719 +        // TODO - handle case sensitivity better...
 155.720 +        String field = PythonIndexer.FIELD_MEMBER;
 155.721 +        QuerySupport.Kind originalKind = kind;
 155.722 +        if (kind == QuerySupport.Kind.EXACT) {
 155.723 +            // I can't do exact searches on methods because the method
 155.724 +            // entries include signatures etc. So turn this into a prefix
 155.725 +            // search and then compare chopped off signatures with the name
 155.726 +            kind = QuerySupport.Kind.PREFIX;
 155.727 +        }
 155.728 +
 155.729 +        String searchUrl = null;
 155.730 +        if (context != null) {
 155.731 +            searchUrl = context.getSnapshot().getSource().getFileObject().toURL().toExternalForm();
 155.732 +        }
 155.733 +
 155.734 +        String[] terms = {PythonIndexer.FIELD_IN,
 155.735 +                          PythonIndexer.FIELD_EXTENDS_NAME,
 155.736 +                          PythonIndexer.FIELD_MEMBER,
 155.737 +                          PythonIndexer.FIELD_CLASS_NAME};
 155.738 +
 155.739 +        search(field, name, kind, result, terms);
 155.740 +
 155.741 +//        Set<String> uniqueClasses = null;
 155.742 +//        if (includeDuplicates) {
 155.743 +//            uniqueClasses = null;
 155.744 +//        } else if (uniqueClasses == null) {
 155.745 +//            uniqueClasses = new HashSet<String>();
 155.746 +//        }
 155.747 +
 155.748 +        final Set<IndexedElement> members = new HashSet<>();
 155.749 +        int nameLength = name.length();
 155.750 +
 155.751 +        for (IndexResult map : result) {
 155.752 +            String[] signatures = map.getValues(PythonIndexer.FIELD_MEMBER);
 155.753 +            if (signatures != null && signatures.length > 0) {
 155.754 +                String url = map.getUrl().toExternalForm();
 155.755 +                String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
 155.756 +                String module = map.getValue(PythonIndexer.FIELD_IN);
 155.757 +                boolean inherited = searchUrl == null || !searchUrl.equals(url);
 155.758 +
 155.759 +                for (String signature : signatures) {
 155.760 +                    if (originalKind == QuerySupport.Kind.EXACT) {
 155.761 +                        if (signature.charAt(nameLength) != ';') {
 155.762 +                            continue;
 155.763 +                        }
 155.764 +                    } else if (originalKind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !signature.regionMatches(true, 0, name, 0, name.length())) {
 155.765 +                        continue;
 155.766 +                    } else {
 155.767 +                        // REGEXP, CAMELCASE filtering etc. not supported here
 155.768 +                        assert (originalKind == QuerySupport.Kind.PREFIX) ||
 155.769 +                                (originalKind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
 155.770 +                    }
 155.771 +
 155.772 +                    IndexedElement element = IndexedElement.create(signature, module, url, clz);
 155.773 +                    element.setInherited(inherited);
 155.774 +                    members.add(element);
 155.775 +                }
 155.776 +            }
 155.777 +        }
 155.778 +
 155.779 +        return members;
 155.780 +    }
 155.781 +    
 155.782 +    public Set<IndexedElement> getAllElements(String name, QuerySupport.Kind kind, PythonParserResult context, boolean includeDuplicates) {
 155.783 +        final Set<IndexResult> result = new HashSet<>();
 155.784 +        // TODO - handle case sensitivity better...
 155.785 +        String field = PythonIndexer.FIELD_ITEM;
 155.786 +        QuerySupport.Kind originalKind = kind;
 155.787 +        if (kind == QuerySupport.Kind.EXACT) {
 155.788 +            // I can't do exact searches on methods because the method
 155.789 +            // entries include signatures etc. So turn this into a prefix
 155.790 +            // search and then compare chopped off signatures with the name
 155.791 +            kind = QuerySupport.Kind.PREFIX;
 155.792 +        }
 155.793 +
 155.794 +        String searchUrl = null;
 155.795 +        if (context != null) {
 155.796 +            searchUrl = context.getSnapshot().getSource().getFileObject().toURL().toExternalForm();
 155.797 +        }
 155.798 +
 155.799 +        String[] terms = { PythonIndexer.FIELD_ITEM,
 155.800 +                           PythonIndexer.FIELD_MODULE_NAME };
 155.801 +
 155.802 +        search(field, name, kind, result, terms);
 155.803 +
 155.804 +        final Set<IndexedElement> elements = new HashSet<>();
 155.805 +        int nameLength = name.length();
 155.806 +
 155.807 +        for (IndexResult map : result) {
 155.808 +            String[] signatures = map.getValues(PythonIndexer.FIELD_ITEM);
 155.809 +            if (signatures != null && signatures.length > 0) {
 155.810 +                String url = map.getUrl().toExternalForm();
 155.811 +                String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
 155.812 +                boolean inherited = searchUrl == null || !searchUrl.equals(url);
 155.813 +
 155.814 +                for (String signature : signatures) {
 155.815 +                    if (originalKind == QuerySupport.Kind.EXACT) {
 155.816 +                        if (signature.charAt(nameLength) != ';') {
 155.817 +                            continue;
 155.818 +                        }
 155.819 +                    } else if (originalKind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !signature.regionMatches(true, 0, name, 0, name.length())) {
 155.820 +                        continue;
 155.821 +                    } else {
 155.822 +                        // REGEXP, CAMELCASE filtering etc. not supported here
 155.823 +                        assert (originalKind == QuerySupport.Kind.PREFIX) ||
 155.824 +                                (originalKind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
 155.825 +                    }
 155.826 +
 155.827 +                    IndexedElement element = IndexedElement.create(signature, module, url, null);
 155.828 +                    if (element.isPrivate() && !url.equals(searchUrl)) {
 155.829 +                        continue;
 155.830 +                    }
 155.831 +                    element.setInherited(inherited);
 155.832 +                    elements.add(element);
 155.833 +                }
 155.834 +            }
 155.835 +        }
 155.836 +
 155.837 +        return elements;
 155.838 +    }
 155.839 +
 155.840 +    public Set<String> getBuiltinSymbols() {
 155.841 +        Set<String> modules = new HashSet<>();
 155.842 +
 155.843 +        // The "functions" module is always imported by the interpreter, and ditto
 155.844 +        // for exceptions, constants, etc.
 155.845 +        //modules.add("objects"); // NOI18N -- just links to the others
 155.846 +        modules.addAll(BUILTIN_MODULES);
 155.847 +
 155.848 +        Set<String> symbols = new HashSet<>(250);
 155.849 +
 155.850 +        String[] terms = { PythonIndexer.FIELD_MODULE_NAME,
 155.851 +                           PythonIndexer.FIELD_ITEM };
 155.852 +
 155.853 +        // Look up all symbols
 155.854 +        for (String module : modules) {
 155.855 +            final Set<IndexResult> result = new HashSet<>();
 155.856 +            // TODO - handle case sensitivity better...
 155.857 +            String field = PythonIndexer.FIELD_MODULE_NAME;
 155.858 +            QuerySupport.Kind kind = QuerySupport.Kind.EXACT;
 155.859 +
 155.860 +            search(field, module, kind, result, terms);
 155.861 +
 155.862 +            for (IndexResult map : result) {
 155.863 +                String[] signatures = map.getValues(PythonIndexer.FIELD_ITEM);
 155.864 +                if (signatures != null) {
 155.865 +                    for (String signature : signatures) {
 155.866 +                        int semi = signature.indexOf(';');
 155.867 +                        assert semi != -1;
 155.868 +                        int flags = IndexedElement.decode(signature, semi + 3, 0);
 155.869 +                        if ((flags & IndexedElement.PRIVATE) != 0) {
 155.870 +                            // Skip private symbols - can't import those
 155.871 +                            continue;
 155.872 +                        }
 155.873 +                        String name = signature.substring(0, semi);
 155.874 +                        symbols.add(name);
 155.875 +                    }
 155.876 +                }
 155.877 +            }
 155.878 +        }
 155.879 +
 155.880 +        // Computed as described below
 155.881 +        String[] MISSING = {
 155.882 +            "Ellipsis", "False", "IndentationError", "None", "NotImplemented", "TabError", // NOI18N
 155.883 +            "True", "__debug__", "__doc__", "__name__", "copyright", "credits", "exit", "license", // NOI18N
 155.884 +            "quit" // NOI18N
 155.885 +        };
 155.886 +        for (String s : MISSING) {
 155.887 +            symbols.add(s);
 155.888 +        }
 155.889 +        symbols.add("__builtins__"); // NOI18N
 155.890 +        symbols.add("__file__"); // NOI18N
 155.891 +
 155.892 +        //// COMPUTING MISSING SYMBOLS:
 155.893 +        //// My builtin .rst files don't seem to define all the builtin symbols that the Python
 155.894 +        //// interpreter is configured with.  I generated these pretty trivially; run
 155.895 +        //// python and type "dir(__builtins__)" and you end up a list like the below:
 155.896 +        ////String[] EXTRA_BUILTINS = {"ArithmeticError", "AssertionError", "AttributeError", "BaseException",
 155.897 +        //    "DeprecationWarning", "EOFError", "Ellipsis", "EnvironmentError", "Exception", "False",
 155.898 +        //    "FloatingPointError", "FutureWarning", "GeneratorExit", "IOError", "ImportError",
 155.899 +        //    "ImportWarning", "IndentationError", "IndexError", "KeyError", "KeyboardInterrupt",
 155.900 +        //    "LookupError", "MemoryError", "NameError", "None", "NotImplemented", "NotImplementedError",
 155.901 +        //    "OSError", "OverflowError", "PendingDeprecationWarning", "ReferenceError", "RuntimeError",
 155.902 +        //    "RuntimeWarning", "StandardError", "StopIteration", "SyntaxError", "SyntaxWarning", "SystemError",
 155.903 +        //    "SystemExit", "TabError", "True", "TypeError", "UnboundLocalError", "UnicodeDecodeError",
 155.904 +        //    "UnicodeEncodeError", "UnicodeError", "UnicodeTranslateError", "UnicodeWarning", "UserWarning",
 155.905 +        //    "ValueError", "Warning", "ZeroDivisionError", "__debug__", "__doc__", "__import__", "__name__",
 155.906 +        //    "abs", "all", "any", "apply", "basestring", "bool", "buffer", "callable", "chr", "classmethod",
 155.907 +        //    "cmp", "coerce", "compile", "complex", "copyright", "credits", "delattr", "dict", "dir", "divmod",
 155.908 +        //    "enumerate", "eval", "execfile", "exit", "file", "filter", "float", "frozenset", "getattr",
 155.909 +        //    "globals", "hasattr", "hash", "help", "hex", "id", "input", "int", "intern", "isinstance",
 155.910 +        //    "issubclass", "iter", "len", "license", "list", "locals", "long", "map", "max", "min", "object",
 155.911 +        //    "oct", "open", "ord", "pow", "property", "quit", "range", "raw_input", "reduce", "reload",
 155.912 +        //    "repr", "reversed", "round", "set", "setattr", "slice", "sorted", "staticmethod", "str", "sum",
 155.913 +        //    "super", "tuple", "type", "unichr", "unicode", "vars", "xrange", "zip"};
 155.914 +        //// Most of these will be defined by my index search. However, for the missing ones, let's add them
 155.915 +        //// in. The following code computes the delta and produces a source-like string for it.
 155.916 +        //// It also counts the total symbol map size so we can pick a reasonable default:
 155.917 +        //List<String> asList = Arrays.asList(EXTRA_BUILTINS);
 155.918 +        //Set<String> asSet = new HashSet<String>(asList);
 155.919 +        //asSet.removeAll(symbols);
 155.920 +        //List<String> missing = new ArrayList<String>(asSet);
 155.921 +        //Collections.sort(missing);
 155.922 +        //int width = 0;
 155.923 +        //StringBuilder sb = new StringBuilder();
 155.924 +        //for (String s : missing) {
 155.925 +        //    sb.append('"');
 155.926 +        //    sb.append(s);
 155.927 +        //    sb.append('"');
 155.928 +        //    sb.append(',');
 155.929 +        //    sb.append(' ');
 155.930 +        //    width += s.length()+4;
 155.931 +        //    if (width > 70) {
 155.932 +        //        sb.append("\n");
 155.933 +        //        width = 0;
 155.934 +        //    }
 155.935 +        //}
 155.936 +        //String missingCode = "String[] MISSING = {\n" + sb.toString() + "\n};\n";
 155.937 +        //symbols.addAll(asList);
 155.938 +        //int requiredSetSize = symbols.size();
 155.939 +
 155.940 +        return symbols;
 155.941 +    }
 155.942 +
 155.943 +    @SuppressWarnings("unchecked")
 155.944 +    public Set<String> getImportsFor(String ident, boolean includeSymbol) {
 155.945 +        Set<String> modules = new HashSet<>(10);
 155.946 +
 155.947 +        final Set<IndexResult> result = new HashSet<>();
 155.948 +        search(PythonIndexer.FIELD_MODULE_NAME, ident, QuerySupport.Kind.EXACT, result, PythonIndexer.FIELD_MODULE_NAME);
 155.949 +        for (IndexResult map : result) {
 155.950 +            String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
 155.951 +            if (module != null) {
 155.952 +                // TODO - record more information about this, such as the FQN
 155.953 +                // so it's easier for the user to disambiguate
 155.954 +                modules.add(module);
 155.955 +            }
 155.956 +        }
 155.957 +
 155.958 +        // TODO - handle case sensitivity better...
 155.959 +        String field = PythonIndexer.FIELD_ITEM;
 155.960 +        QuerySupport.Kind kind = QuerySupport.Kind.PREFIX; // We're storing encoded signatures so not exact matches
 155.961 +
 155.962 +        String[] terms = { PythonIndexer.FIELD_ITEM,
 155.963 +                           PythonIndexer.FIELD_MODULE_NAME };
 155.964 +
 155.965 +        result.clear();
 155.966 +        search(field, ident, kind, result, terms);
 155.967 +        String match = ident + ";";
 155.968 +
 155.969 +        MapSearch:
 155.970 +        for (IndexResult map : result) {
 155.971 +            String module = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
 155.972 +            if (module == null) {
 155.973 +                continue;
 155.974 +            }
 155.975 +
 155.976 +            if (module.indexOf('-') != -1) {
 155.977 +                // Don't include modules with -; these aren't real module
 155.978 +                // names (usually python scripts in directories containing a dash
 155.979 +                // that I incorrectly compute a module name for
 155.980 +                continue;
 155.981 +            }
 155.982 +
 155.983 +            String[] members = map.getValues(PythonIndexer.FIELD_ITEM);
 155.984 +            if (members == null || members.length == 0) {
 155.985 +                continue;
 155.986 +            }
 155.987 +
 155.988 +            int semi = match.length() - 1;
 155.989 +
 155.990 +            for (String signature : members) {
 155.991 +                if (signature.startsWith(match)) {
 155.992 +                    if (includeSymbol) {
 155.993 +                        int flags = IndexedElement.decode(signature, semi + 3, 0);
 155.994 +                        if ((flags & IndexedElement.PRIVATE) != 0) {
 155.995 +                            // Skip private symbols - can't import those
 155.996 +                            continue;
 155.997 +                        }
 155.998 +                        String sig = ident;
 155.999 +                        char type = signature.charAt(semi + 1);
155.1000 +                        if (type == 'F') {
155.1001 +                            int sigStart = signature.indexOf(';', semi + 3) + 1;
155.1002 +                            int sigEnd = signature.indexOf(';', sigStart);
155.1003 +                            sig = ident + "(" + signature.substring(sigStart, sigEnd) + ")"; // NOI18N
155.1004 +                        } else if (type == 'I') {
155.1005 +                            // Don't provide modules that just -import- the symbol
155.1006 +                            continue;
155.1007 +                        }
155.1008 +                        if (!sig.equals(module)) {
155.1009 +                            modules.add(module + ": " + sig); // NOI18N
155.1010 +                        } else {
155.1011 +                            modules.add(module);
155.1012 +                        }
155.1013 +                    } else {
155.1014 +                        modules.add(module);
155.1015 +                    }
155.1016 +                    continue MapSearch;
155.1017 +                }
155.1018 +            }
155.1019 +        }
155.1020 +
155.1021 +        return modules;
155.1022 +    }
155.1023 +    
155.1024 +    public Set<IndexedElement> getImportedElements(String prefix, QuerySupport.Kind kind, PythonParserResult context, List<Import> imports, List<ImportFrom> importsFrom) {
155.1025 +        // TODO - separate methods from variables?? E.g. if you have method Foo() and class Foo
155.1026 +        // coming from different places
155.1027 +        
155.1028 +        
155.1029 +//        Set<String> imported = new HashSet<String>();
155.1030 +//
155.1031 +        Set<IndexedElement> elements = new HashSet<>();
155.1032 +
155.1033 +        // Look up the imports and compute all the symbols we get from the import
155.1034 +        Set<String> modules = new HashSet<>();
155.1035 +
155.1036 +        // ImportsFrom require no index lookup
155.1037 +        for (ImportFrom from : importsFrom) {
155.1038 +            if (ImportManager.isFutureImport(from)) {
155.1039 +                continue;
155.1040 +            }
155.1041 +            List<alias> names = from.getInternalNames();
155.1042 +            if (names != null) {
155.1043 +                for (alias at : names) {
155.1044 +                    if ("*".equals(at.getInternalName())) { // NOI18N
155.1045 +                        modules.add(from.getInternalModule());
155.1046 +//                    } else {
155.1047 +//                        String name = at.getInternalAsname() != null ? at.getInternalAsname() : at.getInternalName();
155.1048 +//                        assert name.length() > 0;
155.1049 +//                        imported.add(name);
155.1050 +                    }
155.1051 +                }
155.1052 +            }
155.1053 +        }
155.1054 +
155.1055 +//        for (Import imp : imports) {
155.1056 +//            if (imp.names != null) {
155.1057 +//                for (alias at : imp.getInternalNames()) {
155.1058 +//                    if (at.getInternalAsname() != null) {
155.1059 +//                        String name = at.getInternalAsname();
155.1060 +//                        assert name.length() > 0;
155.1061 +//                        imported.add(name);
155.1062 +//                    } else {
155.1063 +//                        imported.add(at.getInternalName());
155.1064 +//                    }
155.1065 +//                }
155.1066 +//            }
155.1067 +//        }
155.1068 +//
155.1069 +//
155.1070 +//        // Create variable items for the locally imported symbols
155.1071 +//        for (String name : imported) {
155.1072 +//            if (name.startsWith(prefix)) {
155.1073 +//                if (kind == QuerySupport.Kind.EXACT) {
155.1074 +//                    // Ensure that the method is not longer than the prefix
155.1075 +//                    if ((name.length() > prefix.length()) &&
155.1076 +//                            (name.charAt(prefix.length()) != '(') &&
155.1077 +//                            (name.charAt(prefix.length()) != ';')) {
155.1078 +//                        continue;
155.1079 +//                    }
155.1080 +//                } else {
155.1081 +//                    // REGEXP, CAMELCASE filtering etc. not supported here
155.1082 +//                    assert (kind == QuerySupport.Kind.PREFIX) ||
155.1083 +//                    (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
155.1084 +//                }
155.1085 +//    String url = null;
155.1086 +//                ElementKind elementKind = ElementKind.VARIABLE;
155.1087 +//                if (Character.isUpperCase(name.charAt(0))) {
155.1088 +//                    // Class?
155.1089 +//                    elementKind = ElementKind.CLASS;
155.1090 +//                }
155.1091 +//                IndexedElement element = new IndexedElement(name, elementKind, url, null);
155.1092 +//                element.setSmart(true);
155.1093 +//                elements.add(element);
155.1094 +//                // TODO - imported class symbls should be shown as classes!
155.1095 +//            }
155.1096 +//        }
155.1097 +
155.1098 +        // Always include the current file as imported
155.1099 +        String moduleName = null;
155.1100 +        if (context != null) {
155.1101 +            moduleName = PythonUtils.getModuleName(context.getSnapshot().getSource().getFileObject());
155.1102 +            modules.add(moduleName);
155.1103 +        }
155.1104 +
155.1105 +        modules.addAll(BUILTIN_MODULES);
155.1106 +
155.1107 +        addImportedElements(prefix, kind, modules, elements, null);
155.1108 +
155.1109 +        return elements;
155.1110 +    }
155.1111 +    public Set<String> getImportedFromWildcards(List<ImportFrom> importsFrom) {
155.1112 +        Set<String> symbols = new HashSet<>(100);
155.1113 +
155.1114 +        // Look up the imports and compute all the symbols we get from the import
155.1115 +        Set<String> modules = new HashSet<>();
155.1116 +
155.1117 +        // ImportsFrom require no index lookup
155.1118 +        for (ImportFrom from : importsFrom) {
155.1119 +            List<alias> names = from.getInternalNames();
155.1120 +            if (names != null) {
155.1121 +                for (alias at : names) {
155.1122 +                    if ("*".equals(at.getInternalName())) { // NOI18N
155.1123 +                        modules.add(from.getInternalModule());
155.1124 +                    }
155.1125 +                }
155.1126 +            }
155.1127 +        }
155.1128 +
155.1129 +        String[] terms = { PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MODULE_NAME };
155.1130 +
155.1131 +        // Look up all symbols
155.1132 +        for (String module : modules) {
155.1133 +            // TODO - cache builtins?
155.1134 +            Set<String> moduleSymbols = symbols;
155.1135 +            boolean isSystem = isSystemModule(module);
155.1136 +            if (isSystem) {
155.1137 +                Set<String> s = wildcardImports.get(module);
155.1138 +                if (s != null) {
155.1139 +                    symbols.addAll(s);
155.1140 +                    continue;
155.1141 +                } else {
155.1142 +                    moduleSymbols = new HashSet<>(100);
155.1143 +                }
155.1144 +            }
155.1145 +
155.1146 +
155.1147 +            final Set<IndexResult> result = new HashSet<>();
155.1148 +            // TODO - handle case sensitivity better...
155.1149 +
155.1150 +            search(PythonIndexer.FIELD_MODULE_NAME, module, QuerySupport.Kind.EXACT, result, terms);
155.1151 +
155.1152 +            for (IndexResult map : result) {
155.1153 +                String[] items = map.getValues(PythonIndexer.FIELD_ITEM);
155.1154 +                if (items != null) {
155.1155 +                    for (String signature : items) {
155.1156 +                        int semi = signature.indexOf(';');
155.1157 +                        assert semi != -1;
155.1158 +                        int flags = IndexedElement.decode(signature, semi + 3, 0);
155.1159 +                        if ((flags & IndexedElement.PRIVATE) != 0) {
155.1160 +                            // Skip private symbols - can't import those
155.1161 +                            continue;
155.1162 +                        }
155.1163 +
155.1164 +                        String name = signature.substring(0, semi);
155.1165 +                        moduleSymbols.add(name);
155.1166 +                    }
155.1167 +                }
155.1168 +            }
155.1169 +
155.1170 +            if (isSystem) {
155.1171 +                assert moduleSymbols != symbols;
155.1172 +                symbols.addAll(moduleSymbols);
155.1173 +                wildcardImports.put(module, moduleSymbols);
155.1174 +            }
155.1175 +        }
155.1176 +
155.1177 +        return symbols;
155.1178 +    }
155.1179 +    
155.1180 +    public Set<IndexedElement> getImportedElements(String prefix, QuerySupport.Kind kind, Set<String> modules, Set<String> systemModuleHolder) {
155.1181 +        Set<IndexedElement> elements = new HashSet<>();
155.1182 +
155.1183 +        addImportedElements(prefix, kind, modules, elements, systemModuleHolder);
155.1184 +
155.1185 +        return elements;
155.1186 +    }
155.1187 +
155.1188 +    public boolean isSystemModule(String module) {
155.1189 +        if (systemModules == null) {
155.1190 +            systemModules = new HashSet<>(800); // measured: 623
155.1191 +            String[] terms = { PythonIndexer.FIELD_MODULE_ATTR_NAME,
155.1192 +                               PythonIndexer.FIELD_MODULE_NAME };
155.1193 +            final Set<IndexResult> result = new HashSet<>();
155.1194 +
155.1195 +            // This doesn't work because the attrs field isn't searchable:
155.1196 +            //search(PythonIndexer.FIELD_MODULE_ATTR_NAME, "S", QuerySupport.Kind.PREFIX, result, ALL_SCOPE, terms);
155.1197 +            //for (IndexResult map : result) {
155.1198 +            //    assert map.getValue(PythonIndexer.FIELD_MODULE_ATTR_NAME).indexOf("S") != -1;
155.1199 +            //    systemModules.add(map.getValue(PythonIndexer.FIELD_MODULE_NAME));
155.1200 +            //}
155.1201 +
155.1202 +            search(PythonIndexer.FIELD_MODULE_NAME, "", QuerySupport.Kind.PREFIX, result, terms);
155.1203 +
155.1204 +            for (IndexResult map : result) {
155.1205 +                String attrs = map.getValue(PythonIndexer.FIELD_MODULE_ATTR_NAME);
155.1206 +                if (attrs != null && attrs.indexOf('S') != -1) {
155.1207 +                    String mod = map.getValue(PythonIndexer.FIELD_MODULE_NAME);
155.1208 +                    systemModules.add(mod);
155.1209 +                }
155.1210 +            }
155.1211 +        }
155.1212 +
155.1213 +        return systemModules.contains(module);
155.1214 +    }
155.1215 +
155.1216 +    public boolean isLowercaseClassName(String clz) {
155.1217 +        if (availableClasses == null) {
155.1218 +            availableClasses = new HashSet<>(300); // measured: 193
155.1219 +            final Set<IndexResult> result = new HashSet<>();
155.1220 +
155.1221 +            search(PythonIndexer.FIELD_CLASS_NAME, "", QuerySupport.Kind.PREFIX, result, PythonIndexer.FIELD_CLASS_NAME);
155.1222 +
155.1223 +            for (IndexResult map : result) {
155.1224 +                String c = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
155.1225 +                if (c != null && !Character.isUpperCase(c.charAt(0))) {
155.1226 +                    availableClasses.add(c);
155.1227 +                }
155.1228 +            }
155.1229 +        }
155.1230 +
155.1231 +        return availableClasses.contains(clz);
155.1232 +    }
155.1233 +    
155.1234 +    public void addImportedElements(String prefix, QuerySupport.Kind kind, Set<String> modules, Set<IndexedElement> elements, Set<String> systemModuleHolder) {
155.1235 +        
155.1236 +        String[] terms = { PythonIndexer.FIELD_ITEM,
155.1237 +                           PythonIndexer.FIELD_MODULE_ATTR_NAME,
155.1238 +                           PythonIndexer.FIELD_MODULE_NAME };
155.1239 +
155.1240 +        // Look up all symbols
155.1241 +        for (String module : modules) {
155.1242 +            boolean isBuiltin = isBuiltinModule(module);
155.1243 +            boolean isSystem = isBuiltin;
155.1244 +
155.1245 +            final Set<IndexResult> result = new HashSet<>();
155.1246 +            // TODO - handle case sensitivity better...
155.1247 +
155.1248 +            search(PythonIndexer.FIELD_MODULE_NAME, module, QuerySupport.Kind.EXACT, result, terms);
155.1249 +            int prefixLength = prefix.length();
155.1250 +
155.1251 +            for (IndexResult map : result) {
155.1252 +                String url = map.getUrl().toExternalForm();
155.1253 +                String[] items = map.getValues(PythonIndexer.FIELD_ITEM);
155.1254 +                if (items != null) {
155.1255 +                    String attrs = map.getValue(PythonIndexer.FIELD_MODULE_ATTR_NAME);
155.1256 +                    if (attrs != null && attrs.indexOf('S') != -1) {
155.1257 +                        isSystem = true;
155.1258 +                    }
155.1259 +                    for (String signature : items) {
155.1260 +                        if (signature.startsWith(prefix)) {
155.1261 +                            if (kind == QuerySupport.Kind.EXACT) {
155.1262 +                                if (signature.charAt(prefixLength) != ';') {
155.1263 +                                    continue;
155.1264 +                                }
155.1265 +                            } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !signature.regionMatches(true, 0, prefix, 0, prefix.length())) {
155.1266 +                                continue;
155.1267 +                            } else {
155.1268 +                                // REGEXP, CAMELCASE filtering etc. not supported here
155.1269 +                                assert (kind == QuerySupport.Kind.PREFIX) ||
155.1270 +                                        (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX);
155.1271 +                            }
155.1272 +
155.1273 +                            IndexedElement element = IndexedElement.create(signature, module, url, null);
155.1274 +                            if (element.isPrivate()) {
155.1275 +                                continue;
155.1276 +                            }
155.1277 +                            if (isBuiltin) {
155.1278 +                                element.setRhs("<i>builtin</i>");
155.1279 +                            } else {
155.1280 +                                element.setSmart(true);
155.1281 +                            }
155.1282 +                            element.setInherited(true);
155.1283 +                            elements.add(element);
155.1284 +                        }
155.1285 +                    }
155.1286 +                }
155.1287 +            }
155.1288 +
155.1289 +            if (systemModuleHolder != null && isSystem) {
155.1290 +                systemModuleHolder.add(module);
155.1291 +            }
155.1292 +        }
155.1293 +    }
155.1294 +
155.1295 +    public Set<IndexedElement> getExceptions(String prefix, QuerySupport.Kind kind) {
155.1296 +        final Set<IndexResult> result = new HashSet<>();
155.1297 +        String[] terms = { PythonIndexer.FIELD_EXTENDS_NAME,
155.1298 +                              PythonIndexer.FIELD_CLASS_NAME,
155.1299 +                              PythonIndexer.FIELD_CLASS_ATTR_NAME,
155.1300 +                              PythonIndexer.FIELD_IN };
155.1301 +        search(PythonIndexer.FIELD_EXTENDS_NAME, "", QuerySupport.Kind.PREFIX, result, terms); // NOI18N
155.1302 +        Map<String, String> extendsMap = new HashMap<>(100);
155.1303 +        // First iteration: Compute inheritance hierarchy
155.1304 +        for (IndexResult map : result) {
155.1305 +
155.1306 +            String superClass = map.getValue(PythonIndexer.FIELD_EXTENDS_NAME);
155.1307 +            if (superClass != null) {
155.1308 +                String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
155.1309 +                if (clz != null) {
155.1310 +                    extendsMap.put(clz, superClass);
155.1311 +                }
155.1312 +            }
155.1313 +        }
155.1314 +
155.1315 +        // Compute set of classes that extend Exception
155.1316 +
155.1317 +        Set<String> exceptionClasses = new HashSet<>();
155.1318 +        Set<String> notExceptionClasses = new HashSet<>();
155.1319 +        exceptionClasses.add("Exception"); // NOI18N
155.1320 +        Outer:
155.1321 +        for (String cls : extendsMap.keySet()) {
155.1322 +            if (notExceptionClasses.contains(cls)) {
155.1323 +                continue;
155.1324 +            } else if (!exceptionClasses.contains(cls)) {
155.1325 +                // See if this extends exception:
155.1326 +                String c = cls;
155.1327 +                int depth = 0;
155.1328 +                while (c != null) {
155.1329 +                    c = extendsMap.get(c);
155.1330 +                    String prev = null;
155.1331 +                    if (c != null) {
155.1332 +                        if (exceptionClasses.contains(c)) {
155.1333 +                            exceptionClasses.add(cls);
155.1334 +                            continue Outer;
155.1335 +                        }
155.1336 +                        depth++;
155.1337 +                        if (depth == 15) {
155.1338 +                            // we're probably going in circles, perhaps a extends b extends a.
155.1339 +                            // This doesn't really happen in Python, but can happen when there
155.1340 +                            // are unrelated classes with the same name getting treated as one here -
155.1341 +                            // class a in library X, and class a in library Y,
155.1342 +                            break;
155.1343 +                        }
155.1344 +                    } else if (prev != null) {
155.1345 +                        notExceptionClasses.add(prev);
155.1346 +                        break;
155.1347 +                    }
155.1348 +                }
155.1349 +                notExceptionClasses.add(cls);
155.1350 +            }
155.1351 +        }
155.1352 +
155.1353 +        // Next add elements for all the exceptions
155.1354 +        final Set<IndexedElement> classes = new HashSet<>();
155.1355 +        for (IndexResult map : result) {
155.1356 +            String clz = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
155.1357 +            if (clz == null || !exceptionClasses.contains(clz)) {
155.1358 +                continue;
155.1359 +            }
155.1360 +
155.1361 +            if ((kind == QuerySupport.Kind.PREFIX) && !clz.startsWith(prefix)) {
155.1362 +                continue;
155.1363 +            } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX && !clz.regionMatches(true, 0, prefix, 0, prefix.length())) {
155.1364 +                continue;
155.1365 +            } else if (kind == QuerySupport.Kind.EXACT && !clz.equals(prefix)) {
155.1366 +                continue;
155.1367 +            }
155.1368 +
155.1369 +            String url = map.getUrl().toExternalForm();
155.1370 +            String module = map.getValue(PythonIndexer.FIELD_IN);
155.1371 +            IndexedElement element = new IndexedElement(clz, ElementKind.CLASS, url, module, null, null);
155.1372 +            String attrs = map.getValue(PythonIndexer.FIELD_CLASS_ATTR_NAME);
155.1373 +            if (attrs != null) {
155.1374 +                int flags = IndexedElement.decode(attrs, 0, 0);
155.1375 +                element.setFlags(flags);
155.1376 +            }
155.1377 +            classes.add(element);
155.1378 +        }
155.1379 +
155.1380 +        return classes;
155.1381 +    }
155.1382 +
155.1383 +    /** Find the subclasses of the given class name, with the POSSIBLE fqn from the
155.1384 +     * context of the usage. */
155.1385 +    public Set<IndexedElement> getSubClasses(String fqn, String possibleFqn, String name, boolean directOnly) {
155.1386 +        //String field = PythonIndexer.FIELD_FQN_NAME;
155.1387 +        Set<IndexedElement> classes = new HashSet<>();
155.1388 +        Set<String> scannedClasses = new HashSet<>();
155.1389 +        Set<String> seenClasses = new HashSet<>();
155.1390 +
155.1391 +        if (fqn != null) {
155.1392 +            addSubclasses(fqn, classes, seenClasses, scannedClasses, directOnly);
155.1393 +        } else {
155.1394 +            fqn = possibleFqn;
155.1395 +            if (name.equals(possibleFqn)) {
155.1396 +                fqn = null;
155.1397 +            }
155.1398 +
155.1399 +            // Try looking at the libraries too
155.1400 +            while ((classes.size() == 0) && (fqn != null && fqn.length() > 0)) {
155.1401 +                // TODO - use the boolvalue from addclasses instead!
155.1402 +                boolean found = addSubclasses(fqn + "::" + name, classes, seenClasses, scannedClasses, directOnly);
155.1403 +                if (found) {
155.1404 +                    return classes;
155.1405 +                }
155.1406 +
155.1407 +                int f = fqn.lastIndexOf("::");
155.1408 +
155.1409 +                if (f == -1) {
155.1410 +                    break;
155.1411 +                } else {
155.1412 +                    fqn = fqn.substring(0, f);
155.1413 +                }
155.1414 +            }
155.1415 +
155.1416 +            if (classes.size() == 0) {
155.1417 +                addSubclasses(name, classes, seenClasses, scannedClasses, directOnly);
155.1418 +            }
155.1419 +        }
155.1420 +
155.1421 +        return classes;
155.1422 +    }
155.1423 +    
155.1424 +    private boolean addSubclasses(String classFqn, Set<IndexedElement> classes, Set<String> seenClasses, Set<String> scannedClasses, boolean directOnly) {
155.1425 +        // Prevent problems with circular includes or redundant includes
155.1426 +        if (scannedClasses.contains(classFqn)) {
155.1427 +            return false;
155.1428 +        }
155.1429 +
155.1430 +        scannedClasses.add(classFqn);
155.1431 +
155.1432 +        String searchField = PythonIndexer.FIELD_EXTENDS_NAME;
155.1433 +
155.1434 +        Set<IndexResult> result = new HashSet<>();
155.1435 +
155.1436 +        String[] terms = { PythonIndexer.FIELD_IN,
155.1437 +                              PythonIndexer.FIELD_EXTENDS_NAME,
155.1438 +                              PythonIndexer.FIELD_CLASS_ATTR_NAME,
155.1439 +                              PythonIndexer.FIELD_CLASS_NAME };
155.1440 +
155.1441 +        search(searchField, classFqn, QuerySupport.Kind.EXACT, result, terms);
155.1442 +
155.1443 +        boolean foundIt = result.size() > 0;
155.1444 +
155.1445 +        // If this is a bogus class entry (no search rsults) don't continue
155.1446 +        if (!foundIt) {
155.1447 +            return foundIt;
155.1448 +        }
155.1449 +
155.1450 +        for (IndexResult map : result) {
155.1451 +            String className = map.getValue(PythonIndexer.FIELD_CLASS_NAME);
155.1452 +            if (className != null && !seenClasses.contains(className)) {
155.1453 +                String url = map.getUrl().toExternalForm();
155.1454 +                String module = map.getValue(PythonIndexer.FIELD_IN);
155.1455 +                IndexedElement clz = new IndexedElement(className, ElementKind.CLASS, url, module, null, null);
155.1456 +                String attrs = map.getValue(PythonIndexer.FIELD_CLASS_ATTR_NAME);
155.1457 +                if (attrs != null) {
155.1458 +                    int flags = IndexedElement.decode(attrs, 0, 0);
155.1459 +                    clz.setFlags(flags);
155.1460 +                }
155.1461 +                classes.add(clz);
155.1462 +
155.1463 +                seenClasses.add(className);
155.1464 +
155.1465 +                if (!directOnly) {
155.1466 +                    addSubclasses(className, classes, seenClasses, scannedClasses, directOnly);
155.1467 +                }
155.1468 +            }
155.1469 +        }
155.1470 +
155.1471 +        return foundIt;
155.1472 +    }
155.1473 +}
   156.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   156.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonIndexSearcher.java	Mon Sep 21 13:01:16 2015 +0200
   156.3 @@ -0,0 +1,252 @@
   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.awt.Toolkit;
  156.37 +import java.util.HashSet;
  156.38 +import java.util.Set;
  156.39 +import java.util.logging.Logger;
  156.40 +import javax.swing.Icon;
  156.41 +import org.netbeans.modules.python.source.elements.IndexedElement;
  156.42 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  156.43 +import org.netbeans.api.project.FileOwnerQuery;
  156.44 +import org.netbeans.api.project.Project;
  156.45 +import org.netbeans.api.project.ProjectInformation;
  156.46 +import org.netbeans.api.project.ProjectUtils;
  156.47 +import org.netbeans.modules.csl.api.ElementHandle;
  156.48 +import org.netbeans.modules.csl.api.IndexSearcher;
  156.49 +import org.netbeans.modules.csl.api.IndexSearcher.Descriptor;
  156.50 +import org.netbeans.modules.csl.api.IndexSearcher.Helper;
  156.51 +import org.netbeans.modules.csl.spi.GsfUtilities;
  156.52 +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
  156.53 +import org.openide.filesystems.FileObject;
  156.54 +import org.openide.util.ImageUtilities;
  156.55 +import org.python.antlr.PythonTree;
  156.56 +
  156.57 +/**
  156.58 + *
  156.59 + * @author Tor Norbye
  156.60 + */
  156.61 +public class PythonIndexSearcher implements IndexSearcher {
  156.62 +
  156.63 +    @Override
  156.64 +    public Set<? extends Descriptor> getTypes(Project prjct, String textForQuery, QuerySupport.Kind kind, Helper helper) {
  156.65 +        PythonIndex index = PythonIndex.get(prjct);
  156.66 +        Set<PythonSymbol> result = new HashSet<>();
  156.67 +        Set<? extends IndexedElement> elements;
  156.68 +
  156.69 +        // TODO - do some filtering if you use ./#
  156.70 +        //        int dot = textForQuery.lastIndexOf('.');
  156.71 +        //        if (dot != -1 && (kind == QuerySupport.Kind.PREFIX || kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX)) {
  156.72 +        //            String prefix = textForQuery.substring(dot+1);
  156.73 +        //            String in = textForQuery.substring(0, dot);
  156.74 +
  156.75 +        elements = index.getClasses(textForQuery, kind, null, true);
  156.76 +        for (IndexedElement element : elements) {
  156.77 +            result.add(new PythonSymbol(element, helper));
  156.78 +        }
  156.79 +
  156.80 +        return result;
  156.81 +    }
  156.82 +
  156.83 +    @Override
  156.84 +    public Set<? extends Descriptor> getSymbols(Project prjct, String textForQuery, QuerySupport.Kind kind, Helper helper) {
  156.85 +        PythonIndex index = PythonIndex.get(prjct);
  156.86 +        Set<PythonSymbol> result = new HashSet<>();
  156.87 +        Set<? extends IndexedElement> elements;
  156.88 +
  156.89 +        // TODO - do some filtering if you use ./#
  156.90 +        //        int dot = textForQuery.lastIndexOf('.');
  156.91 +        //        if (dot != -1 && (kind == QuerySupport.Kind.PREFIX || kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX)) {
  156.92 +        //            String prefix = textForQuery.substring(dot+1);
  156.93 +        //            String in = textForQuery.substring(0, dot);
  156.94 +
  156.95 +        elements = index.getAllMembers(textForQuery, kind, null, true);
  156.96 +        for (IndexedElement element : elements) {
  156.97 +            result.add(new PythonSymbol(element, helper));
  156.98 +        }
  156.99 +        elements = index.getClasses(textForQuery, kind, null, true);
 156.100 +        for (IndexedElement element : elements) {
 156.101 +            result.add(new PythonSymbol(element, helper));
 156.102 +        }
 156.103 +        elements = index.getModules(textForQuery, kind);
 156.104 +        for (IndexedElement element : elements) {
 156.105 +            result.add(new PythonSymbol(element, helper));
 156.106 +        }
 156.107 +
 156.108 +        return result;
 156.109 +    }
 156.110 +
 156.111 +    private class PythonSymbol extends Descriptor {
 156.112 +        private final IndexedElement element;
 156.113 +        private String projectName;
 156.114 +        private Icon projectIcon;
 156.115 +        private final Helper helper;
 156.116 +        private boolean isLibrary;
 156.117 +        private static final String ICON_PATH = "org/netbeans/modules/python/editor/resources/pyc_16.png"; //NOI18N
 156.118 +
 156.119 +        public PythonSymbol(IndexedElement element, Helper helper) {
 156.120 +            this.element = element;
 156.121 +            this.helper = helper;
 156.122 +        }
 156.123 +
 156.124 +        @Override
 156.125 +        public Icon getIcon() {
 156.126 +            if (projectName == null) {
 156.127 +                initProjectInfo();
 156.128 +            }
 156.129 +            //if (isLibrary) {
 156.130 +            //    return new ImageIcon(org.openide.util.ImageUtilities.loadImage(PYTHON_KEYWORD));
 156.131 +            //}
 156.132 +            return helper.getIcon(element);
 156.133 +        }
 156.134 +
 156.135 +        @Override
 156.136 +        public String getTypeName() {
 156.137 +            return element.getName();
 156.138 +        }
 156.139 +
 156.140 +        @Override
 156.141 +        public String getProjectName() {
 156.142 +            if (projectName == null) {
 156.143 +                initProjectInfo();
 156.144 +            }
 156.145 +            return projectName;
 156.146 +        }
 156.147 +
 156.148 +        private void initProjectInfo() {
 156.149 +            FileObject fo = element.getFileObject();
 156.150 +            if (fo != null) {
 156.151 +//                File f = FileUtil.toFile(fo);
 156.152 +                Project p = FileOwnerQuery.getOwner(fo);
 156.153 +                if (p != null) {
 156.154 +//                    JsPlatform platform = JsPlatform.platformFor(p);
 156.155 +//                    if (platform != null) {
 156.156 +//                        String lib = platform.getLib();
 156.157 +//                        if (lib != null && f.getPath().startsWith(lib)) {
 156.158 +//                            projectName = "Js Library";
 156.159 +//                            isLibrary = true;
 156.160 +//                        }
 156.161 +//                    } else {
 156.162 +                    ProjectInformation pi = ProjectUtils.getInformation(p);
 156.163 +                    projectName = pi.getDisplayName();
 156.164 +                    projectIcon = pi.getIcon();
 156.165 +//                    }
 156.166 +                }
 156.167 +            } else {
 156.168 +                isLibrary = true;
 156.169 +                Logger.getLogger(PythonIndexSearcher.class.getName()).fine("No fileobject for " + element.toString() + " with fileurl=" + element.getFilenameUrl());
 156.170 +            }
 156.171 +            if (projectName == null) {
 156.172 +                projectName = "";
 156.173 +            }
 156.174 +        }
 156.175 +
 156.176 +        @Override
 156.177 +        public Icon getProjectIcon() {
 156.178 +            if (projectName == null) {
 156.179 +                initProjectInfo();
 156.180 +            }
 156.181 +            if (isLibrary) {
 156.182 +                return ImageUtilities.loadImageIcon(ICON_PATH, false);
 156.183 +            }
 156.184 +            return projectIcon;
 156.185 +        }
 156.186 +
 156.187 +        @Override
 156.188 +        public FileObject getFileObject() {
 156.189 +            return element.getFileObject();
 156.190 +        }
 156.191 +
 156.192 +        @Override
 156.193 +        public void open() {
 156.194 +            PythonParserResult[] parserResultRet = new PythonParserResult[1];
 156.195 +            PythonTree node = PythonAstUtils.getForeignNode(element, parserResultRet);
 156.196 +
 156.197 +            if (node != null) {
 156.198 +                int astOffset = PythonAstUtils.getRange(node).getStart();
 156.199 +                int lexOffset = PythonLexerUtils.getLexerOffset(parserResultRet[0], astOffset);
 156.200 +                if (lexOffset == -1) {
 156.201 +                    lexOffset = 0;
 156.202 +                }
 156.203 +                GsfUtilities.open(element.getFileObject(), lexOffset, element.getName());
 156.204 +                return;
 156.205 +            }
 156.206 +
 156.207 +            FileObject fileObject = element.getFileObject();
 156.208 +            if (fileObject == null) {
 156.209 +                // This should no longer be needed - we perform auto deletion in GSF
 156.210 +                Toolkit.getDefaultToolkit().beep();
 156.211 +                return;
 156.212 +            }
 156.213 +
 156.214 +            helper.open(fileObject, element);
 156.215 +        }
 156.216 +
 156.217 +        @Override
 156.218 +        public String getContextName() {
 156.219 +            // XXX This is lame - move formatting logic to the goto action!
 156.220 +//            StringBuilder sb = new StringBuilder();
 156.221 +//            String require = element.getRequire();
 156.222 +//            String fqn = element.getFqn();
 156.223 +            String fqn = element.getIn() != null ? element.getIn() + "." + element.getName() : element.getName();
 156.224 +            if (element.getName().equals(fqn)) {
 156.225 +                fqn = null;
 156.226 +                String url = element.getFilenameUrl();
 156.227 +                if (url != null) {
 156.228 +                    return url.substring(url.lastIndexOf('/') + 1);
 156.229 +                }
 156.230 +            }
 156.231 +
 156.232 +            return fqn;
 156.233 +        }
 156.234 +
 156.235 +        @Override
 156.236 +        public ElementHandle getElement() {
 156.237 +            return element;
 156.238 +        }
 156.239 +
 156.240 +        @Override
 156.241 +        public int getOffset() {
 156.242 +            throw new UnsupportedOperationException("Not supported yet.");
 156.243 +        }
 156.244 +
 156.245 +        @Override
 156.246 +        public String getSimpleName() {
 156.247 +            return element.getName();
 156.248 +        }
 156.249 +
 156.250 +        @Override
 156.251 +        public String getOuterName() {
 156.252 +            return null;
 156.253 +        }
 156.254 +    }
 156.255 +}
   157.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   157.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonIndexer.java	Mon Sep 21 13:01:16 2015 +0200
   157.3 @@ -0,0 +1,1399 @@
   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.io.File;
  157.37 +import java.io.IOException;
  157.38 +import java.net.MalformedURLException;
  157.39 +import java.net.URL;
  157.40 +import java.util.ArrayList;
  157.41 +import java.util.Collections;
  157.42 +import java.util.HashMap;
  157.43 +import java.util.List;
  157.44 +import java.util.Map;
  157.45 +import java.util.logging.Level;
  157.46 +import java.util.logging.Logger;
  157.47 +import java.util.regex.Matcher;
  157.48 +import java.util.regex.Pattern;
  157.49 +import javax.swing.text.BadLocationException;
  157.50 +import org.netbeans.editor.BaseDocument;
  157.51 +import org.netbeans.modules.csl.spi.GsfUtilities;
  157.52 +import org.netbeans.modules.csl.spi.ParserResult;
  157.53 +import org.netbeans.modules.parsing.api.Snapshot;
  157.54 +import org.netbeans.modules.parsing.spi.Parser;
  157.55 +import org.netbeans.modules.parsing.spi.indexing.Context;
  157.56 +import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexer;
  157.57 +import org.netbeans.modules.parsing.spi.indexing.Indexable;
  157.58 +import org.netbeans.modules.parsing.spi.indexing.support.IndexDocument;
  157.59 +import org.netbeans.modules.parsing.spi.indexing.support.IndexingSupport;
  157.60 +import org.netbeans.modules.python.api.PythonPlatform;
  157.61 +import org.netbeans.modules.python.api.PythonPlatformManager;
  157.62 +import org.netbeans.modules.python.source.elements.IndexedElement;
  157.63 +import org.netbeans.modules.python.source.scopes.ScopeConstants;
  157.64 +import org.netbeans.modules.python.source.scopes.ScopeInfo;
  157.65 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  157.66 +import org.netbeans.modules.python.source.scopes.SymInfo;
  157.67 +import org.netbeans.modules.python.source.queries.DeprecationQuery;
  157.68 +import org.openide.filesystems.FileObject;
  157.69 +import org.openide.filesystems.FileUtil;
  157.70 +import org.openide.filesystems.URLMapper;
  157.71 +import org.openide.util.Exceptions;
  157.72 +import org.python.antlr.PythonTree;
  157.73 +import org.python.antlr.ast.ClassDef;
  157.74 +import org.python.antlr.ast.FunctionDef;
  157.75 +import org.python.antlr.ast.Module;
  157.76 +import org.python.antlr.ast.Name;
  157.77 +import org.python.antlr.base.expr;
  157.78 +
  157.79 +/**
  157.80 + *
  157.81 + * @todo Store information about all symbols exported by a module.
  157.82 + *  I can use that to provide "unused import" help.
  157.83 + * @todo Clean this stuff up: store data, functions, etc.
  157.84 + * @todo Improve detection of builtins. Perhaps run from within Python,
  157.85 + *   something like this:
  157.86 +>>> dir(__builtins__)
  157.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']
  157.88 + *
  157.89 + * My code for scanning for functions has to be smarter:
  157.90 +.. function:: ljust(s, width)
  157.91 +rjust(s, width)
  157.92 +center(s, width)
  157.93 + * Here I need to pick up all 3 signatures!
  157.94 + * @author Tor Norbye
  157.95 + */
  157.96 +public class PythonIndexer extends EmbeddingIndexer {
  157.97 +    public static final String NAME = "PythonIndexer";
  157.98 +    public static final int VERSION = 1;
  157.99 +    public static boolean PREINDEXING = Boolean.getBoolean("gsf.preindexing"); // NOI18N
 157.100 +    public static final String FIELD_MEMBER = "member"; //NOI18N
 157.101 +    public static final String FIELD_MODULE_NAME = "module"; //NOI18N
 157.102 +    public static final String FIELD_MODULE_ATTR_NAME = "modattrs"; //NOI18N
 157.103 +    public static final String FIELD_CLASS_ATTR_NAME = "clzattrs"; //NOI18N
 157.104 +    public static final String FIELD_EXTENDS_NAME = "extends"; //NOI18N
 157.105 +    public static final String FIELD_ITEM = "item"; //NOI18N
 157.106 +    public static final String FIELD_IN = "in"; //NOI18N
 157.107 +    public static final String FIELD_CLASS_NAME = "class"; //NOI18N
 157.108 +    public static final String FIELD_CASE_INSENSITIVE_CLASS_NAME = "class-ig"; //NOI18N
 157.109 +    private FileObject prevParent;
 157.110 +    private boolean prevResult;
 157.111 +
 157.112 +    public static boolean isIndexable(Indexable indexable, Snapshot snapshot) {
 157.113 +        FileObject fo = snapshot.getSource().getFileObject();
 157.114 +        String extension = fo.getExt();
 157.115 +        if ("py".equals(extension)) { // NOI18N
 157.116 +            return true;
 157.117 +        }
 157.118 +
 157.119 +        if ("rst".equals(extension)) { // NOI18N
 157.120 +            // Index restructured text if it looks like it contains Python library
 157.121 +            // definitions
 157.122 +            return true;
 157.123 +        }
 157.124 +
 157.125 +        if ("egg".equals(extension)) { // NOI18N
 157.126 +            return true;
 157.127 +        }
 157.128 +
 157.129 +        return false;
 157.130 +    }
 157.131 +
 157.132 +    
 157.133 +    public boolean isIndexable(Snapshot file) {
 157.134 +        FileObject fo = file.getSource().getFileObject();
 157.135 +        String extension = fo.getExt();
 157.136 +        if ("py".equals(extension)) { // NOI18N
 157.137 +
 157.138 +            // Skip "test" folders under lib... Lots of weird files there
 157.139 +            // and we don't want to pollute the index with them
 157.140 +            FileObject parent = fo.getParent();
 157.141 +
 157.142 +            if (parent != null && parent.getName().equals("test")) { // NOI18N
 157.143 +                // Make sure it's really a lib folder, we want to include the
 157.144 +                // user's files
 157.145 +
 157.146 +                // Avoid double-indexing files that have multiple versions - e.g. foo.js and foo-min.js
 157.147 +                // or foo.uncompressed
 157.148 +                FileObject parentFo = fo.getParent();
 157.149 +                if (prevParent == parentFo) {
 157.150 +                    return prevResult;
 157.151 +                }
 157.152 +                prevResult = true;
 157.153 +                prevParent = parentFo;
 157.154 +                PythonPlatformManager manager = PythonPlatformManager.getInstance();
 157.155 +                Platforms:
 157.156 +                for (String name : manager.getPlatformList()) {
 157.157 +                    PythonPlatform platform = manager.getPlatform(name);
 157.158 +                    if (platform != null) {
 157.159 +                        for (FileObject root : platform.getLibraryRoots()) {
 157.160 +                            if (FileUtil.isParentOf(root, parentFo)) {
 157.161 +                                prevResult = false;
 157.162 +                                break Platforms;
 157.163 +                            }
 157.164 +                        }
 157.165 +                    }
 157.166 +                }
 157.167 +            }
 157.168 +
 157.169 +            return true;
 157.170 +        }
 157.171 +
 157.172 +        if ("rst".equals(extension)) { // NOI18N
 157.173 +            // Index restructured text if it looks like it contains Python library
 157.174 +            // definitions
 157.175 +            return true;
 157.176 +        }
 157.177 +
 157.178 +        if ("egg".equals(extension)) { // NOI18N
 157.179 +            return true;
 157.180 +        }
 157.181 +
 157.182 +        return false;
 157.183 +    }
 157.184 +
 157.185 +    @Override
 157.186 +    protected void index(Indexable indexable, Parser.Result result, Context context) {
 157.187 +        PythonParserResult parseResult = (PythonParserResult)result;
 157.188 +        if (parseResult == null) {
 157.189 +            return;
 157.190 +        }
 157.191 +        
 157.192 +        IndexingSupport support;
 157.193 +        try {
 157.194 +            support = IndexingSupport.getInstance(context);
 157.195 +        } catch (IOException ioe) {
 157.196 +            LOG.log(Level.WARNING, null, ioe);
 157.197 +            return;
 157.198 +        }
 157.199 +        
 157.200 +        support.removeDocuments(indexable);
 157.201 +        
 157.202 +        FileObject fileObject = result.getSnapshot().getSource().getFileObject();
 157.203 +        String extension = fileObject.getNameExt();
 157.204 +
 157.205 +        if (extension.endsWith(".rst")) { // NOI18N
 157.206 +            scanRst(fileObject, indexable, support, null);
 157.207 +        } else if (extension.endsWith(".egg")) { // NOI18N
 157.208 +            scanEgg(fileObject, indexable, parseResult, support);
 157.209 +        } else {
 157.210 +            // Normal python file
 157.211 +            new IndexTask(parseResult, support).scan();
 157.212 +        }
 157.213 +    }
 157.214 +    private static final Logger LOG = Logger.getLogger(PythonIndexer.class.getName());
 157.215 +
 157.216 +    public boolean acceptQueryPath(String url) {
 157.217 +        return !url.contains("jsstubs"); // NOI18N
 157.218 +    }
 157.219 +
 157.220 +    public String getPersistentUrl(File file) {
 157.221 +        String url;
 157.222 +        try {
 157.223 +            url = file.toURI().toURL().toExternalForm();
 157.224 +
 157.225 +            // Make relative URLs for urls in the libraries
 157.226 +            return PythonIndex.getPreindexUrl(url);
 157.227 +        } catch (MalformedURLException ex) {
 157.228 +            Exceptions.printStackTrace(ex);
 157.229 +            return file.getPath();
 157.230 +        }
 157.231 +    }
 157.232 +
 157.233 +    public String getIndexVersion() {
 157.234 +        return "0.123"; // NOI18N
 157.235 +    }
 157.236 +
 157.237 +    public String getIndexerName() {
 157.238 +        return "python"; // NOI18N
 157.239 +    }
 157.240 +
 157.241 +    public FileObject getPreindexedDb() {
 157.242 +        return null;
 157.243 +    }
 157.244 +
 157.245 +    private static void appendFlags(StringBuilder sb, char c, SymInfo sym, int flags) {
 157.246 +        sb.append(';');
 157.247 +        sb.append(c);
 157.248 +        sb.append(';');
 157.249 +
 157.250 +        if (sym.isPrivate()) {
 157.251 +            flags |= IndexedElement.PRIVATE;
 157.252 +        }
 157.253 +        if (c == 'c') {
 157.254 +            flags |= IndexedElement.CONSTRUCTOR;
 157.255 +        }
 157.256 +
 157.257 +        sb.append(IndexedElement.encode(flags));
 157.258 +        sb.append(';');
 157.259 +    }
 157.260 +    private static final int DEFAULT_DOC_SIZE = 40; // TODO Measure
 157.261 +
 157.262 +    private static class IndexTask {
 157.263 +        private PythonParserResult result;
 157.264 +        private FileObject file;
 157.265 +        private IndexingSupport support;
 157.266 +        private List<IndexDocument> documents = new ArrayList<>();
 157.267 +        private String url;
 157.268 +        private String module;
 157.269 +        private SymbolTable symbolTable;
 157.270 +        private String overrideUrl;
 157.271 +
 157.272 +        private IndexTask(PythonParserResult result, IndexingSupport support) {
 157.273 +            this.result = result;
 157.274 +            this.file = result.getSnapshot().getSource().getFileObject();
 157.275 +            this.support = support;
 157.276 +
 157.277 +            module = PythonUtils.getModuleName(file);
 157.278 +            //PythonTree root = PythonAstUtils.getRoot(result);
 157.279 +            //if (root instanceof Module) {
 157.280 +            //    Str moduleDoc = PythonAstUtils.getDocumentationNode(root);
 157.281 +            //    if (moduleDoc != null) {
 157.282 +            //        moduleAttributes = "d(" + moduleDoc.getCharStartIndex() + ")";
 157.283 +            //    }
 157.284 +            //}
 157.285 +        }
 157.286 +
 157.287 +        private IndexTask(PythonParserResult result, IndexingSupport support, String overrideUrl) {
 157.288 +            this(result, support);
 157.289 +            this.overrideUrl = overrideUrl;
 157.290 +        }
 157.291 +
 157.292 +        public List<IndexDocument> scan() {
 157.293 +            url = file.toURL().toExternalForm();
 157.294 +            // Make relative URLs for urls in the libraries
 157.295 +            url = PythonIndex.getPreindexUrl(url);
 157.296 +
 157.297 +            IndexDocument doc = createDocument();
 157.298 +            doc.addPair(FIELD_MODULE_NAME, module, true, true);
 157.299 +
 157.300 +            String moduleAttrs = null;
 157.301 +            if (url.startsWith(PythonIndex.CLUSTER_URL) || url.startsWith(PythonIndex.PYTHONHOME_URL)) {
 157.302 +                moduleAttrs = "S"; // NOI18N
 157.303 +            } else if (PREINDEXING) {
 157.304 +                String prj = System.getProperty("gsf.preindexing.projectpath");
 157.305 +                if (prj != null && !url.contains(prj)) {
 157.306 +                    System.err.println("WARNING -- not marking url " + url + " from " + file + " as a system library!");
 157.307 +                }
 157.308 +            }
 157.309 +            if (DeprecationQuery.isDeprecatedModule(module)) {
 157.310 +                if (moduleAttrs == null) {
 157.311 +                    moduleAttrs = "D"; // NOI18N
 157.312 +                } else {
 157.313 +                    moduleAttrs += "D"; // NOI18N
 157.314 +                }
 157.315 +            }
 157.316 +            if (moduleAttrs != null) {
 157.317 +                doc.addPair(FIELD_MODULE_ATTR_NAME, moduleAttrs, false, true);
 157.318 +            }
 157.319 +
 157.320 +            PythonTree root = PythonAstUtils.getRoot(result);
 157.321 +            if (root == null) {
 157.322 +                return documents;
 157.323 +            }
 157.324 +            if (!(root instanceof Module)) {
 157.325 +                // Unexpected... http://netbeans.org/bugzilla/show_bug.cgi?id=165756
 157.326 +                // Maybe some kind of top level error node?
 157.327 +                System.err.println("WARNING - top level AST node type was " + root + " of type " + root.getClass().getName());
 157.328 +                return documents;
 157.329 +            }
 157.330 +            symbolTable = result.getSymbolTable();
 157.331 +            ScopeInfo scopeInfo = symbolTable.getScopeInfo(root);
 157.332 +            for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 157.333 +                String name = entry.getKey();
 157.334 +                SymInfo sym = entry.getValue();
 157.335 +
 157.336 +                if (sym.isClass()) {
 157.337 +                    StringBuilder sig = new StringBuilder();
 157.338 +                    sig.append(name);
 157.339 +                    appendFlags(sig, 'C', sym, 0);
 157.340 +                    doc.addPair(FIELD_ITEM, sig.toString(), true, true);
 157.341 +
 157.342 +                    if (sym.node instanceof ClassDef) {
 157.343 +                        assert sym.node instanceof ClassDef : sym.node;
 157.344 +                        indexClass(name, sym, (ClassDef)sym.node);
 157.345 +                    } else {
 157.346 +                        // Could be a symbol defined both as a class and a function
 157.347 +                        // (conditionally) such as _Environ in minicompat.py,
 157.348 +                        // and another trigger in socket.py.
 157.349 +                    }
 157.350 +                } else if (sym.isFunction()) {
 157.351 +                    if (sym.node instanceof Name) {
 157.352 +                        assert false : "Unexpected non-function node, " + ((Name)sym.node).getInternalId() + " - from symbol " + name + " in " + file + " with sym=" + sym;
 157.353 +                    }
 157.354 +                    assert sym.node instanceof FunctionDef : sym.node;
 157.355 +                    FunctionDef def = (FunctionDef)sym.node;
 157.356 +                    String sig = computeFunctionSig(name, def, sym);
 157.357 +                    doc.addPair(FIELD_ITEM, sig, true, true);
 157.358 +                } else if (sym.isImported()) {
 157.359 +                    if (!"*".equals(name)) { // NOI18N
 157.360 +                        StringBuilder sig = new StringBuilder();
 157.361 +                        sig.append(name);
 157.362 +                        appendFlags(sig, 'I', sym, 0);
 157.363 +                        doc.addPair(FIELD_ITEM, sig.toString(), true, true);
 157.364 +                    }
 157.365 +                } else if (sym.isGeneratorExp()) {
 157.366 +                    StringBuilder sig = new StringBuilder();
 157.367 +                    sig.append(name);
 157.368 +                    appendFlags(sig, 'G', sym, 0);
 157.369 +                    doc.addPair(FIELD_ITEM, sig.toString(), true, true);
 157.370 +                } else if (sym.isData()) {
 157.371 +                    StringBuilder sig = new StringBuilder();
 157.372 +                    sig.append(name);
 157.373 +                    appendFlags(sig, 'D', sym, 0);
 157.374 +                    doc.addPair(FIELD_ITEM, sig.toString(), true, true);
 157.375 +                } else {
 157.376 +                    // XXX what the heck is this??
 157.377 +                }
 157.378 +            }
 157.379 +
 157.380 +            return documents;
 157.381 +        }
 157.382 +
 157.383 +        private void indexClass(String className, SymInfo classSym, ClassDef clz) {
 157.384 +            IndexDocument classDocument = createDocument();
 157.385 +            classDocument.addPair(FIELD_IN, module, true, true);
 157.386 +
 157.387 +            // Superclass
 157.388 +            List<expr> bases = clz.getInternalBases();
 157.389 +            if (bases != null) {
 157.390 +                for (expr base : bases) {
 157.391 +                    String extendsName = PythonAstUtils.getExprName(base);
 157.392 +                    if (extendsName != null) {
 157.393 +                        classDocument.addPair(FIELD_EXTENDS_NAME, extendsName, true, true);
 157.394 +                    }
 157.395 +                }
 157.396 +            }
 157.397 +
 157.398 +            classDocument.addPair(FIELD_CLASS_NAME, className, true, true);
 157.399 +
 157.400 +            if (classSym.isPrivate()) {
 157.401 +                // TODO - store Documented, Deprecated, DocOnly, etc.
 157.402 +                classDocument.addPair(FIELD_CLASS_ATTR_NAME, IndexedElement.encode(IndexedElement.PRIVATE), false, true);
 157.403 +            }
 157.404 +            classDocument.addPair(FIELD_CASE_INSENSITIVE_CLASS_NAME, className.toLowerCase(), true, true);
 157.405 +
 157.406 +            //Str doc = PythonAstUtils.getDocumentationNode(clz);
 157.407 +            //if (doc != null) {
 157.408 +            //    StringBuilder sb = new StringBuilder();
 157.409 +            //    sb.append("d("); // NOI18N
 157.410 +            //    sb.append(doc.getCharStartIndex());
 157.411 +            //    sb.append(")"); // NOI18N
 157.412 +            //    classDocument.addPair(FIELD_CLASS_ATTRS, sb.toString(), false);
 157.413 +            //}
 157.414 +
 157.415 +            ScopeInfo scopeInfo = symbolTable.getScopeInfo(clz);
 157.416 +            for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 157.417 +                String name = entry.getKey();
 157.418 +                SymInfo sym = entry.getValue();
 157.419 +
 157.420 +//                int flags = sym.flags;
 157.421 +//                assert !sym.isClass() : "found a class " + name + " of type " + sym.dumpFlags(scopeInfo) + " within class " + className + " in module " + module;
 157.422 +//                if (!(sym.isFunction() || sym.isMember() || sym.isData())) {
 157.423 +//                }
 157.424 +//                assert sym.isFunction() || sym.isMember() || sym.isData() : name + ";" + sym.toString();
 157.425 +
 157.426 +                if (sym.isClass()) {
 157.427 +                    // Triggers in httplib _socket_close inside FakeSocket
 157.428 +                    StringBuilder sig = new StringBuilder();
 157.429 +                    sig.append(name);
 157.430 +                    appendFlags(sig, 'C', sym, 0);
 157.431 +                    classDocument.addPair(FIELD_ITEM, sig.toString(), true, true);
 157.432 +
 157.433 +                } else if (sym.isFunction() && sym.node instanceof FunctionDef) {
 157.434 +                    if (sym.node instanceof Name) {
 157.435 +                        assert false : "Unexpected non-function node, " + ((Name)sym.node).getInternalId() + " - from symbol " + name + " in " + file + " with sym=" + sym;
 157.436 +                    }
 157.437 +                    FunctionDef def = (FunctionDef)sym.node;
 157.438 +                    String sig = computeFunctionSig(name, def, sym);
 157.439 +                    classDocument.addPair(FIELD_MEMBER, sig, true, true);
 157.440 +                } else if (sym.isData()) {
 157.441 +                    StringBuilder sig = new StringBuilder();
 157.442 +                    sig.append(name);
 157.443 +                    appendFlags(sig, 'D', sym, 0);
 157.444 +                    classDocument.addPair(FIELD_MEMBER, sig.toString(), true, true);
 157.445 +                } else if (sym.isMember()) {
 157.446 +                    StringBuilder sig = new StringBuilder();
 157.447 +                    sig.append(name);
 157.448 +                    appendFlags(sig, 'A', sym, 0);
 157.449 +                    classDocument.addPair(FIELD_MEMBER, sig.toString(), true, true);
 157.450 +                } else if (!sym.isBound()) {
 157.451 +                    continue;
 157.452 +                } else {
 157.453 +                    // XXX what the heck is this??
 157.454 +                    assert false : className + "::" + name + " : " + sym.dumpFlags(scopeInfo);
 157.455 +                }
 157.456 +            }
 157.457 +
 157.458 +            if (scopeInfo.attributes.size() > 0) {
 157.459 +                for (Map.Entry<String, SymInfo> entry : scopeInfo.attributes.entrySet()) {
 157.460 +                    String name = entry.getKey();
 157.461 +                    SymInfo sym = entry.getValue();
 157.462 +
 157.463 +                    if (sym.isClass()) {
 157.464 +                        // Triggers in httplib _socket_close inside FakeSocket
 157.465 +                        StringBuilder sig = new StringBuilder();
 157.466 +                        sig.append(name);
 157.467 +                        appendFlags(sig, 'C', sym, 0);
 157.468 +                        classDocument.addPair(FIELD_ITEM, sig.toString(), true, true);
 157.469 +
 157.470 +                    } else if (sym.isFunction() && sym.node instanceof FunctionDef) {
 157.471 +                        if (sym.node instanceof Name) {
 157.472 +                            assert false : "Unexpected non-function node, " + ((Name)sym.node).getInternalId() + " - from symbol " + name + " in " + file + " with sym=" + sym;
 157.473 +                        }
 157.474 +                        FunctionDef def = (FunctionDef)sym.node;
 157.475 +                        String sig = computeFunctionSig(name, def, sym);
 157.476 +                        classDocument.addPair(FIELD_MEMBER, sig, true, true);
 157.477 +                    } else if (sym.isData()) {
 157.478 +                        StringBuilder sig = new StringBuilder();
 157.479 +                        sig.append(name);
 157.480 +                        appendFlags(sig, 'D', sym, 0);
 157.481 +                        classDocument.addPair(FIELD_MEMBER, sig.toString(), true, true);
 157.482 +                    } else if (sym.isMember()) {
 157.483 +                        StringBuilder sig = new StringBuilder();
 157.484 +                        sig.append(name);
 157.485 +                        appendFlags(sig, 'A', sym, 0);
 157.486 +                        classDocument.addPair(FIELD_MEMBER, sig.toString(), true, true);
 157.487 +                    } else if (!sym.isBound()) {
 157.488 +                        continue;
 157.489 +                    } else {
 157.490 +                        // XXX what the heck is this??
 157.491 +                        assert false : className + "::" + name + " : " + sym.dumpFlags(scopeInfo);
 157.492 +                    }
 157.493 +                }
 157.494 +            }
 157.495 +        }
 157.496 +
 157.497 +
 157.498 +// TODO - what about nested functions?
 157.499 +        private IndexDocument createDocument() {
 157.500 +            IndexDocument doc = support.createDocument(file);
 157.501 +            documents.add(doc);
 157.502 +
 157.503 +            return doc;
 157.504 +        }
 157.505 +    }
 157.506 +
 157.507 +    public static String computeClassSig(ClassDef def, SymInfo sym) {
 157.508 +        StringBuilder sig = new StringBuilder();
 157.509 +        sig.append(def.getInternalName());
 157.510 +        appendFlags(sig, 'C', sym, 0);
 157.511 +
 157.512 +        return sig.toString();
 157.513 +    }
 157.514 +
 157.515 +    public static String computeFunctionSig(String name, FunctionDef def, SymInfo sym) {
 157.516 +        StringBuilder sb = new StringBuilder();
 157.517 +        sb.append(name);
 157.518 +        char type;
 157.519 +        int flags = 0;
 157.520 +        if ("__init__".equals(name)) { // NOI18N
 157.521 +            type = 'c';
 157.522 +        } else {
 157.523 +            type = 'F';
 157.524 +
 157.525 +            List<expr> decorators = def.getInternalDecorator_list();
 157.526 +            if (decorators != null && decorators.size() > 0) {
 157.527 +                for (expr decorator : decorators) {
 157.528 +                    String decoratorName = PythonAstUtils.getExprName(decorator);
 157.529 +                    if ("property".equals(decoratorName)) { // NOI18N
 157.530 +                        type = 'A';
 157.531 +                    } else if ("classmethod".equals(decoratorName)) { // NOI18N
 157.532 +                        // Classmethods seem to be used mostly for constructors/inherited factories
 157.533 +                        type = 'c';
 157.534 +                        flags |= IndexedElement.CONSTRUCTOR | IndexedElement.STATIC;
 157.535 +                    } else if ("staticmethod".equals(decoratorName)) { // NOI18N
 157.536 +                        flags |= IndexedElement.STATIC;
 157.537 +                    }
 157.538 +                }
 157.539 +            }
 157.540 +        }
 157.541 +        appendFlags(sb, type, sym, flags);
 157.542 +
 157.543 +        List<String> params = PythonAstUtils.getParameters(def);
 157.544 +        boolean first = true;
 157.545 +        for (String param : params) {
 157.546 +            if (first) {
 157.547 +                first = false;
 157.548 +            } else {
 157.549 +                sb.append(',');
 157.550 +            }
 157.551 +            sb.append(param);
 157.552 +        }
 157.553 +        sb.append(';');
 157.554 +        String sig = sb.toString();
 157.555 +        return sig;
 157.556 +    }
 157.557 +
 157.558 +    private String cleanupSignature(String signature) {
 157.559 +        // Clean up signatures - remove [optional] areas, deal
 157.560 +        //   with arg=Default.Value parameters,
 157.561 +        //   or "literal" or (lit,er,al) default values.
 157.562 +        // See unit tests for details.
 157.563 +        boolean lastWasComma = false;
 157.564 +        StringBuilder sb = new StringBuilder();
 157.565 +        Loop:
 157.566 +        for (int i = 0, n = signature.length(); i < n; i++) {
 157.567 +            char c = signature.charAt(i);
 157.568 +            switch (c) {
 157.569 +            case ' ':
 157.570 +            case '[':
 157.571 +            case ']':
 157.572 +            case '\'':
 157.573 +            case '"':
 157.574 +            case '.':
 157.575 +                continue Loop;
 157.576 +            case '=': {
 157.577 +                int level = 0;
 157.578 +                for (i++; i < n; i++) {
 157.579 +                    c = signature.charAt(i);
 157.580 +                    if (c == '(') {
 157.581 +                        level++;
 157.582 +                    } else if (c == ')') {
 157.583 +                        if (level == 0) {
 157.584 +                            break;
 157.585 +                        }
 157.586 +                        level--;
 157.587 +                    }
 157.588 +                    if (c == ',' && level == 0) {
 157.589 +                        break;
 157.590 +                    }
 157.591 +                }
 157.592 +                i--; // compensate for loop-increment
 157.593 +                continue Loop;
 157.594 +            }
 157.595 +            case ')':
 157.596 +                if (lastWasComma) {
 157.597 +                    sb.setLength(sb.length() - 1);
 157.598 +                    lastWasComma = false;
 157.599 +                }
 157.600 +                break;
 157.601 +            case ',':
 157.602 +                if (lastWasComma) {
 157.603 +                    continue Loop;
 157.604 +                }
 157.605 +                lastWasComma = true;
 157.606 +                break;
 157.607 +            default:
 157.608 +                lastWasComma = false;
 157.609 +            }
 157.610 +            sb.append(c);
 157.611 +        }
 157.612 +
 157.613 +        return sb.toString();
 157.614 +    }
 157.615 +
 157.616 +    /**
 157.617 +     * Determine if the definition beginning on lines[lineno] is deprecated.
 157.618 +     */
 157.619 +    private boolean isDeprecated(String[] lines, int lineno) {
 157.620 +        int firstIndent = RstFormatter.getIndentation(lines[lineno], 0);
 157.621 +        for (int i = lineno + 1; i < lines.length; i++) {
 157.622 +            String line = lines[i];
 157.623 +            int indent = RstFormatter.getIndentation(line, 0);
 157.624 +            if (indent == -1) { // empty line
 157.625 +                continue;
 157.626 +            }
 157.627 +            if (line.contains(":deprecated:") || line.contains(".. deprecated::")) { // NOI18N
 157.628 +                return true;
 157.629 +            }
 157.630 +            // Note - we checked for ::deprecated BEFORE bailing on the next
 157.631 +            // same-indent line, because in some cases, these appear on the same
 157.632 +            // level as the deprecated element (for exampe, modules)
 157.633 +            if (indent <= firstIndent) {
 157.634 +                return false;
 157.635 +            }
 157.636 +
 157.637 +            // For classes we can have embedded definitions of functions/data/methods --
 157.638 +            // a deprecated note for these should not be considered a deprecation of
 157.639 +            // the whole class! See the unit test for bz2.zip for example.
 157.640 +            if (line.startsWith(".. attribute::", indent) || // NOI18N
 157.641 +                    line.startsWith(".. data::", indent) || // NOI18N
 157.642 +                    line.startsWith(".. function::", indent) || // NOI18N
 157.643 +                    line.startsWith(".. method::", indent)) { // NOI18N
 157.644 +                return false;
 157.645 +            }
 157.646 +        }
 157.647 +
 157.648 +        return false;
 157.649 +    }
 157.650 +
 157.651 +    private static class CachedIndexDocument {
 157.652 +        private List<CachedIndexDocumentEntry> entries = new ArrayList<>(DEFAULT_DOC_SIZE);
 157.653 +
 157.654 +        private void addPair(String key, String value, boolean index) {
 157.655 +            entries.add(new CachedIndexDocumentEntry(key, value, index));
 157.656 +        }
 157.657 +    }
 157.658 +
 157.659 +    private static class CachedIndexDocumentEntry {
 157.660 +        private String key;
 157.661 +        private String value;
 157.662 +        private boolean index;
 157.663 +
 157.664 +        public CachedIndexDocumentEntry(String key, String value, boolean index) {
 157.665 +            this.key = key;
 157.666 +            this.value = value;
 157.667 +            this.index = index;
 157.668 +        }
 157.669 +    }
 157.670 +
 157.671 +    private List<IndexDocument> scanRst(FileObject fo, Indexable indexable, IndexingSupport support, String overrideUrl) {
 157.672 +        List<CachedIndexDocument> documents = new ArrayList<>();
 157.673 +
 157.674 +        List<IndexDocument> docs = new ArrayList<>();
 157.675 +        
 157.676 +        if (fo != null) {
 157.677 +            String module = fo.getNameExt();
 157.678 +            assert module.endsWith(".rst"); // NOI18N
 157.679 +            module = module.substring(0, module.length() - 4);
 157.680 +
 157.681 +            // Skip files that are already in the standard Python libraries (as .py files).
 157.682 +            // For these, normal scanning applies
 157.683 +            // (I should consider checking that they are consistent with the official
 157.684 +            // documentation, at least during preindexing)
 157.685 +            if (PREINDEXING) {
 157.686 +                // XXX This doesn't work right for anything but the builtin Jython interpreter....
 157.687 +                // OTOH that's the only thing we're preindexing at this point
 157.688 +                FileObject lib = getLibDir();
 157.689 +                if (lib != null) {
 157.690 +                    String path = module.replace('.', '/');
 157.691 +                    FileObject py = lib.getFileObject(path); // Look for package dir
 157.692 +                    if (py == null) {
 157.693 +                        py = lib.getFileObject(path + ".py"); // NOI18N
 157.694 +                    }
 157.695 +                    if (py != null) {
 157.696 +                        System.err.println("DELETE " + FileUtil.getFileDisplayName(fo) + " because there is a corresponding " + FileUtil.getFileDisplayName(py)); // NOI18N
 157.697 +                        // No - it's in a zip archive now
 157.698 +                        //try {
 157.699 +                        //    // Delete it!
 157.700 +                        //    fo.delete();
 157.701 +                        //} catch (IOException ex) {
 157.702 +                        //    Exceptions.printStackTrace(ex);
 157.703 +                        //}
 157.704 +                        return Collections.emptyList();
 157.705 +                    }
 157.706 +                }
 157.707 +            }
 157.708 +
 157.709 +            String name = fo.getName();
 157.710 +
 157.711 +            // Skip some really obsolete libraries -- IRIX only etc
 157.712 +            if (name.equals("gl") || name.equals("cd") || // NOI18N
 157.713 +                    name.equals("al") || name.equals("fm") ||
 157.714 +                    name.equals("fl") || name.equals("imgfile") || // NOI18N
 157.715 +                    name.equals("jpeg") || // NOI18N
 157.716 +                    name.equals("sunau") || name.equals("sunaudio")) { // NOI!8N
 157.717 +                return Collections.emptyList();
 157.718 +            }
 157.719 +
 157.720 +            Pattern PATTERN = Pattern.compile("\\s*\\.\\.\\s+(.*)::\\s*(.+)\\s*"); // NOI18N
 157.721 +
 157.722 +            BaseDocument doc = GsfUtilities.getDocument(fo, true);
 157.723 +            if (doc != null) {
 157.724 +                Map<String, CachedIndexDocument> classDocs = new HashMap<>();
 157.725 +                CachedIndexDocument document = null;
 157.726 +                try {
 157.727 +                    String text = doc.getText(0, doc.getLength());
 157.728 +                    String[] lines = text.split("\n");
 157.729 +                    String currentClass = null;
 157.730 +
 157.731 +                    for (int lineno = 0, maxLines = lines.length; lineno < maxLines; lineno++) {
 157.732 +                        String line = lines[lineno];
 157.733 +                        if (!line.startsWith(".. ") && !line.contains(" .. ")) { // NOI18N
 157.734 +                            continue;
 157.735 +                        }
 157.736 +
 157.737 +                        Matcher m = PATTERN.matcher(line);
 157.738 +                        if (m.matches()) {
 157.739 +                            String key = m.group(1);
 157.740 +
 157.741 +                            if (key.equals("attribute") || // NOI18N
 157.742 +                                    key.equals("currentmodule") || // NOI18N
 157.743 +                                    key.equals("class") || // NOI18N
 157.744 +                                    key.equals("exception") || // NOI18N
 157.745 +                                    key.equals("function") || // NOI18N
 157.746 +                                    key.equals("method") || // NOI18N
 157.747 +                                    key.equals("data") || // NOI18N
 157.748 +                                    key.equals("module")) {  // NOI18N
 157.749 +
 157.750 +
 157.751 +                                if (key.equals("module") || key.equals("currentmodule")) {  // NOI18N
 157.752 +                                    // TODO - determine package name
 157.753 +                                    module = m.group(2);
 157.754 +                                    document = new CachedIndexDocument();
 157.755 +                                    documents.add(document);
 157.756 +                                    document.addPair(FIELD_MODULE_NAME, module, true);
 157.757 +                                    String moduleAttrs = "S";
 157.758 +                                    if (isDeprecated(lines, lineno)) {
 157.759 +                                        moduleAttrs = "SD";
 157.760 +                                    }
 157.761 +                                    document.addPair(FIELD_MODULE_ATTR_NAME, moduleAttrs, false); // NOI18N
 157.762 +                                } else {
 157.763 +                                    // Methods described in an rst without an actual module definition...
 157.764 +                                    if (document == null) {
 157.765 +                                        document = new CachedIndexDocument();
 157.766 +                                        documents.add(document);
 157.767 +                                        document.addPair(FIELD_MODULE_NAME, module, true);
 157.768 +                                        document.addPair(FIELD_MODULE_ATTR_NAME, "S", false); // NOI18N
 157.769 +                                    }
 157.770 +                                    if (key.equals("method") || key.equals("attribute")) { // NOI18N) { // NOI18N
 157.771 +                                        String signature = m.group(2);
 157.772 +
 157.773 +                                        if ("string.template".equals(signature)) { // NOI18N
 157.774 +                                            // Wrong - ignore this one (ends up on the String class)
 157.775 +                                            continue;
 157.776 +                                        }
 157.777 +                                        if (signature.startsWith("somenamedtuple.")) {
 157.778 +                                            // Ditto
 157.779 +                                            continue;
 157.780 +                                        }
 157.781 +                                        // Error in mailbox.rst - Python 2.6
 157.782 +                                        if (".et_folder(folder)".equals(signature)) {
 157.783 +                                            signature = "get_folder(folder)";
 157.784 +                                        }
 157.785 +
 157.786 +                                        int dot = signature.indexOf('.');
 157.787 +                                        if (dot != -1) {
 157.788 +                                            int paren = signature.indexOf('(');
 157.789 +                                            if (paren == -1 || paren > dot) {
 157.790 +                                                assert signature.matches("\\w+\\.\\w+.*") : signature;
 157.791 +                                                String dottedName = signature.substring(0, dot);
 157.792 +                                                CachedIndexDocument dottedDoc = classDocs.get(dottedName);
 157.793 +                                                if (dottedDoc != null) {
 157.794 +                                                    currentClass = dottedName;
 157.795 +                                                } else /*if (currentClass == null)*/ {
 157.796 +                                                    currentClass = dottedName;
 157.797 +                                                    // New class without class:: declaration first.
 157.798 +                                                    CachedIndexDocument classDocument = new CachedIndexDocument();
 157.799 +                                                    documents.add(classDocument);
 157.800 +                                                    classDocs.put(currentClass, classDocument);
 157.801 +                                                    classDocument.addPair(FIELD_IN, module, true);
 157.802 +
 157.803 +                                                    classDocument.addPair(FIELD_CLASS_NAME, currentClass, true);
 157.804 +                                                    classDocument.addPair(FIELD_CASE_INSENSITIVE_CLASS_NAME, currentClass.toLowerCase(), true);
 157.805 +                                                }
 157.806 +                                                signature = signature.substring(dot + 1);
 157.807 +                                            }
 157.808 +                                        }
 157.809 +
 157.810 +
 157.811 +                                        CachedIndexDocument classDocument = classDocs.get(currentClass);
 157.812 +                                        assert classDocs != null;
 157.813 +
 157.814 +                                        if (key.equals("method")) {
 157.815 +                                            signature = cleanupSignature(signature);
 157.816 +                                            if (signature.indexOf('(') == -1) {
 157.817 +                                                signature = signature + "()";
 157.818 +                                            }
 157.819 +
 157.820 +                                            assert signature.indexOf('(') != -1 && signature.indexOf(')') != -1 &&
 157.821 +                                                    signature.indexOf(')') > signature.indexOf('(') : signature;
 157.822 +                                            int lparen = signature.indexOf('(');
 157.823 +                                            int rparen = signature.indexOf(')', lparen + 1);
 157.824 +                                            if (lparen != -1 && rparen != -1) {
 157.825 +                                                String methodName = signature.substring(0, lparen);
 157.826 +                                                String args = signature.substring(lparen + 1, rparen);
 157.827 +                                                char type;
 157.828 +                                                if (methodName.equals("__init__")) { // NOI18N
 157.829 +                                                    type = 'c';
 157.830 +                                                } else {
 157.831 +                                                    type = 'F';
 157.832 +                                                }
 157.833 +                                                StringBuilder sig = new StringBuilder();
 157.834 +                                                sig.append(methodName);
 157.835 +
 157.836 +                                                int symFlags = 0;
 157.837 +                                                if (NameStyle.isPrivateName(methodName)) {
 157.838 +                                                    symFlags |= ScopeConstants.PRIVATE;
 157.839 +                                                }
 157.840 +                                                // TODO - look up deprecated etc.
 157.841 +                                                SymInfo fakeSym = new SymInfo(symFlags);
 157.842 +
 157.843 +                                                int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
 157.844 +                                                if (isDeprecated(lines, lineno)) {
 157.845 +                                                    flags |= IndexedElement.DEPRECATED;
 157.846 +                                                }
 157.847 +
 157.848 +                                                appendFlags(sig, type, fakeSym, flags);
 157.849 +                                                sig.append(args);
 157.850 +                                                sig.append(';');
 157.851 +
 157.852 +                                                classDocument.addPair(FIELD_MEMBER, sig.toString(), true);
 157.853 +                                            }
 157.854 +                                        } else {
 157.855 +                                            assert key.equals("attribute");
 157.856 +
 157.857 +                                            StringBuilder sig = new StringBuilder();
 157.858 +                                            sig.append(signature);
 157.859 +                                            int symFlags = 0;
 157.860 +                                            if (NameStyle.isPrivateName(signature)) {
 157.861 +                                                symFlags |= ScopeConstants.PRIVATE;
 157.862 +                                            }
 157.863 +                                            // TODO - look up deprecated etc.
 157.864 +                                            SymInfo fakeSym = new SymInfo(symFlags);
 157.865 +
 157.866 +                                            int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
 157.867 +                                            if (isDeprecated(lines, lineno)) {
 157.868 +                                                flags |= IndexedElement.DEPRECATED;
 157.869 +                                            }
 157.870 +
 157.871 +
 157.872 +                                            appendFlags(sig, 'A', fakeSym, flags);
 157.873 +                                            classDocument.addPair(FIELD_MEMBER, sig.toString(), true);
 157.874 +                                        }
 157.875 +                                    } else if (key.equals("class") || key.equals("exception")) { // NOI18N
 157.876 +                                        assert module != null;
 157.877 +                                        String cls = m.group(2);
 157.878 +
 157.879 +                                        int paren = cls.indexOf('(');
 157.880 +                                        String constructor = null;
 157.881 +                                        if (paren != -1) {
 157.882 +                                            // Some documents specify a constructor here
 157.883 +                                            constructor = cleanupSignature(cls);
 157.884 +                                            cls = cls.substring(0, paren);
 157.885 +                                        }
 157.886 +                                        currentClass = cls;
 157.887 +
 157.888 +                                        CachedIndexDocument classDocument = new CachedIndexDocument();
 157.889 +                                        classDocs.put(currentClass, classDocument);
 157.890 +                                        documents.add(classDocument);
 157.891 +                                        classDocument.addPair(FIELD_IN, module, true);
 157.892 +
 157.893 +                                        if (key.equals("exception") && !"Exception".equals(cls)) { // NOI18N
 157.894 +                                            classDocument.addPair(FIELD_EXTENDS_NAME, "Exception", true); // NOI18N
 157.895 +                                        }
 157.896 +
 157.897 +                                        classDocument.addPair(FIELD_CLASS_NAME, cls, true);
 157.898 +                                        int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY | IndexedElement.CONSTRUCTOR;
 157.899 +                                        if (isDeprecated(lines, lineno)) {
 157.900 +                                            flags |= IndexedElement.DEPRECATED;
 157.901 +                                        }
 157.902 +                                        if (flags != 0) {
 157.903 +                                            // TODO - store Documented, Deprecated, DocOnly, etc.
 157.904 +                                            classDocument.addPair(FIELD_CLASS_ATTR_NAME, IndexedElement.encode(flags), false);
 157.905 +                                        }
 157.906 +                                        classDocument.addPair(FIELD_CASE_INSENSITIVE_CLASS_NAME, cls.toLowerCase(), true);
 157.907 +
 157.908 +                                        // TODO - determine extends
 157.909 +                                        //document.addPair(FIELD_EXTENDS_NAME, superClass, true);
 157.910 +
 157.911 +                                        if (constructor != null) {
 157.912 +                                            assert constructor.indexOf('(') != -1 && constructor.indexOf(')') != -1 &&
 157.913 +                                                    constructor.indexOf(')') > constructor.indexOf('(') : constructor;
 157.914 +
 157.915 +                                            String signature = constructor;
 157.916 +                                            int lparen = signature.indexOf('(');
 157.917 +                                            int rparen = signature.indexOf(')', lparen + 1);
 157.918 +                                            if (lparen != -1 && rparen != -1) {
 157.919 +                                                //String methodName = signature.substring(0, lparen);
 157.920 +                                                String methodName = "__init__"; // The constructor is always __init__ !
 157.921 +                                                String args = signature.substring(lparen + 1, rparen);
 157.922 +                                                StringBuilder sig = new StringBuilder();
 157.923 +                                                sig.append(methodName);
 157.924 +                                                int symFlags = 0;
 157.925 +                                                if (NameStyle.isPrivateName(methodName)) {
 157.926 +                                                    symFlags |= ScopeConstants.PRIVATE;
 157.927 +                                                }
 157.928 +                                                // TODO - look up deprecated etc.
 157.929 +                                                SymInfo fakeSym = new SymInfo(symFlags);
 157.930 +
 157.931 +                                                flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY | IndexedElement.CONSTRUCTOR;
 157.932 +                                                if (isDeprecated(lines, lineno)) {
 157.933 +                                                    flags |= IndexedElement.DEPRECATED;
 157.934 +                                                }
 157.935 +
 157.936 +                                                appendFlags(sig, 'c', fakeSym, flags);
 157.937 +                                                sig.append(args);
 157.938 +                                                sig.append(';');
 157.939 +
 157.940 +                                                classDocument.addPair(FIELD_MEMBER, sig.toString(), true);
 157.941 +                                            }
 157.942 +
 157.943 +                                        }
 157.944 +                                    } else if (key.equals("function") || (key.equals("data") && m.group(2).contains("("))) { // NOI18N
 157.945 +                                        // constants.rst for example registers a data item for "quit" which is really a function
 157.946 +
 157.947 +                                        String signature = m.group(2);
 157.948 +                                        indexRstFunction(signature, lines, lineno, document);
 157.949 +
 157.950 +                                        // See if we have any additional lines with signatures
 157.951 +                                        for (int lookahead = lineno + 1; lookahead < maxLines; lookahead++) {
 157.952 +                                            String l = lines[lookahead];
 157.953 +                                            String trimmed = l.trim();
 157.954 +                                            if (trimmed.length() == 0 || trimmed.startsWith(":")) { // NOI18N
 157.955 +                                                break;
 157.956 +                                            }
 157.957 +                                            lineno++;
 157.958 +
 157.959 +                                            indexRstFunction(trimmed, lines, lookahead, document);
 157.960 +                                        }
 157.961 +
 157.962 +                                    } else if (key.equals("data")) { // NOI18N
 157.963 +                                        String data = m.group(2);
 157.964 +
 157.965 +                                        StringBuilder sig = new StringBuilder();
 157.966 +                                        sig.append(data);
 157.967 +                                        int symFlags = 0;
 157.968 +                                        if (NameStyle.isPrivateName(data)) {
 157.969 +                                            symFlags |= ScopeConstants.PRIVATE;
 157.970 +                                        }
 157.971 +                                        // TODO - look up deprecated etc.
 157.972 +                                        SymInfo fakeSym = new SymInfo(symFlags);
 157.973 +
 157.974 +                                        int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
 157.975 +                                        if (isDeprecated(lines, lineno)) {
 157.976 +                                            flags |= IndexedElement.DEPRECATED;
 157.977 +                                        }
 157.978 +
 157.979 +                                        appendFlags(sig, 'D', fakeSym, flags);
 157.980 +
 157.981 +                                        document.addPair(FIELD_ITEM, sig.toString(), true);
 157.982 +                                    } else {
 157.983 +                                        // TODO Handle deprecated attribute!
 157.984 +
 157.985 +                                        //    currentmodule::
 157.986 +                                        //    deprecated::
 157.987 +                                        //    doctest::
 157.988 +                                        //    envvar::
 157.989 +                                        //    epigraph::
 157.990 +                                        //    highlight::
 157.991 +                                        //    highlightlang::
 157.992 +                                        //    index::
 157.993 +                                        //    literalinclude::
 157.994 +                                        //    moduleauthor::
 157.995 +                                        //    note::
 157.996 +                                        //    opcode::
 157.997 +                                        //    productionlist::
 157.998 +                                        //    rubric::
 157.999 +                                        //    sectionauthor::
157.1000 +                                        //    seealso::
157.1001 +                                        //    testcode::
157.1002 +                                        //    testsetup::
157.1003 +                                        //    toctree::
157.1004 +                                        //    versionadded::
157.1005 +                                        //    versionchanged::
157.1006 +                                        //    warning::
157.1007 +                                    }
157.1008 +                                }
157.1009 +                            }
157.1010 +                        } else if (line.startsWith(".. _bltin-file-objects:") || line.startsWith(".. _string-methods:")) { // NOI18N
157.1011 +                            if (currentClass != null) {
157.1012 +                                currentClass = null;
157.1013 +                            }
157.1014 +                        }
157.1015 +                    }
157.1016 +
157.1017 +                    for (String clz : classDocs.keySet()) {
157.1018 +                        StringBuilder sig = new StringBuilder();
157.1019 +                        sig.append(clz);
157.1020 +                        int symFlags = 0;
157.1021 +                        if (NameStyle.isPrivateName(clz)) {
157.1022 +                            symFlags |= ScopeConstants.PRIVATE;
157.1023 +                        }
157.1024 +                        // TODO - look up deprecated etc.
157.1025 +                        SymInfo fakeSym = new SymInfo(symFlags);
157.1026 +                        appendFlags(sig, 'C', fakeSym, IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY);
157.1027 +
157.1028 +                        document.addPair(FIELD_ITEM, sig.toString(), true);
157.1029 +                    }
157.1030 +
157.1031 +                } catch (BadLocationException ex) {
157.1032 +                    Exceptions.printStackTrace(ex);
157.1033 +                }
157.1034 +
157.1035 +                // Post processing: Add missing attributes not found in the .rst files
157.1036 +                // but introspected using dir() in a python console
157.1037 +                if (document != null) {
157.1038 +                    if ("operator".equals(module)) { // Fill in missing operators!
157.1039 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.1040 +                                new String[] { "__abs__", "__add__", "__and__", "__div__", "__floordiv__", "__index__", "__invert__", "__lshift__", "__mod__", "__mul__", "__neg__", "__or__", "__pos__", "__pow__", "__rshift__", "__sub__", "__truediv__", "__xor__" },
157.1041 +                                document, classDocs, "int", documents, module, false, true);
157.1042 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.1043 +                                new String[] { "__abs__", "__add__", "__and__", "__div__", "__floordiv__", "__index__", "__invert__", "__lshift__", "__mod__", "__mul__", "__neg__", "__or__", "__pos__", "__pow__", "__rshift__", "__sub__", "__truediv__", "__xor__" },
157.1044 +                                document, classDocs, "long", documents, module, false, true);
157.1045 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.1046 +                                new String[] { "__abs__", "__add__", "__div__", "__eq__", "__floordiv__", "__ge__", "__gt__", "__le__", "__lt__", "__mod__", "__mul__", "__ne__", "__neg__", "__pos__", "__pow__", "__sub__", "__truediv__" },
157.1047 +                                document, classDocs, "float", documents, module, false, true);
157.1048 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.1049 +                                new String[] { "__abs__", "__add__", "__div__", "__eq__", "__floordiv__", "__ge__", "__gt__", "__le__", "__lt__", "__mod__", "__mul__", "__ne__", "__neg__", "__pos__", "__pow__", "__sub__", "__truediv__" },
157.1050 +                                document, classDocs, "complex", documents, module, false, true);
157.1051 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.1052 +                                new String[] { "__abs__", "__add__", "__and__", "__div__", "__floordiv__", "__index__", "__invert__", "__lshift__", "__mod__", "__mul__", "__neg__", "__or__", "__pos__", "__pow__", "__rshift__", "__sub__", "__truediv__", "__xor__" },
157.1053 +                                document, classDocs, "bool", documents, module, false, true);
157.1054 +
157.1055 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.1056 +                                new String[] { "__add__", "__contains__", "__eq__", "__ge__", "__getitem__", "__getslice__", "__gt__", "__le__", "__lt__", "__mod__", "__mul__", "__ne__", "index" },
157.1057 +                                document, classDocs, "str", documents, module, false, true);
157.1058 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.1059 +                                new String[] { "__add__", "__contains__", "__delitem__", "__delslice__", "__eq__", "__ge__", "__getitem__", "__getslice__", "__gt__", "__iadd__", "__imul__", "__le__", "__lt__", "__mul__", "__ne__", "__setitem__", "__setslice__", "index" },
157.1060 +                                document, classDocs, "list", documents, module, false, true);
157.1061 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.1062 +                                new String[] { "__contains__", "__delitem__", "__eq__", "__ge__", "__getitem__", "__gt__", "__le__", "__lt__", "__ne__", "__setitem__" },
157.1063 +                                document, classDocs, "dict", documents, module, false, true);
157.1064 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.1065 +                                new String[] { "__add__", "__contains__", "__eq__", "__ge__", "__getitem__", "__getslice__", "__gt__", "__le__", "__lt__", "__mul__", "__ne__", "index" },
157.1066 +                                document, classDocs, "tuple", documents, module, false, true);
157.1067 +                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.1068 +                                new String[] { "__add__", "__contains__", "__eq__", "__ge__", "__getitem__", "__getslice__", "__gt__", "__le__", "__lt__", "__mod__", "__mul__", "__ne__", "index" },
157.1069 +                                document, classDocs, "unicode", documents, module, false, true);
157.1070 +//                    } else if ("stdtypes".equals(module)) {
157.1071 +//                        // Found no definitions for these puppies
157.1072 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.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" },
157.1074 +//                                document, classDocs, "int", documents, module, true, false);
157.1075 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.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" },
157.1077 +//                                document, classDocs, "long", documents, module, true, false);
157.1078 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.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" },
157.1080 +//                                document, classDocs, "float", documents, module, true, false);
157.1081 +//
157.1082 +//
157.1083 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.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" },
157.1085 +//                                document, classDocs, "complex", documents, module, true, false);
157.1086 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.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" },
157.1088 +//                                document, classDocs, "bool", documents, module, true, false);
157.1089 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.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" },
157.1091 +//                                document, classDocs, "str", documents, module, true, false);
157.1092 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.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" },
157.1094 +//                                document, classDocs, "list", documents, module, true, false);
157.1095 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.1096 +//                              new String[] { "__class__", "__cmp__", "__delattr__", "__doc__", "__format__", "__getattribute__", "__hash__", "__iter__", "__len__", "__new__", "__repr__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__" },
157.1097 +//                                document, classDocs, "dict", documents, module, true, false);
157.1098 +//
157.1099 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.1100 +//                              new String[] { "__class__", "__delattr__", "__doc__", "__format__", "__getattribute__", "__getnewargs__", "__hash__", "__init__", "__iter__", "__len__", "__new__", "__reduce__", "__reduce_ex__", "__repr__", "__rmul__", "__setattr__", "__sizeof__", "__str__", "__subclasshook__", "count" },
157.1101 +//                                document, classDocs, "tuple", documents, module, true, false);
157.1102 +//                        addMissing(PythonIndexer.FIELD_ITEM, PythonIndexer.FIELD_MEMBER,
157.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" },
157.1104 +//                                document, classDocs, "unicode", documents, module, true, false);
157.1105 +//
157.1106 +                    }
157.1107 +                }
157.1108 +
157.1109 +                // And convert to a proper GSF search document. I didn't do this directly
157.1110 +                // because I want to modify the documents after adding documents and pairs.
157.1111 +                for (CachedIndexDocument cid : documents) {
157.1112 +                    List<CachedIndexDocumentEntry> entries = cid.entries;
157.1113 +                    IndexDocument indexedDoc = support.createDocument(indexable);
157.1114 +//                    IndexDocument indexedDoc = support.createDocument(entries.size(), overrideUrl);
157.1115 +                    docs.add(indexedDoc);
157.1116 +                    for (CachedIndexDocumentEntry entry : entries) {
157.1117 +                        indexedDoc.addPair(entry.key, entry.value, true, true); // XXX indexable and stored ???
157.1118 +                    }
157.1119 +                }
157.1120 +            }
157.1121 +        }
157.1122 +
157.1123 +        return docs;
157.1124 +    }
157.1125 +
157.1126 +    /** Add the given list of names, found in the given document with a given key, and add it
157.1127 +     * to the specified class (possibly found in the classDocs list - if not, add one to the
157.1128 +     * documents list)
157.1129 +     */
157.1130 +    private void addMissing(String key, String newKey, String[] names, CachedIndexDocument doc,
157.1131 +            Map<String, CachedIndexDocument> classDocs, String clz, List<CachedIndexDocument> documents, String module,
157.1132 +            boolean addUnknown, boolean search) {
157.1133 +
157.1134 +        CachedIndexDocument classDocument = classDocs.get(clz);
157.1135 +        if (classDocument == null) {
157.1136 +            // New class without class:: declaration first.
157.1137 +            classDocument = new CachedIndexDocument();
157.1138 +            documents.add(classDocument);
157.1139 +            classDocs.put(clz, classDocument);
157.1140 +            classDocument.addPair(FIELD_IN, module, true);
157.1141 +
157.1142 +            classDocument.addPair(FIELD_CLASS_NAME, clz, true);
157.1143 +            classDocument.addPair(FIELD_CASE_INSENSITIVE_CLASS_NAME, clz.toLowerCase(), true);
157.1144 +        }
157.1145 +
157.1146 +        assert classDocument != doc;
157.1147 +
157.1148 +        List<String> namesFound = new ArrayList<>();
157.1149 +        List<String> namesMissing = new ArrayList<>();
157.1150 +        boolean noneFound = true;
157.1151 +
157.1152 +        // Look for each of the given functions
157.1153 +        Search:
157.1154 +        for (String name : names) {
157.1155 +            boolean found = false;
157.1156 +            if (search) {
157.1157 +                int nameLength = name.length();
157.1158 +
157.1159 +                // DEBUGGING: Look to make sure I don't already have it in the class doc!
157.1160 +                for (CachedIndexDocumentEntry entry : classDocument.entries) {
157.1161 +                    if (newKey.equals(entry.key)) {
157.1162 +                        if (entry.value.startsWith(name) &&
157.1163 +                                (entry.value.length() <= nameLength || entry.value.charAt(nameLength) == ';')) {
157.1164 +                             // Uh oh - what do I do here?
157.1165 +                            System.err.println("WARNING: I already have a definition for name " + name + " in class " + clz);
157.1166 +                            continue Search;
157.1167 +                        }
157.1168 +                    }
157.1169 +                }
157.1170 +
157.1171 +                for (CachedIndexDocumentEntry entry : doc.entries) {
157.1172 +                    if (key.equals(entry.key)) {
157.1173 +                        if (entry.value.startsWith(name) &&
157.1174 +                                (entry.value.length() <= nameLength || entry.value.charAt(nameLength) == ';')) {
157.1175 +                            // Found it!
157.1176 +                            classDocument.addPair(newKey, entry.value, entry.index);
157.1177 +                            found = true;
157.1178 +                            namesFound.add(name);
157.1179 +                            break;
157.1180 +                        }
157.1181 +                    }
157.1182 +                }
157.1183 +            }
157.1184 +
157.1185 +            if (!found) {
157.1186 +                if (addUnknown) {
157.1187 +                    // TODO - see if I can find a way to extract the signature too!
157.1188 +                    String args = "";
157.1189 +                    String signature = name + "()"; //
157.1190 +
157.1191 +                    assert signature.indexOf('(') != -1 && signature.indexOf(')') != -1 &&
157.1192 +                            signature.indexOf(')') > signature.indexOf('(') : signature;
157.1193 +                    char type;
157.1194 +                    if (name.equals("__init__")) { // NOI18N
157.1195 +                        type = 'c';
157.1196 +                    } else {
157.1197 +                        type = 'F';
157.1198 +                    }
157.1199 +                    StringBuilder sig = new StringBuilder();
157.1200 +                    sig.append(name);
157.1201 +
157.1202 +                    int symFlags = 0;
157.1203 +                    if (NameStyle.isPrivateName(name)) {
157.1204 +                        symFlags |= ScopeConstants.PRIVATE;
157.1205 +                    }
157.1206 +                    // TODO - look up deprecated etc.
157.1207 +                    SymInfo fakeSym = new SymInfo(symFlags);
157.1208 +
157.1209 +                    int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
157.1210 +                    appendFlags(sig, type, fakeSym, flags);
157.1211 +                    sig.append(args);
157.1212 +                    sig.append(';');
157.1213 +
157.1214 +                    classDocument.addPair(newKey, sig.toString(), true);
157.1215 +                } else {
157.1216 +                    namesMissing.add(name);
157.1217 +                }
157.1218 +            } else {
157.1219 +                noneFound = false;
157.1220 +            }
157.1221 +        }
157.1222 +
157.1223 +        if (PREINDEXING) {
157.1224 +            if (namesFound.size() > 0) {
157.1225 +                StringBuilder sb = new StringBuilder();
157.1226 +                sb.append("FOUND for ");
157.1227 +                sb.append(clz);
157.1228 +                sb.append(" in ");
157.1229 +                sb.append(module);
157.1230 +                sb.append(": ");
157.1231 +                appendList(sb, namesFound);
157.1232 +                System.err.println(sb.toString());
157.1233 +            }
157.1234 +
157.1235 +            if (noneFound && search) {
157.1236 +                System.err.println("ERROR: NONE of the passed in names for " + clz + " were found!");
157.1237 +            }
157.1238 +
157.1239 +            if (namesMissing.size() > 0) {
157.1240 +                StringBuilder sb = new StringBuilder();
157.1241 +                sb.append("WARNING: Missing these names from ");
157.1242 +                sb.append(module);
157.1243 +                sb.append(" for use by class ");
157.1244 +                sb.append(clz);
157.1245 +                sb.append(" : ");
157.1246 +                appendList(sb, namesMissing);
157.1247 +                System.err.println(sb.toString());
157.1248 +            }
157.1249 +        }
157.1250 +    }
157.1251 +
157.1252 +    private static void appendList(StringBuilder sb, List<String> list) {
157.1253 +        sb.append("{ ");
157.1254 +        boolean first = true;
157.1255 +        for (String m : list) {
157.1256 +            if (first) {
157.1257 +                first = false;
157.1258 +            } else {
157.1259 +                sb.append(", ");
157.1260 +            }
157.1261 +            sb.append('"');
157.1262 +            sb.append(m);
157.1263 +            sb.append('"');
157.1264 +        }
157.1265 +        sb.append(" }");
157.1266 +    }
157.1267 +
157.1268 +    private void indexRstFunction(String signature, String[] lines, int lineno, CachedIndexDocument document) {
157.1269 +        int dot = signature.indexOf('.');
157.1270 +        if (dot != -1) {
157.1271 +            int paren = signature.indexOf('(');
157.1272 +            if (paren == -1 || paren > dot) {
157.1273 +                assert signature.matches("\\w+\\.\\w+.*") : signature; // NOI18N
157.1274 +                signature = signature.substring(dot + 1);
157.1275 +            }
157.1276 +        }
157.1277 +        signature = cleanupSignature(signature);
157.1278 +        if (signature.indexOf('(') == -1) {
157.1279 +            signature = signature + "()"; // NOI18N
157.1280 +        } else if (signature.indexOf(')') == -1) {
157.1281 +            //signature = signature + ")";
157.1282 +            assert signature.indexOf(')') != -1;
157.1283 +        }
157.1284 +        int lparen = signature.indexOf('(');
157.1285 +        int rparen = signature.indexOf(')', lparen + 1);
157.1286 +        if (lparen != -1 && rparen != -1) {
157.1287 +            String methodName = signature.substring(0, lparen);
157.1288 +            String args = signature.substring(lparen + 1, rparen);
157.1289 +            StringBuilder sig = new StringBuilder();
157.1290 +            sig.append(methodName);
157.1291 +            int symFlags = 0;
157.1292 +            if (NameStyle.isPrivateName(methodName)) {
157.1293 +                symFlags |= ScopeConstants.PRIVATE;
157.1294 +            }
157.1295 +            // TODO - look up deprecated etc.
157.1296 +            SymInfo fakeSym = new SymInfo(symFlags);
157.1297 +            int flags = IndexedElement.DOCUMENTED | IndexedElement.DOC_ONLY;
157.1298 +            if (isDeprecated(lines, lineno)) {
157.1299 +                flags |= IndexedElement.DEPRECATED;
157.1300 +            }
157.1301 +            appendFlags(sig, 'F', fakeSym, flags);
157.1302 +            sig.append(args);
157.1303 +            sig.append(';');
157.1304 +
157.1305 +            document.addPair(FIELD_ITEM, sig.toString(), true);
157.1306 +        }
157.1307 +    }
157.1308 +
157.1309 +    private List<IndexDocument> scanEgg(FileObject fo, Indexable indexable, ParserResult result, IndexingSupport support) {
157.1310 +        List<IndexDocument> documents = new ArrayList<>();
157.1311 +
157.1312 +        if (fo == null) {
157.1313 +            return documents;
157.1314 +        }
157.1315 +
157.1316 +        try {
157.1317 +            String s = fo.toURL().toExternalForm() + "!"; // NOI18N
157.1318 +            URL u = new URL("jar:" + s); // NOI18N
157.1319 +            FileObject root = URLMapper.findFileObject(u);
157.1320 +            String rootUrl = PythonIndex.getPreindexUrl(u.toExternalForm());
157.1321 +            indexScriptDocRecursively(support, documents, root, rootUrl);
157.1322 +        } catch (MalformedURLException ex) {
157.1323 +            Exceptions.printStackTrace(ex);
157.1324 +        }
157.1325 +
157.1326 +        return documents;
157.1327 +    }
157.1328 +
157.1329 +    /**
157.1330 +     * Method which recursively indexes directory trees, such as the yui/ folder
157.1331 +     * for example
157.1332 +     */
157.1333 +    private void indexScriptDocRecursively(IndexingSupport support, List<IndexDocument> documents, final FileObject fo, String url) {
157.1334 +        if (fo.isFolder()) {
157.1335 +            for (FileObject c : fo.getChildren()) {
157.1336 +                indexScriptDocRecursively(support, documents, c, url + "/" + c.getNameExt()); // NOI18N
157.1337 +            }
157.1338 +            return;
157.1339 +        }
157.1340 +
157.1341 +        String ext = fo.getExt();
157.1342 +
157.1343 +//        if ("py".equals(ext)) { // NOI18N
157.1344 +//            DefaultParseListener listener = new DefaultParseListener();
157.1345 +//            List<ParserFile> files = Collections.<ParserFile>singletonList(new DefaultParserFile(fo, null, false));
157.1346 +//            SourceFileReader reader = new SourceFileReader() {
157.1347 +//                public CharSequence read(ParserFile file) throws IOException {
157.1348 +//                    BaseDocument doc = GsfUtilities.getDocument(fo, true);
157.1349 +//                    if (doc != null) {
157.1350 +//                        try {
157.1351 +//                            return doc.getText(0, doc.getLength());
157.1352 +//                        } catch (BadLocationException ex) {
157.1353 +//                            Exceptions.printStackTrace(ex);
157.1354 +//                        }
157.1355 +//                    }
157.1356 +//
157.1357 +//                    return "";
157.1358 +//                }
157.1359 +//
157.1360 +//                public int getCaretOffset(ParserFile file) {
157.1361 +//                    return -1;
157.1362 +//                }
157.1363 +//            };
157.1364 +//            Job job = new Job(files, listener, reader, null);
157.1365 +//            new PythonParser().parseFiles(job);
157.1366 +//            ParserResult parserResult = listener.getParserResult();
157.1367 +//            if (parserResult != null && parserResult.isValid()) {
157.1368 +//                documents.addAll(new IndexTask((PythonParserResult)parserResult, support, url).scan());
157.1369 +//            }
157.1370 +//        } else if ("rst".equals(ext)) { // NOI18N
157.1371 +//            documents.addAll(scanRst(fo, support, url));
157.1372 +//        }
157.1373 +    }
157.1374 +
157.1375 +    private FileObject getLibDir() {
157.1376 +        // TODO - fetch from projects!!!!
157.1377 +        PythonPlatformManager manager = PythonPlatformManager.getInstance();
157.1378 +        PythonPlatform platform = manager.getPlatform(manager.getDefaultPlatform());
157.1379 +        if (platform != null) {
157.1380 +            String cmd = platform.getInterpreterCommand();
157.1381 +            File file = new File(cmd);
157.1382 +            if (file.exists()) {
157.1383 +                file = file.getAbsoluteFile();
157.1384 +                File home = file.getParentFile().getParentFile();
157.1385 +                if (home != null) {
157.1386 +                    // Look for Lib - Jython style
157.1387 +                    File lib = new File(home, "Lib"); // NOI18N
157.1388 +                    boolean exists = lib.exists();
157.1389 +                    if (!exists) { // Unix style
157.1390 +                        lib = new File(home, "lib" + File.separator + "python"); // NOI18N
157.1391 +                        exists = lib.exists();
157.1392 +                    }
157.1393 +                    if (exists) {
157.1394 +                        return FileUtil.toFileObject(lib);
157.1395 +                    }
157.1396 +                }
157.1397 +            }
157.1398 +        }
157.1399 +
157.1400 +        return null;
157.1401 +    }
157.1402 +}
   158.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   158.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonIndexerFactory.java	Mon Sep 21 13:01:16 2015 +0200
   158.3 @@ -0,0 +1,47 @@
   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.parsing.api.Snapshot;
  158.12 +import org.netbeans.modules.parsing.spi.indexing.Context;
  158.13 +import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexer;
  158.14 +import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory;
  158.15 +import org.netbeans.modules.parsing.spi.indexing.Indexable;
  158.16 +
  158.17 +/**
  158.18 + *
  158.19 + * @author Ralph Benjamin Ruijs
  158.20 + */
  158.21 +public class PythonIndexerFactory extends EmbeddingIndexerFactory {    
  158.22 +
  158.23 +    @Override
  158.24 +    public EmbeddingIndexer createIndexer(Indexable indexable, Snapshot snapshot) {
  158.25 +        if(PythonIndexer.isIndexable(indexable, snapshot)) {
  158.26 +            return new PythonIndexer();
  158.27 +        }
  158.28 +        return null;
  158.29 +    }
  158.30 +
  158.31 +    @Override
  158.32 +    public void filesDeleted(Iterable<? extends Indexable> indexables, Context context) {
  158.33 +//        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
  158.34 +    }
  158.35 +
  158.36 +    @Override
  158.37 +    public void filesDirty(Iterable<? extends Indexable> arg0, Context arg1) {
  158.38 +//        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
  158.39 +    }
  158.40 +
  158.41 +    @Override
  158.42 +    public String getIndexerName() {
  158.43 +        return PythonIndexer.NAME;
  158.44 +    }
  158.45 +
  158.46 +    @Override
  158.47 +    public int getIndexVersion() {
  158.48 +        return PythonIndexer.VERSION;
  158.49 +    }
  158.50 +}
   159.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   159.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonParser.java	Mon Sep 21 13:01:16 2015 +0200
   159.3 @@ -0,0 +1,760 @@
   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.io.InputStream;
  159.37 +import java.io.InputStreamReader;
  159.38 +import java.util.ArrayList;
  159.39 +import java.util.List;
  159.40 +import java.util.logging.Level;
  159.41 +import java.util.logging.Logger;
  159.42 +import javax.swing.event.ChangeListener;
  159.43 +import javax.swing.text.BadLocationException;
  159.44 +import org.netbeans.modules.csl.api.Severity;
  159.45 +import org.netbeans.modules.csl.spi.DefaultError;
  159.46 +import org.netbeans.modules.csl.api.Error;
  159.47 +import org.netbeans.modules.csl.api.OffsetRange;
  159.48 +import org.netbeans.modules.csl.spi.GsfUtilities;
  159.49 +import org.netbeans.modules.parsing.api.Snapshot;
  159.50 +import org.netbeans.modules.parsing.api.Task;
  159.51 +import org.netbeans.modules.parsing.spi.Parser;
  159.52 +import org.netbeans.modules.parsing.spi.SourceModificationEvent;
  159.53 +import org.netbeans.modules.python.api.PythonFileEncodingQuery;
  159.54 +import org.openide.filesystems.FileObject;
  159.55 +import org.python.antlr.runtime.ANTLRStringStream;
  159.56 +import org.python.antlr.runtime.BaseRecognizer;
  159.57 +import org.python.antlr.runtime.BitSet;
  159.58 +import org.python.antlr.runtime.CommonToken;
  159.59 +import org.python.antlr.runtime.CommonTokenStream;
  159.60 +import org.python.antlr.runtime.IntStream;
  159.61 +import org.python.antlr.runtime.Lexer;
  159.62 +import org.python.antlr.runtime.MismatchedTokenException;
  159.63 +import org.python.antlr.runtime.RecognitionException;
  159.64 +
  159.65 +import org.openide.filesystems.FileUtil;
  159.66 +import org.openide.util.Exceptions;
  159.67 +import org.python.antlr.ListErrorHandler;
  159.68 +import org.python.antlr.ParseException;
  159.69 +import org.python.antlr.PythonLexer;
  159.70 +import org.python.antlr.PythonTokenSource;
  159.71 +import org.python.antlr.PythonTree;
  159.72 +import org.python.antlr.PythonTreeAdaptor;
  159.73 +import org.python.antlr.base.expr;
  159.74 +import org.python.antlr.base.mod;
  159.75 +import org.python.antlr.base.slice;
  159.76 +import org.python.antlr.base.stmt;
  159.77 +import org.python.antlr.runtime.ANTLRReaderStream;
  159.78 +import org.python.antlr.runtime.CharStream;
  159.79 +
  159.80 +/**
  159.81 + * Parser for Python. Wraps Jython.
  159.82 + * 
  159.83 + * @author Frank Wierzbicki
  159.84 + * @author Tor Norbye
  159.85 + */
  159.86 +public class PythonParser extends Parser {
  159.87 +    /** For unit tests such that they can make sure we didn't have a parser abort */
  159.88 +    static Throwable runtimeException;
  159.89 +
  159.90 +    static {
  159.91 +        org.python.core.PySystemState.initialize();
  159.92 +    }
  159.93 +    
  159.94 +    private Result lastResult;
  159.95 +    private final PythonFileEncodingQuery fileEncodingQuery = new PythonFileEncodingQuery();
  159.96 +    private String headerCached = null;
  159.97 +    private String encodingCache = null;
  159.98 +
  159.99 +    public mod file_input(CharStream charStream, String fileName) throws RecognitionException {
 159.100 +        ListErrorHandler eh = new ListErrorHandler();
 159.101 +        mod tree = null;
 159.102 +        PythonLexer lexer = new PythonLexer(charStream);
 159.103 +        lexer.setErrorHandler(eh);
 159.104 +        CommonTokenStream tokens = new CommonTokenStream(lexer);
 159.105 +        tokens.discardOffChannelTokens(true);
 159.106 +        PythonTokenSource indentedSource = new PythonTokenSource(tokens, fileName);
 159.107 +        tokens = new CommonTokenStream(indentedSource);
 159.108 +        org.python.antlr.PythonParser parser = new org.python.antlr.PythonParser(tokens);
 159.109 +        parser.setTreeAdaptor(new PythonTreeAdaptor());
 159.110 +        parser.setErrorHandler(eh);
 159.111 +        org.python.antlr.PythonParser.file_input_return r = parser.file_input();
 159.112 +        tree = (mod)r.getTree();
 159.113 +        return tree;
 159.114 +    }
 159.115 +
 159.116 +    @Override
 159.117 +    public void addChangeListener(ChangeListener changeListener) {}
 159.118 +
 159.119 +    @Override
 159.120 +    public void removeChangeListener(ChangeListener changeListener) {}
 159.121 +    
 159.122 +    public PythonTree parse(InputStream istream, String fileName) throws Exception {
 159.123 +        InputStreamReader reader = new InputStreamReader(istream, "ISO-8859-1");
 159.124 +        return file_input(new ANTLRReaderStream(reader), fileName);
 159.125 +    }
 159.126 +    
 159.127 +    @Override
 159.128 +    public final Result getResult(Task task) throws org.netbeans.modules.parsing.spi.ParseException {
 159.129 +        return lastResult;
 159.130 +    }
 159.131 +    
 159.132 +    private static final Logger LOG = Logger.getLogger(PythonParser.class.getName());
 159.133 +
 159.134 +    @Override
 159.135 +    public void parse(Snapshot snapshot, Task task, SourceModificationEvent event) throws org.netbeans.modules.parsing.spi.ParseException {
 159.136 +        Context context = new Context();
 159.137 +        context.snapshot = snapshot;
 159.138 +        context.event = event;
 159.139 +        context.task = task;
 159.140 +        context.caretOffset = GsfUtilities.getLastKnownCaretOffset(snapshot, event);
 159.141 +        context.source = snapshot.getText().toString();
 159.142 +        context.file = snapshot.getSource().getFileObject();
 159.143 +        if(context.file == null) {
 159.144 +            return; // TODO: parse the source, not the file
 159.145 +        }
 159.146 +        /* Let's not sanitize ;-) Would be great if we could have a more robust parser
 159.147 +        if (context.caretOffset != -1) {
 159.148 +            context.sanitized = Sanitize.EDITED_DOT;
 159.149 +        }
 159.150 +        */
 159.151 +        lastResult = parse(context, context.sanitized);
 159.152 +    }
 159.153 +    public PythonParserResult parse(final Context context, Sanitize sanitizing) {
 159.154 +        boolean sanitizedSource = false;
 159.155 +        String sourceCode = context.source;
 159.156 +        if (!((sanitizing == Sanitize.NONE) || (sanitizing == Sanitize.NEVER))) {
 159.157 +            boolean ok = sanitizeSource(context, sanitizing);
 159.158 +
 159.159 +            if (ok) {
 159.160 +                assert context.sanitizedSource != null;
 159.161 +                sanitizedSource = true;
 159.162 +                sourceCode = context.sanitizedSource;
 159.163 +            } else {
 159.164 +                // Try next trick
 159.165 +                return sanitize(context, sanitizing);
 159.166 +            }
 159.167 +        }
 159.168 +        final String source = sourceCode;
 159.169 +
 159.170 +        if (sanitizing == Sanitize.NONE) {
 159.171 +            context.errorOffset = -1;
 159.172 +        }
 159.173 +
 159.174 +        final List<Error> errors = new ArrayList<>();
 159.175 +        final FileObject file = context.file;
 159.176 +        try {
 159.177 +            String fileName = file.getNameExt();
 159.178 +            // TODO - sniff file headers etc. Frank's comment:
 159.179 +            // Longer term for Python compatibility, having NetBeans sniff the top two lines
 159.180 +            // for an encoding would be the right thing to do from a pure Python
 159.181 +            // compatibility standard (see http://www.python.org/dev/peps/pep-0263/) I
 159.182 +            // have pep-0263 code in Jython that I could probably extract for this
 159.183 +            // purpose down the road.
 159.184 +            //String charset = "ISO8859_1"; // NOI18N
 159.185 +            //String charset = "UTF-8"; // NOI18N
 159.186 +            //String charset = "iso8859_1"; // NOI18N
 159.187 +            // TODO: improve this check.
 159.188 +            int cache_len = sourceCode.length() >= 64 ? 64 : sourceCode.length();
 159.189 +            if (headerCached == null || cache_len != headerCached.length() || !headerCached.equals(sourceCode.substring(0, cache_len))) {
 159.190 +                headerCached = sourceCode.substring(0, cache_len);
 159.191 +                encodingCache = fileEncodingQuery.getPythonFileEncoding(sourceCode.split("\n", 2));                
 159.192 +            }
 159.193 +            String charset = encodingCache;            
 159.194 +                
 159.195 +            final boolean ignoreErrors = sanitizedSource;
 159.196 +            ListErrorHandler errorHandler = new ListErrorHandler() {
 159.197 +                @Override
 159.198 +                public void error(String message, PythonTree t) {
 159.199 +                    errors.add(new DefaultError(null, message, null, file, t.getCharStartIndex(), t.getCharStopIndex(), Severity.ERROR));
 159.200 +                    super.error(message, t);
 159.201 +                }
 159.202 +
 159.203 +                @Override
 159.204 +                public expr errorExpr(PythonTree t) {
 159.205 +                    return super.errorExpr(t);
 159.206 +                }
 159.207 +
 159.208 +                @Override
 159.209 +                public mod errorMod(PythonTree t) {
 159.210 +                    return super.errorMod(t);
 159.211 +                }
 159.212 +
 159.213 +                @Override
 159.214 +                public slice errorSlice(PythonTree t) {
 159.215 +                    return super.errorSlice(t);
 159.216 +                }
 159.217 +
 159.218 +                @Override
 159.219 +                public stmt errorStmt(PythonTree t) {
 159.220 +                    return super.errorStmt(t);
 159.221 +                }
 159.222 +
 159.223 +                @Override
 159.224 +                public boolean mismatch(BaseRecognizer br, IntStream input, int ttype, BitSet follow) {
 159.225 +                    return super.mismatch(br, input, ttype, follow);
 159.226 +                }
 159.227 +
 159.228 +                @Override
 159.229 +                public Object recoverFromMismatchedToken(BaseRecognizer br, IntStream input, int ttype, BitSet follow) {
 159.230 +                    MismatchedTokenException mt = new MismatchedTokenException(ttype, input);
 159.231 +                    String message = br.getErrorMessage(mt, br.getTokenNames());
 159.232 +                    if (mt.line >= 1) {
 159.233 +                        int lineOffset = findLineOffset(context.source, mt.line-1);
 159.234 +                        if (mt.charPositionInLine > 0) {
 159.235 +                            lineOffset += mt.charPositionInLine;
 159.236 +                        }
 159.237 +                        int start = lineOffset;//t.getCharStartIndex();
 159.238 +                        int stop = lineOffset;//t.getCharStopIndex();
 159.239 +                        errors.add(new DefaultError(null, message, null, file, start, stop, Severity.ERROR));
 159.240 +                    }
 159.241 +                    return super.recoverFromMismatchedToken(br, input, ttype, follow);
 159.242 +                }
 159.243 +
 159.244 +                @Override
 159.245 +                public void recover(Lexer lex, RecognitionException re) {
 159.246 +                    super.recover(lex, re);
 159.247 +                }
 159.248 +
 159.249 +                @Override
 159.250 +                public void recover(BaseRecognizer br, IntStream input, RecognitionException re) {
 159.251 +                    super.recover(br, input, re);
 159.252 +                }
 159.253 +
 159.254 +                @Override
 159.255 +                public void reportError(BaseRecognizer br, RecognitionException re) {
 159.256 +                    if (!ignoreErrors) {
 159.257 +                        String message = br.getErrorMessage(re, br.getTokenNames());
 159.258 +                        if (message == null || message.length() == 0) {
 159.259 +                            message = re.getMessage();
 159.260 +                        }
 159.261 +                        if (message == null) {
 159.262 +                            //message = re.getUnexpectedType();
 159.263 +                            message = re.toString();
 159.264 +                        }
 159.265 +                        int start = re.index;
 159.266 +
 159.267 +                        // Try to find the line offset. re.index doesn't do the trick.
 159.268 +                        start = PythonUtils.getOffsetByLineCol(source, re.line - 1, 0); // -1: 0-based
 159.269 +                        int end = start;
 159.270 +                        if (re.charPositionInLine > 0) {
 159.271 +                            try {
 159.272 +                                end = GsfUtilities.getRowLastNonWhite(source, start) + 1;
 159.273 +                                start += re.charPositionInLine;
 159.274 +                                if (end < start) {
 159.275 +                                    end = start;
 159.276 +                                }
 159.277 +                            } catch (BadLocationException ex) {
 159.278 +                                Exceptions.printStackTrace(ex);
 159.279 +                                end = start;
 159.280 +                            }
 159.281 +                            if (end == 0) {
 159.282 +                                end = start;
 159.283 +                            }
 159.284 +                        }
 159.285 +
 159.286 +                        // Some errors have better offsets if we look at the token stream
 159.287 +                        if (re instanceof MismatchedTokenException) {
 159.288 +                            MismatchedTokenException m = (MismatchedTokenException)re;
 159.289 +                            if (m.token != null) {
 159.290 +                                if (m.token instanceof org.python.antlr.runtime.CommonToken) {
 159.291 +                                    CommonToken token = (org.python.antlr.runtime.CommonToken)m.token;
 159.292 +                                    start = token.getStartIndex();
 159.293 +                                    end = token.getStopIndex();
 159.294 +                                }
 159.295 +                            }
 159.296 +                        }
 159.297 +
 159.298 +                        if (start > source.length()) {
 159.299 +                            start = source.length();
 159.300 +                            end = start;
 159.301 +                        }
 159.302 +
 159.303 +                        errors.add(new DefaultError(null, message, null, file, start, end, Severity.ERROR));
 159.304 +
 159.305 +                        // In order to avoid a StackOverflowError, the BaseRecognizer must be recreated.
 159.306 +                        // We must keep the names of the tokens to avoid a NullPointerException.
 159.307 +                        // See bz252630
 159.308 +                        final String[] tokenNames = br.getTokenNames();
 159.309 +                        br = new BaseRecognizer() {
 159.310 +
 159.311 +                            @Override
 159.312 +                            public String getSourceName() {
 159.313 +                                return file.getName();
 159.314 +                            }
 159.315 +
 159.316 +                            @Override
 159.317 +                            public String[] getTokenNames() {
 159.318 +                                return tokenNames;
 159.319 +                            }
 159.320 +                        };
 159.321 +
 159.322 +                        super.reportError(br, re);
 159.323 +                    }
 159.324 +                }
 159.325 +            };
 159.326 +
 159.327 +            PythonLexer lexer = new PythonLexer(new ANTLRStringStream(sourceCode));
 159.328 +            lexer.setErrorHandler(errorHandler);
 159.329 +            CommonTokenStream tokens = new CommonTokenStream(lexer);
 159.330 +            tokens.discardOffChannelTokens(true);
 159.331 +            PythonTokenSource indentedSource = new PythonTokenSource(tokens, fileName);
 159.332 +            CommonTokenStream indentedTokens = new CommonTokenStream(indentedSource);
 159.333 +            // Import line ending with a dot raise a NullPointerException in
 159.334 +            // org.python.antlr.GrammarActions.makeDottedText called from parser.file_input
 159.335 +            // sanitizeImportTokens will remove the dot token from the list of tokens in
 159.336 +            // indentedTokens to avoid the bug and add an error at this file.
 159.337 +            // See https://netbeans.org/bugzilla/show_bug.cgi?id=252356
 159.338 +            sanitizeImportTokens(indentedTokens, errors, file);
 159.339 +            org.python.antlr.PythonParser parser;
 159.340 +            if (charset != null) {
 159.341 +                parser = new org.python.antlr.PythonParser(indentedTokens, charset);
 159.342 +            } else {
 159.343 +                parser = new org.python.antlr.PythonParser(indentedTokens);
 159.344 +            }
 159.345 +            parser.setTreeAdaptor(new PythonTreeAdaptor());
 159.346 +            parser.setErrorHandler(errorHandler);
 159.347 +            org.python.antlr.PythonParser.file_input_return r = parser.file_input();
 159.348 +            PythonTree t = (PythonTree)r.getTree();
 159.349 +            PythonParserResult result = new PythonParserResult(t, context.snapshot);
 159.350 +            result.setErrors(errors);
 159.351 +
 159.352 +            result.setSanitized(context.sanitized, context.sanitizedRange, context.sanitizedContents);
 159.353 +            result.setSource(sourceCode);
 159.354 +
 159.355 +            return result;
 159.356 +        } catch (ParseException pe) {
 159.357 +            if (sanitizing == Sanitize.NONE) {
 159.358 +                PythonParserResult sanitizedResult = sanitize(context, sanitizing);
 159.359 +                if (sanitizedResult.isValid()) {
 159.360 +                    return sanitizedResult;
 159.361 +                } else {
 159.362 +                    int offset = pe.index;
 159.363 +                    assert offset >= 0;
 159.364 +                    String desc = pe.getLocalizedMessage();
 159.365 +                    if (desc == null) {
 159.366 +                        desc = pe.getMessage();
 159.367 +                    }
 159.368 +                    DefaultError error = new DefaultError(null /*key*/, desc, null, file, offset, offset, Severity.ERROR);
 159.369 +                    PythonParserResult parserResult = new PythonParserResult(null, context.snapshot);
 159.370 +                    parserResult.addError(error);
 159.371 +                    for (Error e : errors) {
 159.372 +                        parserResult.addError(e);
 159.373 +                    }
 159.374 +
 159.375 +                    return parserResult;
 159.376 +                }
 159.377 +            } else {
 159.378 +                return sanitize(context, sanitizing);
 159.379 +            }
 159.380 +        } catch (NullPointerException e) {
 159.381 +            String fileName = "";
 159.382 +            if (file != null) {
 159.383 +                fileName = FileUtil.getFileDisplayName(file);
 159.384 +            }
 159.385 +            e = Exceptions.attachMessage(e, "Was parsing " + fileName);
 159.386 +            Exceptions.printStackTrace(e);
 159.387 +            return new PythonParserResult(null, context.snapshot);
 159.388 +        } catch (Throwable t) {
 159.389 +            runtimeException = t;
 159.390 +            StackTraceElement[] stackTrace = t.getStackTrace();
 159.391 +            if (stackTrace != null && stackTrace.length > 0 && stackTrace[0].getClassName().startsWith("org.python.antlr")) {//.runtime.tree.RewriteRuleElementStream")) {
 159.392 +                // This is issue 150921
 159.393 +                // Don't bug user about it -- we already know
 159.394 +                Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Encountered issue #150921", t);
 159.395 +            } else {
 159.396 +                t = Exceptions.attachMessage(t, "Was parsing " + FileUtil.getFileDisplayName(file));
 159.397 +                Exceptions.printStackTrace(t);
 159.398 +            }
 159.399 +            return new PythonParserResult(null, context.snapshot);
 159.400 +        }
 159.401 +    }
 159.402 +
 159.403 +    private void sanitizeImportTokens(CommonTokenStream indentedTokens, List errors, FileObject file) {
 159.404 +        List tokens = indentedTokens.getTokens();
 159.405 +        List<CommonToken> tokensToRemove = new ArrayList<>();
 159.406 +        int i = 0;
 159.407 +        while (i < tokens.size()) {
 159.408 +            CommonToken importToken = (CommonToken)tokens.get(i);
 159.409 +            if ("import".equals(importToken.getText()) || "from".equals(importToken.getText())) {
 159.410 +                // sanitizeDotTokens return the index of the token that starts the next line
 159.411 +                i = sanitizeDotTokens(tokens, tokensToRemove, importToken, i + 1, errors, file);
 159.412 +            } else {
 159.413 +                i++;
 159.414 +            }
 159.415 +        }
 159.416 +
 159.417 +        for (CommonToken token : tokensToRemove) {
 159.418 +            tokens.remove(token);
 159.419 +        }
 159.420 +    }
 159.421 +
 159.422 +    private int sanitizeDotTokens(List tokens, List tokensToRemove, CommonToken importToken,
 159.423 +            int startIndex, List errors, FileObject file) {
 159.424 +        for (int j = startIndex; j < tokens.size() - 1; j++) {
 159.425 +            CommonToken dotToken = (CommonToken)tokens.get(j);
 159.426 +            CommonToken nextToken = (CommonToken)tokens.get(j + 1);
 159.427 +            if (".".equals(dotToken.getText())) {
 159.428 +                if (nextToken.getText().startsWith("\n")) {
 159.429 +                    tokensToRemove.add(dotToken);
 159.430 +                    String rawTokenText;
 159.431 +                    if (nextToken.getText().startsWith("\n")) {
 159.432 +                        rawTokenText = "\\n";
 159.433 +                    } else {
 159.434 +                        rawTokenText = " ";
 159.435 +                    }
 159.436 +                    errors.add(
 159.437 +                        new DefaultError(null, "Mismatch input '.' expecting NAME\nMissing NAME at '" + rawTokenText + "'",
 159.438 +                            null, file, importToken.getStartIndex(), dotToken.getStopIndex(), Severity.ERROR));
 159.439 +                }
 159.440 +            } else if ("\n".equals(nextToken.getText())) { // End of line, must continue looping from external loop
 159.441 +                return j + 1;
 159.442 +            }
 159.443 +        }
 159.444 +
 159.445 +        return startIndex;
 159.446 +    }
 159.447 +
 159.448 +    private static String asString(CharSequence sequence) {
 159.449 +        if (sequence instanceof String) {
 159.450 +            return (String)sequence;
 159.451 +        } else {
 159.452 +            return sequence.toString();
 159.453 +        }
 159.454 +    }
 159.455 +
 159.456 +
 159.457 +    @SuppressWarnings("fallthrough")
 159.458 +    private PythonParserResult sanitize(final Context context, final Sanitize sanitizing) {
 159.459 +
 159.460 +        switch (sanitizing) {
 159.461 +        case NEVER:
 159.462 +            return new PythonParserResult(null, context.snapshot);
 159.463 +
 159.464 +        case NONE:
 159.465 +            if (context.caretOffset != -1) {
 159.466 +                return parse(context, Sanitize.EDITED_DOT);
 159.467 +            }
 159.468 +
 159.469 +        case EDITED_DOT:
 159.470 +            // We've tried removing whitespace around the edit location
 159.471 +            // Fall through to try parsing with removing stuff around error location
 159.472 +            // (Don't bother doing this if errorOffset==caretOffset since that would try the same
 159.473 +            // source as EDITED_DOT which has no better chance of succeeding...)
 159.474 +            if (context.errorOffset != -1 && context.errorOffset != context.caretOffset) {
 159.475 +                return parse(context, Sanitize.ERROR_DOT);
 159.476 +            }
 159.477 +
 159.478 +        // Fall through to try the next trick
 159.479 +        case ERROR_DOT:
 159.480 +
 159.481 +            // We've tried removing dots - now try removing the whole line at the error position
 159.482 +            if (context.errorOffset != -1) {
 159.483 +                return parse(context, Sanitize.ERROR_LINE);
 159.484 +            }
 159.485 +
 159.486 +        // Fall through to try the next trick
 159.487 +        case ERROR_LINE:
 159.488 +
 159.489 +            // Messing with the error line didn't work - we could try "around" the error line
 159.490 +            // but I'm not attempting that now.
 159.491 +            // Finally try removing the whole line around the user editing position
 159.492 +            // (which could be far from where the error is showing up - but if you're typing
 159.493 +            // say a new "def" statement in a class, this will show up as an error on a mismatched
 159.494 +            // "end" statement rather than here
 159.495 +            if (context.caretOffset != -1) {
 159.496 +                return parse(context, Sanitize.EDITED_LINE);
 159.497 +            }
 159.498 +
 159.499 +        // Fall through for default handling
 159.500 +        case EDITED_LINE:
 159.501 +        default:
 159.502 +            // We're out of tricks - just return the failed parse result
 159.503 +            return new PythonParserResult(null, context.snapshot);
 159.504 +        }
 159.505 +    }
 159.506 +
 159.507 +    /**
 159.508 +     * Try cleaning up the source buffer around the current offset to increase
 159.509 +     * likelihood of parse success. Initially this method had a lot of
 159.510 +     * logic to determine whether a parse was likely to fail (e.g. invoking
 159.511 +     * the isEndMissing method from bracket completion etc.).
 159.512 +     * However, I am now trying a parse with the real source first, and then
 159.513 +     * only if that fails do I try parsing with sanitized source. Therefore,
 159.514 +     * this method has to be less conservative in ripping out code since it
 159.515 +     * will only be used when the regular source is failing.
 159.516 +     *
 159.517 +     * @todo Automatically close current statement by inserting ";"
 159.518 +     * @todo Handle sanitizing "new ^" from parse errors
 159.519 +     * @todo Replace "end" insertion fix with "}" insertion
 159.520 +     */
 159.521 +    private boolean sanitizeSource(Context context, Sanitize sanitizing) {
 159.522 +        int offset = context.caretOffset;
 159.523 +
 159.524 +        // Let caretOffset represent the offset of the portion of the buffer we'll be operating on
 159.525 +        if ((sanitizing == Sanitize.ERROR_DOT) || (sanitizing == Sanitize.ERROR_LINE)) {
 159.526 +            offset = context.errorOffset;
 159.527 +        }
 159.528 +
 159.529 +        // Don't attempt cleaning up the source if we don't have the buffer position we need
 159.530 +        if (offset == -1) {
 159.531 +            return false;
 159.532 +        }
 159.533 +
 159.534 +        // The user might be editing around the given caretOffset.
 159.535 +        // See if it looks modified
 159.536 +        // Insert an end statement? Insert a } marker?
 159.537 +        String doc = context.source;
 159.538 +        if (offset > doc.length()) {
 159.539 +            return false;
 159.540 +        }
 159.541 +
 159.542 +        try {
 159.543 +            // Sometimes the offset shows up on the next line
 159.544 +            if (GsfUtilities.isRowEmpty(doc, offset) || GsfUtilities.isRowWhite(doc, offset)) {
 159.545 +                offset = GsfUtilities.getRowStart(doc, offset) - 1;
 159.546 +                if (offset < 0) {
 159.547 +                    offset = 0;
 159.548 +                }
 159.549 +            }
 159.550 +
 159.551 +            if (!(GsfUtilities.isRowEmpty(doc, offset) || GsfUtilities.isRowWhite(doc, offset))) {
 159.552 +                if ((sanitizing == Sanitize.EDITED_LINE) || (sanitizing == Sanitize.ERROR_LINE)) {
 159.553 +                    // See if I should try to remove the current line, since it has text on it.
 159.554 +                    int lineEnd = GsfUtilities.getRowLastNonWhite(doc, offset);
 159.555 +
 159.556 +                    if (lineEnd != -1) {
 159.557 +                        lineEnd++; // lineEnd is exclusive, not inclusive
 159.558 +                        StringBuilder sb = new StringBuilder(doc.length());
 159.559 +                        int lineStart = GsfUtilities.getRowStart(doc, offset);
 159.560 +                        if (lineEnd >= lineStart + 2) {
 159.561 +                            sb.append(doc.substring(0, lineStart));
 159.562 +                            sb.append("//");
 159.563 +                            int rest = lineStart + 2;
 159.564 +                            if (rest < doc.length()) {
 159.565 +                                sb.append(doc.substring(rest, doc.length()));
 159.566 +                            }
 159.567 +                        } else {
 159.568 +                            // A line with just one character - can't replace with a comment
 159.569 +                            // Just replace the char with a space
 159.570 +                            sb.append(doc.substring(0, lineStart));
 159.571 +                            sb.append(" ");
 159.572 +                            int rest = lineStart + 1;
 159.573 +                            if (rest < doc.length()) {
 159.574 +                                sb.append(doc.substring(rest, doc.length()));
 159.575 +                            }
 159.576 +
 159.577 +                        }
 159.578 +
 159.579 +                        assert sb.length() == doc.length();
 159.580 +
 159.581 +                        context.sanitizedRange = new OffsetRange(lineStart, lineEnd);
 159.582 +                        context.sanitizedSource = sb.toString();
 159.583 +                        context.sanitizedContents = doc.substring(lineStart, lineEnd);
 159.584 +                        return true;
 159.585 +                    }
 159.586 +                } else {
 159.587 +                    assert sanitizing == Sanitize.ERROR_DOT || sanitizing == Sanitize.EDITED_DOT;
 159.588 +                    // Try nuking dots/colons from this line
 159.589 +                    // See if I should try to remove the current line, since it has text on it.
 159.590 +                    int lineStart = GsfUtilities.getRowStart(doc, offset);
 159.591 +                    int lineEnd = offset - 1;
 159.592 +                    while (lineEnd >= lineStart && lineEnd < doc.length()) {
 159.593 +                        if (!Character.isWhitespace(doc.charAt(lineEnd))) {
 159.594 +                            break;
 159.595 +                        }
 159.596 +                        lineEnd--;
 159.597 +                    }
 159.598 +                    if (lineEnd > lineStart) {
 159.599 +                        StringBuilder sb = new StringBuilder(doc.length());
 159.600 +                        String line = doc.substring(lineStart, lineEnd + 1);
 159.601 +                        int removeChars = 0;
 159.602 +                        int removeEnd = lineEnd + 1;
 159.603 +                        boolean isLineEnd = GsfUtilities.getRowLastNonWhite(context.source, lineEnd) <= lineEnd;
 159.604 +
 159.605 +                        if (line.endsWith(".")) { // NOI18N
 159.606 +                            removeChars = 1;
 159.607 +                        } else if (line.endsWith("(")) { // NOI18N
 159.608 +                            if (isLineEnd) {
 159.609 +                                removeChars = 1;
 159.610 +                            }
 159.611 +                        } else if (line.endsWith(",")) { // NOI18N                            removeChars = 1;
 159.612 +                            if (!isLineEnd) {
 159.613 +                                removeChars = 1;
 159.614 +                            }
 159.615 +                        } else if (line.endsWith(", ")) { // NOI18N
 159.616 +                            if (!isLineEnd) {
 159.617 +                                removeChars = 2;
 159.618 +                            }
 159.619 +                        } else if (line.endsWith(",)")) { // NOI18N
 159.620 +                            // Handle lone comma in parameter list - e.g.
 159.621 +                            // type "foo(a," -> you end up with "foo(a,|)" which doesn't parse - but
 159.622 +                            // the line ends with ")", not "," !
 159.623 +                            // Just remove the comma
 159.624 +                            removeChars = 1;
 159.625 +                            removeEnd--;
 159.626 +                        } else if (line.endsWith(", )")) { // NOI18N
 159.627 +                            // Just remove the comma
 159.628 +                            removeChars = 1;
 159.629 +                            removeEnd -= 2;
 159.630 +                        } else if (line.endsWith(" def") && isLineEnd) { // NOI18N
 159.631 +                            removeChars = 3;
 159.632 +                        } else {
 159.633 +//                            // Make sure the line doesn't end with one of the JavaScript keywords
 159.634 +//                            // (new, do, etc) - we can't handle that!
 159.635 +//                            for (String keyword : PythonUtils.PYTHON_KEYWORDS) { // reserved words are okay
 159.636 +//                                if (line.endsWith(keyword)) {
 159.637 +//                                    if ("print".equals(keyword)) { // NOI18N
 159.638 +//                                        // Only remove the keyword if it's the end of the line. Otherwise,
 159.639 +//                                        // it could have just been typed in front of something (e.g. inserted a print) and we don't
 159.640 +//                                        // want to confuse the parser with "va foo" instead of "var foo"
 159.641 +//                                        if (!isLineEnd) {
 159.642 +//                                            continue;
 159.643 +//                                        }
 159.644 +//                                    }
 159.645 +//                                    removeChars = 1;
 159.646 +//                                    break;
 159.647 +//                                }
 159.648 +//                            }
 159.649 +                        }
 159.650 +
 159.651 +                        if (removeChars == 0) {
 159.652 +                            return false;
 159.653 +                        }
 159.654 +
 159.655 +                        int removeStart = removeEnd - removeChars;
 159.656 +
 159.657 +                        sb.append(doc.substring(0, removeStart));
 159.658 +
 159.659 +                        for (int i = 0; i < removeChars; i++) {
 159.660 +                            sb.append(' ');
 159.661 +                        }
 159.662 +
 159.663 +                        if (removeEnd < doc.length()) {
 159.664 +                            sb.append(doc.substring(removeEnd, doc.length()));
 159.665 +                        }
 159.666 +                        assert sb.length() == doc.length();
 159.667 +
 159.668 +                        context.sanitizedRange = new OffsetRange(removeStart, removeEnd);
 159.669 +                        context.sanitizedSource = sb.toString();
 159.670 +                        context.sanitizedContents = doc.substring(removeStart, removeEnd);
 159.671 +                        return true;
 159.672 +                    }
 159.673 +                }
 159.674 +            }
 159.675 +        } catch (BadLocationException ble) {
 159.676 +            Exceptions.printStackTrace(ble);
 159.677 +        }
 159.678 +
 159.679 +        return false;
 159.680 +    }
 159.681 +
 159.682 +    private static int findLineOffset(String source, int line) {
 159.683 +        int offset = -1;
 159.684 +        for (int i = 0; i < line; i++) {
 159.685 +            offset = source.indexOf("\n", offset+1);
 159.686 +            if (offset == -1) {
 159.687 +                return source.length();
 159.688 +            }
 159.689 +        }
 159.690 +
 159.691 +        return Math.min(source.length(), offset+1);
 159.692 +    }
 159.693 +
 159.694 +    /** Attempts to sanitize the input buffer */
 159.695 +    public static enum Sanitize {
 159.696 +        /** Only parse the current file accurately, don't try heuristics */
 159.697 +        NEVER,
 159.698 +        /** Perform no sanitization */
 159.699 +        NONE,
 159.700 +        /** Try to remove the trailing . or :: at the caret line */
 159.701 +        EDITED_DOT,
 159.702 +        /** Try to remove the trailing . or :: at the error position, or the prior
 159.703 +         * line, or the caret line */
 159.704 +        ERROR_DOT,
 159.705 +        /** Try to cut out the error line */
 159.706 +        ERROR_LINE,
 159.707 +        /** Try to cut out the current edited line, if known */
 159.708 +        EDITED_LINE,
 159.709 +    }
 159.710 +
 159.711 +    /** Sanitize context */
 159.712 +    public static class Context {
 159.713 +        private FileObject file;
 159.714 +//        private ParseListener listener;
 159.715 +        private int errorOffset;
 159.716 +        private String source;
 159.717 +        private String sanitizedSource;
 159.718 +        private OffsetRange sanitizedRange = OffsetRange.NONE;
 159.719 +        private String sanitizedContents;
 159.720 +        private int caretOffset;
 159.721 +        private Sanitize sanitized = Sanitize.NONE;
 159.722 +//        private TranslatedSource translatedSource;
 159.723 +//        private Parser.Job job;
 159.724 +        private Snapshot snapshot;
 159.725 +        private Task task;
 159.726 +        private SourceModificationEvent event;
 159.727 +//
 159.728 +//        public Context(ParserFile parserFile, ParseListener listener, String source, int caretOffset, TranslatedSource translatedSource, Parser.Job job) {
 159.729 +//            this.file = parserFile;
 159.730 +//            this.listener = listener;
 159.731 +//            this.source = source;
 159.732 +//            this.caretOffset = caretOffset;
 159.733 +//            this.translatedSource = translatedSource;
 159.734 +//            this.job = job;
 159.735 +//
 159.736 +//
 159.737 +//            if (caretOffset != -1) {
 159.738 +//                sanitized = Sanitize.EDITED_DOT;
 159.739 +//            }
 159.740 +//        }
 159.741 +//
 159.742 +//        @Override
 159.743 +//        public String toString() {
 159.744 +//            return "PythonParser.Context(" + file.toString() + ")"; // NOI18N
 159.745 +//        }
 159.746 +//
 159.747 +//        public OffsetRange getSanitizedRange() {
 159.748 +//            return sanitizedRange;
 159.749 +//        }
 159.750 +//
 159.751 +//        public Sanitize getSanitized() {
 159.752 +//            return sanitized;
 159.753 +//        }
 159.754 +//
 159.755 +//        public String getSanitizedSource() {
 159.756 +//            return sanitizedSource;
 159.757 +//        }
 159.758 +//
 159.759 +//        public int getErrorOffset() {
 159.760 +//            return errorOffset;
 159.761 +//        }
 159.762 +    }
 159.763 +}
   160.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   160.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonParserResult.java	Mon Sep 21 13:01:16 2015 +0200
   160.3 @@ -0,0 +1,152 @@
   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.LinkedList;
  160.37 +import java.util.List;
  160.38 +import org.netbeans.api.annotations.common.NonNull;
  160.39 +import org.netbeans.modules.csl.api.Error;
  160.40 +import org.netbeans.modules.csl.api.OffsetRange;
  160.41 +import org.netbeans.modules.csl.spi.ParserResult;
  160.42 +import org.netbeans.modules.parsing.api.Snapshot;
  160.43 +import org.netbeans.modules.python.source.PythonParser.Sanitize;
  160.44 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  160.45 +import org.python.antlr.PythonTree;
  160.46 +
  160.47 +/**
  160.48 + * A ParserResult for Python. The AST Jython's AST.
  160.49 + *
  160.50 + * @todo Cache AstPath for caret position here!
  160.51 + * @author Tor Norbye
  160.52 + */
  160.53 +public class PythonParserResult extends ParserResult {
  160.54 +    private PythonTree root;
  160.55 +    private List<Error> errors;
  160.56 +    private OffsetRange sanitizedRange = OffsetRange.NONE;
  160.57 +    private String source;
  160.58 +    private String sanitizedContents;
  160.59 +    private PythonParser.Sanitize sanitized;
  160.60 +    private PythonStructureScanner.AnalysisResult analysisResult;
  160.61 +    private SymbolTable symbolTable;
  160.62 +    private int codeTemplateOffset = -1;
  160.63 +
  160.64 +    public PythonParserResult(PythonTree tree, @NonNull Snapshot snapshot) {
  160.65 +        super(snapshot);
  160.66 +        this.root = tree;
  160.67 +        this.errors = new LinkedList<>();
  160.68 +    }
  160.69 +
  160.70 +    public PythonTree getRoot() {
  160.71 +        return root;
  160.72 +    }
  160.73 +
  160.74 +    @Override
  160.75 +    public List<? extends Error> getDiagnostics() {
  160.76 +        return errors;
  160.77 +    }
  160.78 +
  160.79 +    @Override
  160.80 +    protected void invalidate() {
  160.81 +    }
  160.82 +
  160.83 +    public void setErrors(List<? extends Error> errors) {
  160.84 +        this.errors.clear();
  160.85 +        this.errors.addAll(errors);
  160.86 +    }
  160.87 +    
  160.88 +    /**
  160.89 +     * Set the range of source that was sanitized, if any.
  160.90 +     */
  160.91 +    void setSanitized(PythonParser.Sanitize sanitized, OffsetRange sanitizedRange, String sanitizedContents) {
  160.92 +        this.sanitized = sanitized;
  160.93 +        this.sanitizedRange = sanitizedRange;
  160.94 +        this.sanitizedContents = sanitizedContents;
  160.95 +        if (sanitizedContents == null || sanitizedRange == OffsetRange.NONE) {
  160.96 +            this.sanitized = Sanitize.NONE;
  160.97 +        }
  160.98 +    }
  160.99 +
 160.100 +    public PythonParser.Sanitize getSanitized() {
 160.101 +        return sanitized;
 160.102 +    }
 160.103 +
 160.104 +    /**
 160.105 +     * Return whether the source code for the parse result was "cleaned"
 160.106 +     * or "sanitized" (modified to reduce chance of parser errors) or not.
 160.107 +     * This method returns OffsetRange.NONE if the source was not sanitized,
 160.108 +     * otherwise returns the actual sanitized range.
 160.109 +     */
 160.110 +    public OffsetRange getSanitizedRange() {
 160.111 +        return sanitizedRange;
 160.112 +    }
 160.113 +
 160.114 +    public SymbolTable getSymbolTable() {
 160.115 +        if (symbolTable == null) {
 160.116 +            symbolTable = new SymbolTable(root, getSnapshot().getSource().getFileObject());
 160.117 +        }
 160.118 +
 160.119 +        return symbolTable;
 160.120 +    }
 160.121 +
 160.122 +    public String getSanitizedContents() {
 160.123 +        return sanitizedContents;
 160.124 +    }
 160.125 +
 160.126 +    public String getSource() {
 160.127 +        return source;
 160.128 +    }
 160.129 +
 160.130 +    public void setSource(String source) {
 160.131 +        this.source = source;
 160.132 +    }
 160.133 +
 160.134 +    /**
 160.135 +     * @return the codeTemplateOffset
 160.136 +     */
 160.137 +    public int getCodeTemplateOffset() {
 160.138 +        return codeTemplateOffset;
 160.139 +    }
 160.140 +
 160.141 +    /**
 160.142 +     * @param codeTemplateOffset the codeTemplateOffset to set
 160.143 +     */
 160.144 +    public void setCodeTemplateOffset(int codeTemplateOffset) {
 160.145 +        this.codeTemplateOffset = codeTemplateOffset;
 160.146 +    }
 160.147 +
 160.148 +    public void addError(Error e) {
 160.149 +        errors.add(e);
 160.150 +    }
 160.151 +
 160.152 +    public boolean isValid() {
 160.153 +        return errors.isEmpty();
 160.154 +    }
 160.155 +}
   161.1 --- a/python.source/src/org/netbeans/modules/python/source/PythonProjectSourceLevelQuery.java	Fri Sep 18 16:20:24 2015 -0500
   161.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   161.3 @@ -1,29 +0,0 @@
   161.4 -/*
   161.5 - * To change this license header, choose License Headers in Project Properties.
   161.6 - * To change this template file, choose Tools | Templates
   161.7 - * and open the template in the editor.
   161.8 - */
   161.9 -package org.netbeans.modules.python.source;
  161.10 -
  161.11 -import org.netbeans.modules.python.source.queries.SourceLevelQueryImplementation;
  161.12 -import org.netbeans.api.project.FileOwnerQuery;
  161.13 -import org.netbeans.api.project.Project;
  161.14 -import org.openide.filesystems.FileObject;
  161.15 -import org.openide.util.lookup.ServiceProvider;
  161.16 -
  161.17 -@ServiceProvider(service = SourceLevelQueryImplementation.class, position = 400)
  161.18 -public class PythonProjectSourceLevelQuery implements SourceLevelQueryImplementation {
  161.19 -
  161.20 -    @Override
  161.21 -    public Result getSourceLevel(FileObject pythonFile) {
  161.22 -        final Project project = FileOwnerQuery.getOwner(pythonFile);
  161.23 -        if (project != null) {
  161.24 -            SourceLevelQueryImplementation impl = project.getLookup().lookup(SourceLevelQueryImplementation.class);
  161.25 -            if (impl != null) {
  161.26 -                return impl.getSourceLevel(pythonFile);
  161.27 -            }
  161.28 -        }
  161.29 -        return null;
  161.30 -    }
  161.31 -
  161.32 -}
   162.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   162.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonStructureItem.java	Mon Sep 21 13:01:16 2015 +0200
   162.3 @@ -0,0 +1,195 @@
   162.4 +/*
   162.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   162.6 + *
   162.7 + * Copyright 1997-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 + * Contributor(s):
  162.31 + *
  162.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  162.33 + */
  162.34 +package org.netbeans.modules.python.source;
  162.35 +
  162.36 +import java.util.ArrayList;
  162.37 +import java.util.Collections;
  162.38 +import java.util.List;
  162.39 +import javax.swing.ImageIcon;
  162.40 +import org.netbeans.modules.csl.api.ElementHandle;
  162.41 +import org.netbeans.modules.csl.api.ElementKind;
  162.42 +import org.netbeans.modules.csl.api.HtmlFormatter;
  162.43 +import org.netbeans.modules.csl.api.Modifier;
  162.44 +import org.netbeans.modules.csl.api.StructureItem;
  162.45 +import org.netbeans.modules.python.source.elements.AstElement;
  162.46 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  162.47 +import org.openide.util.ImageUtilities;
  162.48 +import org.python.antlr.PythonTree;
  162.49 +import org.python.antlr.ast.ClassDef;
  162.50 +import org.python.antlr.ast.FunctionDef;
  162.51 +
  162.52 +public final class PythonStructureItem extends AstElement implements StructureItem {
  162.53 +    private List<PythonStructureItem> children;
  162.54 +    private PythonStructureItem parent;
  162.55 +
  162.56 +    public PythonStructureItem(SymbolTable scopes, ClassDef def) {
  162.57 +        this(scopes, def, def.getInternalName(), ElementKind.CLASS);
  162.58 +    }
  162.59 +
  162.60 +    public PythonStructureItem(SymbolTable scopes, FunctionDef def) {
  162.61 +        this(scopes, def, def.getInternalName(), ElementKind.METHOD);
  162.62 +        if ("__init__".equals(name)) { // NOI18N
  162.63 +            kind = ElementKind.CONSTRUCTOR;
  162.64 +        }
  162.65 +    }
  162.66 +    
  162.67 +    public PythonStructureItem(SymbolTable scopes, PythonTree node, String name, ElementKind kind) {
  162.68 +        super(scopes, node, name, kind);
  162.69 +        this.node = node;
  162.70 +        this.name = name;
  162.71 +        this.kind = kind;
  162.72 +    }
  162.73 +
  162.74 +    void add(PythonStructureItem child) {
  162.75 +        if (children == null) {
  162.76 +            children = new ArrayList<>();
  162.77 +        }
  162.78 +        children.add(child);
  162.79 +        child.parent = this;
  162.80 +    }
  162.81 +
  162.82 +    @Override
  162.83 +    public String getSortText() {
  162.84 +        return name;
  162.85 +    }
  162.86 +
  162.87 +    @Override
  162.88 +    public String getHtml(HtmlFormatter formatter) {
  162.89 +        formatter.appendText(name);
  162.90 +        if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
  162.91 +            FunctionDef def = (FunctionDef)node;
  162.92 +            List<String> params = PythonAstUtils.getParameters(def);
  162.93 +            if (params.size() > 0) {
  162.94 +                boolean isFirst = true;
  162.95 +                formatter.appendHtml("(");
  162.96 +                formatter.parameters(true);
  162.97 +                for (String param : params) {
  162.98 +                    if (isFirst) {
  162.99 +                        isFirst = false;
 162.100 +                    } else {
 162.101 +                        formatter.appendText(",");
 162.102 +                    }
 162.103 +                    formatter.appendText(param);
 162.104 +                }
 162.105 +                formatter.parameters(false);
 162.106 +                formatter.appendHtml(")");
 162.107 +            }
 162.108 +        }
 162.109 +        return formatter.getText();
 162.110 +    }
 162.111 +
 162.112 +    @Override
 162.113 +    public ElementHandle getElementHandle() {
 162.114 +        return null;
 162.115 +    }
 162.116 +
 162.117 +    @Override
 162.118 +    public boolean isLeaf() {
 162.119 +        return children == null;
 162.120 +    }
 162.121 +
 162.122 +    @Override
 162.123 +    public List<? extends StructureItem> getNestedItems() {
 162.124 +        return children == null ? Collections.<StructureItem>emptyList() : children;
 162.125 +    }
 162.126 +
 162.127 +    @Override
 162.128 +    public long getPosition() {
 162.129 +        return node.getCharStartIndex();
 162.130 +    }
 162.131 +
 162.132 +    @Override
 162.133 +    public long getEndPosition() {
 162.134 +        return node.getCharStopIndex();
 162.135 +    }
 162.136 +
 162.137 +    @Override
 162.138 +    public ImageIcon getCustomIcon() {
 162.139 +        if (kind == ElementKind.CLASS && getModifiers().contains(Modifier.PRIVATE)) {
 162.140 +            // GSF doesn't automatically handle icons on private classes, so I have to
 162.141 +            // work around that here
 162.142 +            return ImageUtilities.loadImageIcon("org/netbeans/modules/python/editor/resources/private-class.png", false); //NOI18N
 162.143 +        }
 162.144 +
 162.145 +        return null;
 162.146 +    }
 162.147 +
 162.148 +    @Override
 162.149 +    public Object getSignature() {
 162.150 +        if ((kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) && parent != null &&
 162.151 +                parent.kind == ElementKind.CLASS) {
 162.152 +            return parent.name + "." + name;
 162.153 +        }
 162.154 +        return super.getSignature();
 162.155 +    }
 162.156 +
 162.157 +    @Override
 162.158 +    public boolean equals(Object obj) {
 162.159 +        if (obj == null) {
 162.160 +            return false;
 162.161 +        }
 162.162 +        if (getClass() != obj.getClass()) {
 162.163 +            return false;
 162.164 +        }
 162.165 +        final PythonStructureItem other = (PythonStructureItem)obj;
 162.166 +        if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
 162.167 +            return false;
 162.168 +        }
 162.169 +        if (this.kind != other.kind) {
 162.170 +            return false;
 162.171 +        }
 162.172 +        if (this.getModifiers() != other.getModifiers() && (this.modifiers == null || !this.modifiers.equals(other.modifiers))) {
 162.173 +            return false;
 162.174 +        }
 162.175 +
 162.176 +        if ((kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) && node != null && other.node != null) {
 162.177 +            FunctionDef def = (FunctionDef)node;
 162.178 +            List<String> params = PythonAstUtils.getParameters(def);
 162.179 +            List<String> otherParams = PythonAstUtils.getParameters((FunctionDef)other.node);
 162.180 +            if (!params.equals((otherParams))) {
 162.181 +                return false;
 162.182 +            }
 162.183 +        }
 162.184 +
 162.185 +//        if (this.getNestedItems().size() != other.getNestedItems().size()) {
 162.186 +//            return false;
 162.187 +//        }
 162.188 +//
 162.189 +        return true;
 162.190 +    }
 162.191 +
 162.192 +    @Override
 162.193 +    public int hashCode() {
 162.194 +        int hash = 7;
 162.195 +        hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0);
 162.196 +        return hash;
 162.197 +    }
 162.198 +}
   163.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   163.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonStructureScanner.java	Mon Sep 21 13:01:16 2015 +0200
   163.3 @@ -0,0 +1,274 @@
   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;
  163.35 +
  163.36 +import java.util.ArrayList;
  163.37 +import java.util.Collections;
  163.38 +import java.util.HashMap;
  163.39 +import java.util.List;
  163.40 +import java.util.Map;
  163.41 +import javax.swing.text.BadLocationException;
  163.42 +import org.netbeans.modules.python.source.lexer.PythonLexerUtils;
  163.43 +import org.netbeans.editor.BaseDocument;
  163.44 +import org.netbeans.editor.Utilities;
  163.45 +import org.netbeans.modules.csl.api.ElementKind;
  163.46 +import org.netbeans.modules.csl.api.OffsetRange;
  163.47 +import org.netbeans.modules.csl.api.StructureItem;
  163.48 +import org.netbeans.modules.csl.api.StructureScanner;
  163.49 +import org.netbeans.modules.csl.api.StructureScanner.Configuration;
  163.50 +import org.netbeans.modules.csl.spi.GsfUtilities;
  163.51 +import org.netbeans.modules.csl.spi.ParserResult;
  163.52 +import org.netbeans.modules.python.source.scopes.ScopeInfo;
  163.53 +import org.netbeans.modules.python.source.scopes.SymInfo;
  163.54 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  163.55 +import org.openide.util.Exceptions;
  163.56 +import org.python.antlr.PythonTree;
  163.57 +import org.python.antlr.Visitor;
  163.58 +import org.python.antlr.ast.ClassDef;
  163.59 +import org.python.antlr.ast.FunctionDef;
  163.60 +import org.python.antlr.ast.Str;
  163.61 +
  163.62 +/**
  163.63 + * This class analyzes the structure of a Python parse tree
  163.64 + * and infers structure (navigation items, folds, etc.)
  163.65 + *
  163.66 + * @author Tor Norbye
  163.67 + */
  163.68 +public class PythonStructureScanner implements StructureScanner {
  163.69 +    
  163.70 +    public static AnalysisResult analyze(PythonParserResult info) {
  163.71 +        AnalysisResult analysisResult = new AnalysisResult();
  163.72 +
  163.73 +        PythonTree root = PythonAstUtils.getRoot(info);
  163.74 +        if (root != null) {
  163.75 +            SymbolTable scopes = PythonAstUtils.getParseResult(info).getSymbolTable();
  163.76 +            StructureVisitor visitor = new StructureVisitor(scopes);
  163.77 +            try {
  163.78 +                visitor.visit(root);
  163.79 +                analysisResult.setElements(visitor.getRoots());
  163.80 +            } catch (Exception ex) {
  163.81 +                Exceptions.printStackTrace(ex);
  163.82 +            }
  163.83 +        }
  163.84 +
  163.85 +        return analysisResult;
  163.86 +    }
  163.87 +
  163.88 +    @Override
  163.89 +    public List<? extends StructureItem> scan(ParserResult info) {
  163.90 +        PythonParserResult parseResult = PythonAstUtils.getParseResult(info);
  163.91 +        if (parseResult == null) {
  163.92 +            return Collections.emptyList();
  163.93 +        }
  163.94 +
  163.95 +        return getStructure(parseResult).getElements();
  163.96 +    }
  163.97 +    
  163.98 +    public PythonStructureScanner.AnalysisResult getStructure(PythonParserResult result) {
  163.99 +        // TODO Cache ! (Used to be in PythonParserResult
 163.100 +        AnalysisResult analysisResult = PythonStructureScanner.analyze(result);
 163.101 +        return analysisResult;
 163.102 +    }
 163.103 +
 163.104 +    @Override
 163.105 +    public Map<String, List<OffsetRange>> folds(ParserResult info) {
 163.106 +        PythonParserResult result = PythonAstUtils.getParseResult(info);
 163.107 +        PythonTree root = PythonAstUtils.getRoot(result);
 163.108 +        if (root == null) {
 163.109 +            return Collections.emptyMap();
 163.110 +        }
 163.111 +
 163.112 +        //TranslatedSource source = result.getTranslatedSource();
 163.113 +        //
 163.114 +        //AnalysisResult ar = result.getStructure();
 163.115 +        //
 163.116 +        //List<?extends AstElement> elements = ar.getElements();
 163.117 +        //List<StructureItem> itemList = new ArrayList<StructureItem>(elements.size());
 163.118 +
 163.119 +        BaseDocument doc = GsfUtilities.getDocument(result.getSnapshot().getSource().getFileObject(), false);
 163.120 +        if (doc != null) {
 163.121 +            try {
 163.122 +                doc.readLock(); // For Utilities.getRowEnd() access
 163.123 +                FoldVisitor visitor = new FoldVisitor((PythonParserResult) info, doc);
 163.124 +                visitor.visit(root);
 163.125 +                List<OffsetRange> codeBlocks = visitor.getCodeBlocks();
 163.126 +
 163.127 +                Map<String, List<OffsetRange>> folds = new HashMap<>();
 163.128 +                folds.put("codeblocks", codeBlocks); // NOI18N
 163.129 +
 163.130 +                return folds;
 163.131 +            } catch (Exception ex) {
 163.132 +                Exceptions.printStackTrace(ex);
 163.133 +            } finally {
 163.134 +                doc.readUnlock();
 163.135 +            }
 163.136 +        }
 163.137 +        return Collections.emptyMap();
 163.138 +    }
 163.139 +
 163.140 +    @Override
 163.141 +    public Configuration getConfiguration() {
 163.142 +        return new Configuration(true, true, -1);
 163.143 +    }
 163.144 +
 163.145 +    private static class FoldVisitor extends Visitor {
 163.146 +        private List<OffsetRange> codeBlocks = new ArrayList<>();
 163.147 +        private PythonParserResult info;
 163.148 +        private BaseDocument doc;
 163.149 +
 163.150 +        private FoldVisitor(PythonParserResult info, BaseDocument doc) {
 163.151 +            this.info = info;
 163.152 +            this.doc = doc;
 163.153 +        }
 163.154 +
 163.155 +        private void addFoldRange(PythonTree node) {
 163.156 +            OffsetRange astRange = PythonAstUtils.getRange(node);
 163.157 +
 163.158 +            OffsetRange lexRange = PythonLexerUtils.getLexerOffsets(info, astRange);
 163.159 +            if (lexRange != OffsetRange.NONE) {
 163.160 +                try {
 163.161 +                    int startRowEnd = Utilities.getRowEnd(doc, lexRange.getStart());
 163.162 +                    if (startRowEnd < lexRange.getEnd()) {
 163.163 +                        codeBlocks.add(new OffsetRange(startRowEnd, lexRange.getEnd()));
 163.164 +                    }
 163.165 +                } catch (BadLocationException ex) {
 163.166 +                    Exceptions.printStackTrace(ex);
 163.167 +                }
 163.168 +            }
 163.169 +        }
 163.170 +
 163.171 +        @Override
 163.172 +        public Object visitClassDef(ClassDef node) throws Exception {
 163.173 +            addFoldRange(node);
 163.174 +
 163.175 +            return super.visitClassDef(node);
 163.176 +        }
 163.177 +
 163.178 +        @Override
 163.179 +        public Object visitFunctionDef(FunctionDef node) throws Exception {
 163.180 +            addFoldRange(node);
 163.181 +
 163.182 +            return super.visitFunctionDef(node);
 163.183 +        }
 163.184 +
 163.185 +        @Override
 163.186 +        public Object visitStr(Str node) throws Exception {
 163.187 +            addFoldRange(node);
 163.188 +            return super.visitStr(node);
 163.189 +        }
 163.190 +
 163.191 +        public List<OffsetRange> getCodeBlocks() {
 163.192 +            return codeBlocks;
 163.193 +        }
 163.194 +    }
 163.195 +
 163.196 +    private static class StructureVisitor extends Visitor {
 163.197 +        List<PythonStructureItem> roots = new ArrayList<>();
 163.198 +        List<PythonStructureItem> stack = new ArrayList<>();
 163.199 +        SymbolTable scopes;
 163.200 +
 163.201 +        StructureVisitor(SymbolTable scopes) {
 163.202 +            this.scopes = scopes;
 163.203 +        }
 163.204 +
 163.205 +        private List<PythonStructureItem> getRoots() {
 163.206 +            return roots;
 163.207 +        }
 163.208 +
 163.209 +        @Override
 163.210 +        public Object visitClassDef(ClassDef def) throws Exception {
 163.211 +            PythonStructureItem item = new PythonStructureItem(scopes, def);
 163.212 +            add(item);
 163.213 +
 163.214 +            ScopeInfo scope = scopes.getScopeInfo(def);
 163.215 +            if (scope != null && scope.attributes.size() > 0) {
 163.216 +                for (Map.Entry<String, SymInfo> entry : scope.attributes.entrySet()) {
 163.217 +                    // TODO - sort these puppies? Right now their natural order will be
 163.218 +                    // random (hashkey dependent) instead of by source position or by name
 163.219 +                    SymInfo sym = entry.getValue();
 163.220 +                    if (sym.node != null) {
 163.221 +                        String name = entry.getKey();
 163.222 +                        PythonStructureItem attribute = new PythonStructureItem(scopes, sym.node, name, ElementKind.ATTRIBUTE);
 163.223 +                        item.add(attribute);
 163.224 +                    }
 163.225 +                }
 163.226 +            }
 163.227 +
 163.228 +            stack.add(item);
 163.229 +            Object result = super.visitClassDef(def);
 163.230 +            stack.remove(stack.size() - 1);
 163.231 +
 163.232 +            return result;
 163.233 +        }
 163.234 +
 163.235 +        @Override
 163.236 +        public Object visitFunctionDef(FunctionDef def) throws Exception {
 163.237 +            PythonStructureItem item = new PythonStructureItem(scopes, def);
 163.238 +
 163.239 +            add(item);
 163.240 +            stack.add(item);
 163.241 +            Object result = super.visitFunctionDef(def);
 163.242 +            stack.remove(stack.size() - 1);
 163.243 +
 163.244 +            return result;
 163.245 +        }
 163.246 +
 163.247 +        private void add(PythonStructureItem child) {
 163.248 +            PythonStructureItem parent = stack.size() > 0 ? stack.get(stack.size() - 1) : null;
 163.249 +            if (parent == null) {
 163.250 +                roots.add(child);
 163.251 +            } else {
 163.252 +                parent.add(child);
 163.253 +            }
 163.254 +        }
 163.255 +    }
 163.256 +
 163.257 +    public static class AnalysisResult {
 163.258 +        //private List<?extends AstElement> elements;
 163.259 +        private List<PythonStructureItem> elements;
 163.260 +
 163.261 +        private AnalysisResult() {
 163.262 +        }
 163.263 +
 163.264 +        //private void setElements(List<?extends AstElement> elements) {
 163.265 +        private void setElements(List<PythonStructureItem> elements) {
 163.266 +            this.elements = elements;
 163.267 +        }
 163.268 +
 163.269 +        //public List<?extends AstElement> getElements() {
 163.270 +        public List<PythonStructureItem> getElements() {
 163.271 +            if (elements == null) {
 163.272 +                return Collections.emptyList();
 163.273 +            }
 163.274 +            return elements;
 163.275 +        }
 163.276 +    }
 163.277 +}
   164.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   164.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonUtils.java	Mon Sep 21 13:01:16 2015 +0200
   164.3 @@ -0,0 +1,513 @@
   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;
  164.35 +
  164.36 +import java.util.Comparator;
  164.37 +import java.util.List;
  164.38 +import javax.swing.text.Document;
  164.39 +import org.netbeans.api.annotations.common.NonNull;
  164.40 +import org.netbeans.api.project.FileOwnerQuery;
  164.41 +import org.netbeans.api.project.Project;
  164.42 +import org.netbeans.api.project.ProjectUtils;
  164.43 +import org.netbeans.api.project.SourceGroup;
  164.44 +import org.netbeans.api.project.Sources;
  164.45 +import org.netbeans.modules.python.api.PythonMIMEResolver;
  164.46 +import org.netbeans.modules.python.api.PythonPlatform;
  164.47 +import org.netbeans.modules.python.api.PythonPlatformManager;
  164.48 +import org.openide.filesystems.FileObject;
  164.49 +import org.openide.filesystems.FileUtil;
  164.50 +import org.openide.util.NbBundle;
  164.51 +import org.python.antlr.PythonTree;
  164.52 +import org.python.antlr.ast.Attribute;
  164.53 +import org.python.antlr.ast.Name;
  164.54 +
  164.55 +/**
  164.56 + *
  164.57 + * @author Tor Norbye
  164.58 + */
  164.59 +public class PythonUtils {
  164.60 +    public static boolean canContainPython(FileObject f) {
  164.61 +        String mimeType = f.getMIMEType();
  164.62 +        return PythonMIMEResolver.PYTHON_MIME_TYPE.equals(mimeType);
  164.63 +    // TODO:       "text/x-yaml".equals(mimeType) ||  // NOI18N
  164.64 +    // RubyInstallation.RHTML_MIME_TYPE.equals(mimeType);
  164.65 +    }
  164.66 +
  164.67 +    public static boolean isPythonFile(FileObject f) {
  164.68 +        return PythonMIMEResolver.PYTHON_MIME_TYPE.equals(f.getMIMEType());
  164.69 +    }
  164.70 +
  164.71 +    public static boolean isRstFile(FileObject f) {
  164.72 +        return "rst".equals(f.getExt()); // NOI18N
  164.73 +    }
  164.74 +
  164.75 +    public static boolean isPythonDocument(Document doc) {
  164.76 +        String mimeType = (String)doc.getProperty("mimeType"); // NOI18N
  164.77 +
  164.78 +        return PythonMIMEResolver.PYTHON_MIME_TYPE.equals(mimeType);
  164.79 +    }
  164.80 +    public static final String DOT__INIT__ = ".__init__"; // NOI18N
  164.81 +
  164.82 +    // From PythonProjectType
  164.83 +    public static final String SOURCES_TYPE_PYTHON = "python"; // NOI18N
  164.84 +
  164.85 +    // Cache
  164.86 +    private static FileObject prevParent;
  164.87 +    private static String prevRootUrl;
  164.88 +
  164.89 +    /**
  164.90 +     * Produce the module name (including packages) for a given python source file.
  164.91 +     * 
  164.92 +     * @param fo The source file (can be null, if file is not))
  164.93 +     * @param file The parser file (can be null, if fo is not).
  164.94 +     * @param fileName The filename (basename only)
  164.95 +     * @param projectRelativeName If non null, the path from the project root down to this file
  164.96 +     * @return A string for the full package module name
  164.97 +     */
  164.98 +    public static String getModuleName(@NonNull FileObject fo) {
  164.99 +
 164.100 +        // TODO - use PythonPlatform's library roots!
 164.101 +
 164.102 +        String module = fo.getName();
 164.103 +
 164.104 +        // First see if we're on the load path for the platform, and if so,
 164.105 +        // use that as the base
 164.106 +        // TODO - look up platform for the current search context instead of all platforms!!
 164.107 +        if (fo.getParent() != prevParent) {
 164.108 +            prevRootUrl = null;
 164.109 +            prevParent = fo.getParent();
 164.110 +        }
 164.111 +
 164.112 +        String url = fo.toURL().toExternalForm();
 164.113 +        if (prevRootUrl == null) {
 164.114 +            boolean found = false;
 164.115 +            PythonPlatformManager manager = PythonPlatformManager.getInstance();
 164.116 +
 164.117 +            PlatformSearch:
 164.118 +            for (String name : manager.getPlatformList()) {
 164.119 +                PythonPlatform platform = manager.getPlatform(name);
 164.120 +                if (platform != null) {
 164.121 +                    List<FileObject> unique = platform.getUniqueLibraryRoots();
 164.122 +                    for (FileObject root : unique) {
 164.123 +                        if (FileUtil.isParentOf(root, fo)) {
 164.124 +                            for (FileObject r : platform.getLibraryRoots()) {
 164.125 +                                if (FileUtil.isParentOf(r, fo)) {
 164.126 +                                    // See if the folder itself contains
 164.127 +                                    // an __init__.py file - if it does,
 164.128 +                                    // then include the directory itself
 164.129 +                                    // in the package name.
 164.130 +                                    if (r.getFileObject("__init__.py") != null) { // NOI18N
 164.131 +                                        r = r.getParent();
 164.132 +                                    }
 164.133 +
 164.134 +                                    prevRootUrl = r.toURL().toExternalForm();
 164.135 +                                    found = true;
 164.136 +                                    break PlatformSearch;
 164.137 +                                }
 164.138 +                            }
 164.139 +                            break PlatformSearch;
 164.140 +                        }
 164.141 +                    }
 164.142 +                }
 164.143 +            }
 164.144 +
 164.145 +            if (!found) {
 164.146 +                Project project = FileOwnerQuery.getOwner(fo);
 164.147 +                if (project != null) {
 164.148 +                    Sources source = ProjectUtils.getSources(project);
 164.149 +                    // Look up the source path
 164.150 +                    SourceGroup[] sourceGroups = source.getSourceGroups(SOURCES_TYPE_PYTHON);
 164.151 +                    for (SourceGroup group : sourceGroups) {
 164.152 +                        FileObject folder = group.getRootFolder();
 164.153 +                        if (FileUtil.isParentOf(folder, fo)) {
 164.154 +                            // See if the folder itself contains
 164.155 +                            // an __init__.py file - if it does,
 164.156 +                            // then include the directory itself
 164.157 +                            // in the package name.
 164.158 +                            if (folder.getFileObject("__init__.py") != null) { // NOI18N
 164.159 +                                folder = folder.getParent();
 164.160 +                            }
 164.161 +
 164.162 +                            prevRootUrl = folder.toURL().toExternalForm();
 164.163 +                            break;
 164.164 +                        }
 164.165 +                    }
 164.166 +                }
 164.167 +            }
 164.168 +        }
 164.169 +
 164.170 +        if (prevRootUrl != null) {
 164.171 +            module = url.substring(prevRootUrl.length());
 164.172 +            if (module.startsWith("/")) {
 164.173 +                module = module.substring(1);
 164.174 +            }
 164.175 +        }
 164.176 +
 164.177 +        // Strip off .y extension
 164.178 +        if (module.endsWith(".py")) { // NOI18N
 164.179 +            module = module.substring(0, module.length() - 3);
 164.180 +        }
 164.181 +
 164.182 +        if (module.indexOf('/') != -1) {
 164.183 +            module = module.replace('/', '.');
 164.184 +        }
 164.185 +
 164.186 +        if (module.endsWith(DOT__INIT__)) {
 164.187 +            module = module.substring(0, module.length() - DOT__INIT__.length());
 164.188 +        }
 164.189 +
 164.190 +        return module;
 164.191 +    }
 164.192 +
 164.193 +    // According to https://hg.python.org/cpython/file/3.5/Lib/keyword.py
 164.194 +    // and https://hg.python.org/cpython/file/2.7/Lib/keyword.py
 164.195 +    static final String[] PYTHON_KEYWORDS = new String[]{
 164.196 +        "False", // NOI18N
 164.197 +        "None", // NOI18N
 164.198 +        "True", // NOI18N
 164.199 +        "and", // NOI18N
 164.200 +        "as", // NOI18N
 164.201 +        "assert", // NOI18N
 164.202 +        "break", // NOI18N
 164.203 +        "class", // NOI18N
 164.204 +        "continue", // NOI18N
 164.205 +        "def", // NOI18N
 164.206 +        "del", // NOI18N
 164.207 +        "elif", // NOI18N
 164.208 +        "else", // NOI18N
 164.209 +        "except", // NOI18N
 164.210 +        "finally", // NOI18N
 164.211 +        "for", // NOI18N
 164.212 +        "from", // NOI18N
 164.213 +        "global", // NOI18N
 164.214 +        "if", // NOI18N
 164.215 +        "import", // NOI18N
 164.216 +        "in", // NOI18N
 164.217 +        "is", // NOI18N
 164.218 +        "lambda", // NOI18N
 164.219 +        "nonlocal", // NOI18N
 164.220 +        "not", // NOI18N
 164.221 +        "or", // NOI18N
 164.222 +        "pass", // NOI18N
 164.223 +        "raise", // NOI18N
 164.224 +        "return", // NOI18N
 164.225 +        "try", // NOI18N
 164.226 +        "while", // NOI18N
 164.227 +        "with", // NOI18N
 164.228 +        "yield", // NOI18N
 164.229 +        "async", // NOI18N, Python 3.5 only
 164.230 +        "await", // NOI18N, Python 3.5 only
 164.231 +        "exec", // NOI18N, Python 2 only
 164.232 +        "print", // NOI18N, Pytohn 2 only, function in python 3
 164.233 +    };
 164.234 +
 164.235 +    public static boolean isPythonKeyword(String name) {
 164.236 +        for (String s : PYTHON_KEYWORDS) {
 164.237 +            if (s.equals(name)) {
 164.238 +                return true;
 164.239 +            }
 164.240 +        }
 164.241 +
 164.242 +        return false;
 164.243 +    }
 164.244 +
 164.245 +    /**
 164.246 +     * Return true iff the name is a class name
 164.247 +     * @param name The name
 164.248 +     * @param emptyDefault Whether empty or _ names should be considered a class name or not
 164.249 +     * @return True iff the name looks like a class name
 164.250 +     */
 164.251 +    public static boolean isClassName(String name, boolean emptyDefault) {
 164.252 +        if (name == null || name.length() == 0) {
 164.253 +            return emptyDefault;
 164.254 +        }
 164.255 +        if (name.startsWith("_") && name.length() > 1) {
 164.256 +            return Character.isUpperCase(name.charAt(1));
 164.257 +        }
 164.258 +
 164.259 +        return Character.isUpperCase(name.charAt(0));
 164.260 +    }
 164.261 +
 164.262 +    /**
 164.263 +     * Return true iff the name is a method name
 164.264 +     * @param name The name
 164.265 +     * @param emptyDefault Whether empty or _ names should be considered a class name or not
 164.266 +     * @return True iff the name looks like a method name
 164.267 +     */
 164.268 +    public static boolean isMethodName(String name, boolean emptyDefault) {
 164.269 +        if (name == null || name.length() == 0) {
 164.270 +            return emptyDefault;
 164.271 +        }
 164.272 +        if (name.startsWith("__") && name.length() > 2) {
 164.273 +            return Character.isLowerCase(name.charAt(2));
 164.274 +        }
 164.275 +        if (name.startsWith("_") && name.length() > 1) {
 164.276 +            return Character.isLowerCase(name.charAt(1));
 164.277 +        }
 164.278 +
 164.279 +        return Character.isLowerCase(name.charAt(0));
 164.280 +    }
 164.281 +
 164.282 +    public static boolean isValidPythonClassName(String name) {
 164.283 +        if (isPythonKeyword(name)) {
 164.284 +            return false;
 164.285 +        }
 164.286 +
 164.287 +        if (name.trim().length() == 0) {
 164.288 +            return false;
 164.289 +        }
 164.290 +
 164.291 +        if (!Character.isUpperCase(name.charAt(0))) {
 164.292 +            return false;
 164.293 +        }
 164.294 +
 164.295 +        for (int i = 1; i < name.length(); i++) {
 164.296 +            char c = name.charAt(i);
 164.297 +            if (!Character.isJavaIdentifierPart(c)) {
 164.298 +                return false;
 164.299 +            }
 164.300 +
 164.301 +        }
 164.302 +
 164.303 +        return true;
 164.304 +    }
 164.305 +
 164.306 +    /** Is this name a valid operator name? */
 164.307 +    public static boolean isOperator(String name) {
 164.308 +        // TODO - update to Python
 164.309 +        if (name.length() == 0) {
 164.310 +            return false;
 164.311 +        }
 164.312 +
 164.313 +        switch (name.charAt(0)) {
 164.314 +        case '+':
 164.315 +            return name.equals("+") || name.equals("+@");
 164.316 +        case '-':
 164.317 +            return name.equals("-") || name.equals("-@");
 164.318 +        case '*':
 164.319 +            return name.equals("*") || name.equals("**");
 164.320 +        case '<':
 164.321 +            return name.equals("<") || name.equals("<<") || name.equals("<=") || name.equals("<=>");
 164.322 +        case '>':
 164.323 +            return name.equals(">") || name.equals(">>") || name.equals(">=");
 164.324 +        case '=':
 164.325 +            return name.equals("=") || name.equals("==") || name.equals("===") || name.equals("=~");
 164.326 +        case '!':
 164.327 +            return name.equals("!=") || name.equals("!~");
 164.328 +        case '&':
 164.329 +            return name.equals("&") || name.equals("&&");
 164.330 +        case '|':
 164.331 +            return name.equals("|") || name.equals("||");
 164.332 +        case '[':
 164.333 +            return name.equals("[]") || name.equals("[]=");
 164.334 +        case '%':
 164.335 +            return name.equals("%");
 164.336 +        case '/':
 164.337 +            return name.equals("/");
 164.338 +        case '~':
 164.339 +            return name.equals("~");
 164.340 +        case '^':
 164.341 +            return name.equals("^");
 164.342 +        case '`':
 164.343 +            return name.equals("`");
 164.344 +        default:
 164.345 +            return false;
 164.346 +        }
 164.347 +    }
 164.348 +
 164.349 +    public static boolean isValidPythonMethodName(String name) {
 164.350 +        if (isPythonKeyword(name)) {
 164.351 +            return false;
 164.352 +        }
 164.353 +
 164.354 +        if (name.trim().length() == 0) {
 164.355 +            return false;
 164.356 +        }
 164.357 +
 164.358 +        // TODO - allow operators
 164.359 +        if (isOperator(name)) {
 164.360 +            return true;
 164.361 +        }
 164.362 +
 164.363 +        if (Character.isUpperCase(name.charAt(0)) || Character.isWhitespace(name.charAt(0))) {
 164.364 +            return false;
 164.365 +        }
 164.366 +
 164.367 +        for (int i = 0; i < name.length(); i++) {
 164.368 +            char c = name.charAt(i);
 164.369 +            if (!(Character.isLetterOrDigit(c) || c == '_')) {
 164.370 +                return false;
 164.371 +            }
 164.372 +
 164.373 +        }
 164.374 +
 164.375 +        return true;
 164.376 +    }
 164.377 +
 164.378 +    public static boolean isValidPythonIdentifier(String name) {
 164.379 +        if (isPythonKeyword(name)) {
 164.380 +            return false;
 164.381 +        }
 164.382 +
 164.383 +        if (name.trim().length() == 0) {
 164.384 +            return false;
 164.385 +        }
 164.386 +
 164.387 +        for (int i = 0; i < name.length(); i++) {
 164.388 +            // Identifier char isn't really accurate - I can have a function named "[]" etc.
 164.389 +            // so just look for -obvious- mistakes
 164.390 +            if (Character.isWhitespace(name.charAt(i))) {
 164.391 +                return false;
 164.392 +            }
 164.393 +
 164.394 +        // TODO - make this more accurate, like the method validifier
 164.395 +        }
 164.396 +
 164.397 +        return true;
 164.398 +    }
 164.399 +
 164.400 +    /**
 164.401 +     * Ruby identifiers should consist of [a-zA-Z0-9_]
 164.402 +     * http://www.headius.com/rubyspec/index.php/Variables
 164.403 +     * <p>
 164.404 +     * This method also accepts the field/global chars
 164.405 +     * since it's unlikely
 164.406 +     */
 164.407 +    public static boolean isSafeIdentifierName(String name, int fromIndex) {
 164.408 +        int i = fromIndex;
 164.409 +        for (; i < name.length(); i++) {
 164.410 +            char c = name.charAt(i);
 164.411 +            if (!(c == '$' || c == '@' || c == ':')) {
 164.412 +                break;
 164.413 +            }
 164.414 +        }
 164.415 +        for (; i < name.length(); i++) {
 164.416 +            char c = name.charAt(i);
 164.417 +            if (!((c >= 'a' && c <= 'z') || (c == '_') ||
 164.418 +                    (c >= 'A' && c <= 'Z') ||
 164.419 +                    (c >= '0' && c <= '9') ||
 164.420 +                    (c == '?') || (c == '=') || (c == '!'))) { // Method suffixes; only allowed on the last line
 164.421 +
 164.422 +                if (isOperator(name)) {
 164.423 +                    return true;
 164.424 +                }
 164.425 +
 164.426 +                return false;
 164.427 +            }
 164.428 +        }
 164.429 +
 164.430 +        return true;
 164.431 +    }
 164.432 +
 164.433 +    /**
 164.434 +     * Return null if the given identifier name is valid, otherwise a localized
 164.435 +     * error message explaining the problem.
 164.436 +     */
 164.437 +    public static String getIdentifierWarning(String name, int fromIndex) {
 164.438 +        if (isSafeIdentifierName(name, fromIndex)) {
 164.439 +            return null;
 164.440 +        } else {
 164.441 +            return NbBundle.getMessage(PythonUtils.class, "UnsafeIdentifierName");
 164.442 +        }
 164.443 +    }
 164.444 +
 164.445 +    /** @todo Move into GsfUtilities after 6.5 */
 164.446 +    public static int getOffsetByLineCol(String source, int line, int col) {
 164.447 +        int offset = 0;
 164.448 +        for (int i = 0; i < line; i++) {
 164.449 +            offset = source.indexOf('\n', offset);
 164.450 +            if (offset == -1) {
 164.451 +                offset = source.length();
 164.452 +                break;
 164.453 +            }
 164.454 +            offset++;
 164.455 +        }
 164.456 +        if (col > 0) { // -1: invalid
 164.457 +            offset += col;
 164.458 +        }
 164.459 +
 164.460 +        return offset;
 164.461 +    }
 164.462 +    public static Comparator NAME_NODE_COMPARATOR = new Comparator<Name>() {
 164.463 +        @Override
 164.464 +        public int compare(Name n1, Name n2) {
 164.465 +            return n1.getInternalId().compareTo(n2.getInternalId());
 164.466 +        }
 164.467 +    };
 164.468 +    public static Comparator ATTRIBUTE_NAME_NODE_COMPARATOR = new Comparator<Object>() {
 164.469 +        @SuppressWarnings("unchecked")
 164.470 +        @Override
 164.471 +        public int compare(Object n1, Object n2) {
 164.472 +            String s1 = "";
 164.473 +            String s2 = "";
 164.474 +
 164.475 +            if (n1 instanceof Name) {
 164.476 +                s1 = ((Name)n1).getInternalId();
 164.477 +            } else if (n1 instanceof Attribute) {
 164.478 +                Attribute a = (Attribute)n1;
 164.479 +                String v = PythonAstUtils.getName(a.getInternalValue());
 164.480 +                if (v != null) {
 164.481 +                    s1 = a.getInternalAttr() + "." + v;
 164.482 +                } else {
 164.483 +                    s1 = a.getInternalAttr();
 164.484 +                }
 164.485 +            }
 164.486 +
 164.487 +            if (n2 instanceof Name) {
 164.488 +                s2 = ((Name)n2).getInternalId();
 164.489 +            } else if (n2 instanceof Attribute) {
 164.490 +                Attribute a = (Attribute)n2;
 164.491 +                String v = PythonAstUtils.getName(a.getInternalValue());
 164.492 +                if (v != null) {
 164.493 +                    s2 = a.getInternalAttr() + "." + v;
 164.494 +                } else {
 164.495 +                    s2 = a.getInternalAttr();
 164.496 +                }
 164.497 +            }
 164.498 +
 164.499 +            return s1.compareTo(s2);
 164.500 +        }
 164.501 +    };
 164.502 +    public static Comparator NODE_POS_COMPARATOR = new Comparator<PythonTree>() {
 164.503 +        @Override
 164.504 +        public int compare(PythonTree p1, PythonTree p2) {
 164.505 +            int ret = p1.getCharStartIndex() - p2.getCharStartIndex();
 164.506 +            if (ret != 0) {
 164.507 +                return ret;
 164.508 +            }
 164.509 +            ret = p2.getCharStopIndex() - p1.getCharStopIndex();
 164.510 +            if (ret != 0) {
 164.511 +                return ret;
 164.512 +            }
 164.513 +            return p2.getAntlrType() - p1.getAntlrType();
 164.514 +        }
 164.515 +    };
 164.516 +}
   165.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   165.2 +++ b/python.source/src/org/netbeans/modules/python/source/RstFormatter.java	Mon Sep 21 13:01:16 2015 +0200
   165.3 @@ -0,0 +1,1342 @@
   165.4 +/*
   165.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   165.6 + *
   165.7 + * Copyright 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 + * If you wish your version of this file to be governed by only the CDDL
  165.31 + * or only the GPL Version 2, indicate your decision by adding
  165.32 + * "[Contributor] elects to include this software in this distribution
  165.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  165.34 + * single choice of license, a recipient has the option to distribute
  165.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  165.36 + * to extend the choice of license to its licensees as provided above.
  165.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  165.38 + * Version 2 license, then the option applies only if the new code is
  165.39 + * made subject to such option by the copyright holder.
  165.40 + *
  165.41 + * Contributor(s):
  165.42 + *
  165.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  165.44 + */
  165.45 +package org.netbeans.modules.python.source;
  165.46 +
  165.47 +import java.awt.Color;
  165.48 +import java.io.CharConversionException;
  165.49 +import java.util.ArrayList;
  165.50 +import java.util.Collections;
  165.51 +import java.util.List;
  165.52 +import javax.swing.text.AttributeSet;
  165.53 +import javax.swing.text.BadLocationException;
  165.54 +import javax.swing.text.StyleConstants;
  165.55 +import org.netbeans.api.editor.mimelookup.MimeLookup;
  165.56 +import org.netbeans.api.editor.mimelookup.MimePath;
  165.57 +import org.netbeans.api.editor.settings.FontColorSettings;
  165.58 +import org.netbeans.api.lexer.Language;
  165.59 +import org.netbeans.api.lexer.Token;
  165.60 +import org.netbeans.api.lexer.TokenHierarchy;
  165.61 +import org.netbeans.api.lexer.TokenSequence;
  165.62 +import org.netbeans.editor.BaseDocument;
  165.63 +import org.netbeans.modules.csl.api.ElementHandle;
  165.64 +import org.netbeans.modules.csl.api.ElementKind;
  165.65 +import org.netbeans.modules.csl.spi.GsfUtilities;
  165.66 +import org.netbeans.modules.csl.spi.ParserResult;
  165.67 +import org.netbeans.modules.python.api.PythonMIMEResolver;
  165.68 +import org.netbeans.modules.python.source.elements.Element;
  165.69 +import org.netbeans.modules.python.source.elements.IndexedElement;
  165.70 +import org.netbeans.modules.python.source.elements.IndexedMethod;
  165.71 +import org.netbeans.modules.python.source.lexer.PythonTokenId;
  165.72 +import org.openide.filesystems.FileObject;
  165.73 +import org.openide.util.Exceptions;
  165.74 +import org.openide.util.Lookup;
  165.75 +import org.openide.xml.XMLUtil;
  165.76 +import org.python.antlr.PythonTree;
  165.77 +
  165.78 +/**
  165.79 + * Support for reStructured text. Parse .rst files and rst content in
  165.80 + * Python doc strings and format it as HTML. Also provide functions
  165.81 + * to locate a code element in RST files.
  165.82 + * @see http://www.python.org/dev/peps/pep-0287/
  165.83 + * @see http://docutils.sourceforge.net/docs/user/rst/quickstart.html
  165.84 + *
  165.85 + * @todo Render verbatim blocks
  165.86 + * @todo Syntax highlight verbatim blocks?
  165.87 + * @todo Render *bold* and `identifier` stuff
  165.88 + * @todo For class definitions which nest the method documentation,
  165.89 + *    try to remove all items, or perhaps just make it shorter
  165.90 + * @todo Render note:: into something cleaner etc.
  165.91 + *
  165.92 + * @author Tor Norbye
  165.93 + */
  165.94 +public class RstFormatter {
  165.95 +    private static final String BRBR = "\n<br><br>\n"; // NOI18N
  165.96 +    private StringBuilder sb = new StringBuilder();
  165.97 +    private boolean lastWasEmpty = false;
  165.98 +    private int beginPos;
  165.99 +    private boolean inVerbatim;
 165.100 +    private boolean inIndex;
 165.101 +    private boolean inTable;
 165.102 +    private boolean inDiv;
 165.103 +    private int lastIndent;
 165.104 +    private boolean maybeVerbatim;
 165.105 +    private boolean inDocTest;
 165.106 +    private List<String> code;
 165.107 +
 165.108 +    public RstFormatter() {
 165.109 +    }
 165.110 +
 165.111 +    private void flush() {
 165.112 +        if (inTable) {
 165.113 +            sb.append("</pre>\n"); // NOI18N
 165.114 +            inTable = false;
 165.115 +            inVerbatim = false;
 165.116 +        } else if (inVerbatim) {
 165.117 +            // Process code and format as Python
 165.118 +            String html = getPythonHtml(code, true);
 165.119 +            if (html != null) {
 165.120 +                // <pre> tag is added as part of the rubyhtml (since it
 165.121 +                // needs to pick up the background color from the syntax
 165.122 +                // coloring settings)
 165.123 +                sb.append(html);
 165.124 +            } else {
 165.125 +                sb.append("<pre style=\"margin: 5px 5px; background: #ffffdd; border-size: 1px; padding: 5px\">"); // NOI18N
 165.126 +                sb.append("\n"); // NOI18N
 165.127 +                // Some kind of error; normal append
 165.128 +                for (String s : code) {
 165.129 +                    appendEscaped(s);
 165.130 +                    sb.append("<br>"); // NOI18N
 165.131 +                }
 165.132 +                sb.append("</pre>\n"); // NOI18N
 165.133 +            }
 165.134 +            inVerbatim = false;
 165.135 +            code = null;
 165.136 +        } else if (inDiv) {
 165.137 +            sb.append("</div>\n"); // NOI18N
 165.138 +            inDiv = false;
 165.139 +        }
 165.140 +    }
 165.141 +
 165.142 +    private void appendEscaped(char c) {
 165.143 +        if ('<' == c) {
 165.144 +            sb.append("&lt;"); // NOI18N
 165.145 +        } else if ('&' == c) {
 165.146 +            sb.append("&amp;"); // NOI18N
 165.147 +        } else {
 165.148 +            sb.append(c);
 165.149 +        }
 165.150 +    }
 165.151 +
 165.152 +    private void appendEscaped(CharSequence s) {
 165.153 +        for (int i = 0, n = s.length(); i < n; i++) {
 165.154 +            char c = s.charAt(i);
 165.155 +            if ('<' == c) {
 165.156 +                sb.append("&lt;"); // NOI18N
 165.157 +            } else if ('&' == c) {
 165.158 +                sb.append("&amp;"); // NOI18N
 165.159 +            } else {
 165.160 +                sb.append(c);
 165.161 +            }
 165.162 +        }
 165.163 +    }
 165.164 +
 165.165 +    private int appendColonCmd(String line, int i, String marker, boolean url) throws CharConversionException {
 165.166 +        String MARKER = ":" + marker + ":`"; // NOI18N
 165.167 +        if (line.startsWith(MARKER, i)) {
 165.168 +            int end = line.indexOf("`", i + MARKER.length()); // NOI18N
 165.169 +            if (end != -1) {
 165.170 +                String token = line.substring(i + MARKER.length(), end);
 165.171 +                if (url) {
 165.172 +                    sb.append("<a href=\""); // NOI18N
 165.173 +                    if ("pep".equals(marker)) { // NOI18N
 165.174 +                        sb.append("http://www.python.org/dev/peps/pep-"); // NOI18N
 165.175 +                        for (int j = 0; j < 4 - token.length(); j++) {
 165.176 +                            sb.append("0");
 165.177 +                        }
 165.178 +                        sb.append(token);
 165.179 +                        sb.append("/"); // NOI18N
 165.180 +                        sb.append("\">PEP "); // NOI18N
 165.181 +                        sb.append(token);
 165.182 +                        sb.append("</a>");
 165.183 +                        return end;
 165.184 +                    } else {
 165.185 +                        sb.append(marker);
 165.186 +                        sb.append(":"); // NOI18N
 165.187 +                        appendEscaped(token);
 165.188 +                    }
 165.189 +                    sb.append("\">"); // NOI18N
 165.190 +                } else if (marker.equals("keyword")) { // NOI18N
 165.191 +                    sb.append("<code style=\""); // NOI18N
 165.192 +
 165.193 +                    MimePath mimePath = MimePath.parse(PythonMIMEResolver.PYTHON_MIME_TYPE);
 165.194 +                    Lookup lookup = MimeLookup.getLookup(mimePath);
 165.195 +                    FontColorSettings fcs = lookup.lookup(FontColorSettings.class);
 165.196 +
 165.197 +                    AttributeSet attribs = fcs.getTokenFontColors("keyword"); // NOI18N
 165.198 +                    Color fg = (Color)attribs.getAttribute(StyleConstants.Foreground);
 165.199 +                    if (fg != null) {
 165.200 +                        sb.append("color:"); // NOI18N
 165.201 +                        sb.append(getHtmlColor(fg));
 165.202 +                        sb.append(";"); // NOI18N
 165.203 +                    }
 165.204 +                    Color bg = (Color)attribs.getAttribute(StyleConstants.Background);
 165.205 +                    // Only set the background for dark colors
 165.206 +                    if (bg != null && bg.getRed() < 128) {
 165.207 +                        sb.append("background:"); // NOI18N
 165.208 +                        sb.append(getHtmlColor(bg));
 165.209 +                    }
 165.210 +
 165.211 +                    sb.append("\">"); // NOI18N
 165.212 +                } else {
 165.213 +                    sb.append("<code>"); // NOI18N
 165.214 +                }
 165.215 +                appendEscaped(token);
 165.216 +                if (url) {
 165.217 +                    sb.append("</a>"); // NOI18N
 165.218 +                } else {
 165.219 +                    sb.append("</code>"); // NOI18N
 165.220 +                }
 165.221 +                //return end+1; // instead of end+2: get to end of ``, minus loop increment
 165.222 +                return end; // instead of end+2: get to end of ``, minus loop increment
 165.223 +            }
 165.224 +        }
 165.225 +
 165.226 +        return -1;
 165.227 +    }
 165.228 +
 165.229 +    private void appendRstLine(String line) throws CharConversionException {
 165.230 +        int n = line.length();
 165.231 +        char prev = 0;
 165.232 +        Loop:
 165.233 +        for (int i = 0; i < n; i++) {
 165.234 +            char c = line.charAt(i);
 165.235 +            if (c == '`') {
 165.236 +                if (i < n - 2 && line.charAt(i + 1) == '`') {
 165.237 +                    // See if it's an ``identifier``
 165.238 +                    int end = line.indexOf("``", i + 2);
 165.239 +                    if (end != -1) {
 165.240 +                        sb.append("<code>"); // NOI18N
 165.241 +                        appendEscaped(line.substring(i + 2, end));
 165.242 +                        sb.append("</code>"); // NOI18N
 165.243 +                        i = end + 1; // instead of end+2: get to end of ``, minus loop increment
 165.244 +                        continue;
 165.245 +                    }
 165.246 +                } else {
 165.247 +                    // Single identifier
 165.248 +                    for (int j = i + 1; j < n; j++) {
 165.249 +                        char d = line.charAt(j);
 165.250 +                        if (d == '`') {
 165.251 +                            sb.append("<code>"); // NOI18N
 165.252 +                            appendEscaped(line.substring(i + 1, j));
 165.253 +                            sb.append("</code>"); // NOI18N
 165.254 +                            i = j;
 165.255 +                            continue Loop;
 165.256 +                        } else if (!Character.isJavaIdentifierPart(d)) {
 165.257 +                            break;
 165.258 +                        }
 165.259 +                    }
 165.260 +                }
 165.261 +            } else if (c == ':') {
 165.262 +                int nextI = appendColonCmd(line, i, "class", true); // NOI18N
 165.263 +                if (nextI == -1) {
 165.264 +                    nextI = appendColonCmd(line, i, "exc", true); // NOI18N
 165.265 +                    if (nextI == -1) {
 165.266 +                        nextI = appendColonCmd(line, i, "var", false); // NOI18N
 165.267 +                        if (nextI == -1) {
 165.268 +                            nextI = appendColonCmd(line, i, "meth", true); // NOI18N
 165.269 +                            if (nextI == -1) {
 165.270 +                                nextI = appendColonCmd(line, i, "func", true); // NOI18N
 165.271 +                                if (nextI == -1) {
 165.272 +                                    nextI = appendColonCmd(line, i, "data", false); // NOI18N
 165.273 +                                    if (nextI == -1) {
 165.274 +                                        nextI = appendColonCmd(line, i, "attr", false); // NOI18N
 165.275 +                                        if (nextI == -1) {
 165.276 +                                            nextI = appendColonCmd(line, i, "envvar", false); // NOI18N
 165.277 +                                            if (nextI == -1) {
 165.278 +                                                nextI = appendColonCmd(line, i, "mod", true); // NOI18N
 165.279 +                                                if (nextI == -1) {
 165.280 +                                                    nextI = appendColonCmd(line, i, "pep", true); // NOI18N
 165.281 +                                                    if (nextI == -1) {
 165.282 +                                                        nextI = appendColonCmd(line, i, "ref", false); // NOI18N
 165.283 +                                                        if (nextI == -1) {
 165.284 +                                                            nextI = appendColonCmd(line, i, "mod", true); // NOI18N
 165.285 +                                                            if (nextI == -1) {
 165.286 +                                                                nextI = appendColonCmd(line, i, "keyword", false); // NOI18N
 165.287 +                                                                if (nextI == -1) {
 165.288 +                                                                    if (line.startsWith(":noindex:", i)) { // NOI18N
 165.289 +                                                                        nextI = i + 9;
 165.290 +                                                                    } else if (line.startsWith(":synopsis:", i)) { // NOI18N
 165.291 +                                                                        nextI = i + 10;
 165.292 +                                                                    } else if (line.startsWith(":deprecated:", i)) {
 165.293 +                                                                        sb.append("Deprecated. ");
 165.294 +                                                                        nextI = i + 12;
 165.295 +                                                                    } else if (line.startsWith(":platform:", i)) {
 165.296 +                                                                        sb.append("Platform: ");
 165.297 +                                                                        nextI = i + 10;
 165.298 +                                                                    }
 165.299 +                                                                }
 165.300 +                                                            }
 165.301 +                                                        }
 165.302 +                                                    }
 165.303 +                                                }
 165.304 +                                            }
 165.305 +                                        }
 165.306 +                                    }
 165.307 +                                }
 165.308 +                            }
 165.309 +                        }
 165.310 +                    }
 165.311 +                }
 165.312 +                if (nextI != -1) {
 165.313 +                    i = nextI;
 165.314 +                    continue;
 165.315 +                }
 165.316 +            } else if (c == '*') {
 165.317 +                // Bold?
 165.318 +                if (i < n - 1 && Character.isJavaIdentifierPart(line.charAt(i + 1)) && !Character.isJavaIdentifierPart(prev)) { // TODO Use PythonUtils
 165.319 +                    // Peek ahead to see if we have [not-identifier-char]*[identifierchars]*[not-identifier-chars]
 165.320 +                    for (int j = i + 1; j < n; j++) {
 165.321 +                        char d = line.charAt(j);
 165.322 +                        if (d == '*') {
 165.323 +                            if (j == n - 1 || !Character.isJavaIdentifierPart(line.charAt(j + 1))) {
 165.324 +                                // Yess, make bold
 165.325 +                                sb.append("<b>"); // NOI18N
 165.326 +                                appendEscaped(line.substring(i + 1, j));
 165.327 +                                sb.append("</b>"); // NOI18N
 165.328 +                                i = j;
 165.329 +                                continue Loop;
 165.330 +                            }
 165.331 +                        } else if (!Character.isJavaIdentifierPart(d)) {
 165.332 +                            break;
 165.333 +                        }
 165.334 +                    }
 165.335 +                }
 165.336 +            } // TODO: :addedin, :deprecated, etc
 165.337 +
 165.338 +            appendEscaped(c);
 165.339 +            prev = c;
 165.340 +        }
 165.341 +    }
 165.342 +
 165.343 +    public void append(String line) {
 165.344 +        try {
 165.345 +            String trim = line.trim();
 165.346 +            if (trim.length() == 0) {
 165.347 +                inDocTest = false;
 165.348 +                if (inIndex) {
 165.349 +                    // Completely swallow all indexing entries
 165.350 +                    return;
 165.351 +                } else if (inTable) {
 165.352 +                    sb.append("</pre>\n"); // NOI18N
 165.353 +                    inVerbatim = false;
 165.354 +                    inTable = false;
 165.355 +                } else if (inVerbatim) {
 165.356 +                    sb.append("\n"); // NOI18N
 165.357 +                } else if (!lastWasEmpty && sb.length() > beginPos) {
 165.358 +                    sb.append(BRBR); // NOI18N
 165.359 +                }
 165.360 +                lastWasEmpty = true;
 165.361 +            } else {
 165.362 +                if (!lastWasEmpty && trim.startsWith("- ")) { // NOI18N
 165.363 +                    // lists - make sure they're on a new line
 165.364 +                    sb.append("<br>"); // NOI18N
 165.365 +                }
 165.366 +
 165.367 +                lastWasEmpty = false;
 165.368 +
 165.369 +                if (maybeVerbatim) {
 165.370 +                    int indent = getIndentation(line, 0);
 165.371 +                    if (indent > lastIndent) {
 165.372 +                        // Truncate last whitespace separator before <pre> if any
 165.373 +                        if (sb.length() > BRBR.length() && sb.substring(sb.length() - BRBR.length()).equals(BRBR)) {
 165.374 +                            sb.setLength(sb.length() - BRBR.length());
 165.375 +                        }
 165.376 +                        inVerbatim = true;
 165.377 +                        code = new ArrayList<>();
 165.378 +                        code.add(line);
 165.379 +                        maybeVerbatim = false;
 165.380 +                        return;
 165.381 +                    }
 165.382 +                    maybeVerbatim = false;
 165.383 +                } else if (inVerbatim || inTable) {
 165.384 +                    int indent = getIndentation(line, 0);
 165.385 +                    if (indent <= lastIndent) {
 165.386 +////                        // Truncate trailing whitespace
 165.387 +////                        while (sb.length() > 0 && sb.charAt(sb.length()-1) == '\n') {
 165.388 +////                            sb.setLength(sb.length()-1);
 165.389 +////                        }
 165.390 +////                        sb.append("</pre>"); // NOI18N
 165.391 +//                        inVerbatim = false;
 165.392 +//                        inTable = false;
 165.393 +                        flush();
 165.394 +                        lastWasEmpty = true;
 165.395 +                    } else if (inVerbatim) {
 165.396 +                        // We need to buffer up the text such that we can lex it as a unit
 165.397 +                        // (and determine when done with the section if it's code or regular text)
 165.398 +                        code.add(line);
 165.399 +                        return;
 165.400 +                    } else {
 165.401 +                        appendEscaped(line);
 165.402 +                        sb.append("\n"); // NOI18N
 165.403 +                        return;
 165.404 +                    }
 165.405 +                } else if (inDiv) {
 165.406 +                    int indent = getIndentation(line, 0);
 165.407 +                    if (indent <= lastIndent) {
 165.408 +                        // Truncate last whitespace separator before <pre> if any
 165.409 +                        if (sb.length() > BRBR.length() && sb.substring(sb.length() - BRBR.length()).equals(BRBR)) {
 165.410 +                            sb.setLength(sb.length() - BRBR.length());
 165.411 +                        }
 165.412 +                        sb.append("</div>\n"); // NOI18N
 165.413 +                        inDiv = false;
 165.414 +                        lastWasEmpty = true;
 165.415 +                    } else {
 165.416 +                        appendRstLine(line);
 165.417 +                        sb.append("\n"); // NOI18N
 165.418 +                        return;
 165.419 +                    }
 165.420 +                } else if (inIndex) {
 165.421 +                    int indent = getIndentation(line, 0);
 165.422 +                    if (indent <= lastIndent) {
 165.423 +                        inIndex = false;
 165.424 +                        lastWasEmpty = true;
 165.425 +                    } else {
 165.426 +                        return;
 165.427 +                    }
 165.428 +
 165.429 +                }
 165.430 +
 165.431 +                if (trim.startsWith(".. method:: ")) { // NOI18N
 165.432 +                    String sig = trim.substring(12).trim();
 165.433 +                    sb.append("<a href=\"meth:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
 165.434 +                    return;
 165.435 +                } else if (trim.startsWith(".. function:: ")) { // NOI18N
 165.436 +                    String sig = trim.substring(14).trim();
 165.437 +                    sb.append("<a href=\"func:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
 165.438 +                    return;
 165.439 +                } else if (trim.startsWith(".. class:: ")) { // NOI18N
 165.440 +                    String sig = trim.substring(11).trim();
 165.441 +                    sb.append("<a href=\"class:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
 165.442 +                    return;
 165.443 +                } else if (trim.startsWith(".. attribute:: ")) { // NOI18N
 165.444 +                    String sig = trim.substring(15).trim();
 165.445 +                    sb.append("<a href=\"attr:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
 165.446 +                    return;
 165.447 +                } else if (trim.startsWith(".. data:: ")) { // NOI18N
 165.448 +                    String sig = trim.substring(10).trim();
 165.449 +                    sb.append("<a href=\"data:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>\n"); // NOI18N
 165.450 +                    return;
 165.451 +                } else if (trim.startsWith(".. module:: ")) { // NOI18N
 165.452 +                    String sig = trim.substring(12).trim();
 165.453 +                    sb.append("<a href=\"module:" + sig.replace("\"", "&quot;") + "\">" + sig + "</a>"); // NOI18N
 165.454 +                    sb.append("<br>\n");
 165.455 +                    return;
 165.456 +                } else if (trim.startsWith(".. productionlist:")) {
 165.457 +                    lastIndent = getIndentation(line, 0);
 165.458 +                    inVerbatim = true;
 165.459 +                    code = new ArrayList<>();
 165.460 +                    code.add(line);
 165.461 +                    maybeVerbatim = false;
 165.462 +                    return;
 165.463 +                }
 165.464 +
 165.465 +                if (trim.startsWith(">>>") || inDocTest) { // NOI18N
 165.466 +                    if (!trim.startsWith(">>>")) { // NOI18N
 165.467 +                        sb.append("<code>"); // NOI18N
 165.468 +                        appendEscaped(line); // NOI18N
 165.469 +                        // Wait until there is an empty line before we mark doctest done!
 165.470 +                        // inDocTest = false;
 165.471 +                        sb.append("</code><br>"); // NOI18N
 165.472 +                    } else {
 165.473 +                        sb.append("<code>"); // NOI18N
 165.474 +                        appendEscaped(">>>"); // NOI18N
 165.475 +                        String html = getPythonHtml(Collections.singletonList(trim.substring(3)), false);
 165.476 +                        sb.append(html);
 165.477 +                        sb.append("</code>"); // NOI18N
 165.478 +                        inDocTest = true;
 165.479 +                    }
 165.480 +                    return;
 165.481 +                }
 165.482 +                inDocTest = false;
 165.483 +
 165.484 +                if (trim.startsWith(".. note::") || trim.startsWith(".. warning::") || trim.startsWith(".. seealso:")) { // NOI18N
 165.485 +                    // Truncate last whitespace separator before <pre> if any
 165.486 +                    if (sb.length() > BRBR.length() && sb.substring(sb.length() - BRBR.length()).equals(BRBR)) {
 165.487 +                        sb.setLength(sb.length() - BRBR.length());
 165.488 +                    }
 165.489 +                    sb.append("<div style=\"margin: 5px 5px; "); // NOI18N
 165.490 +                    if (!trim.contains("seealso")) { // NOI18N
 165.491 +                        sb.append("background: #ffdddd; "); // NOI18N
 165.492 +                    } else {
 165.493 +                        sb.append("background: #ddffdd; "); // NOI18N
 165.494 +                    }
 165.495 +                    sb.append("border-size: 1px; padding: 5px\">"); // NOI18N
 165.496 +                    if (trim.contains("note:")) {
 165.497 +                        sb.append("<b>NOTE</b>: "); // NOI18N
 165.498 +                    } else if (trim.contains("warning")) {
 165.499 +                        sb.append("<b>WARNING</b>: "); // NOI18N
 165.500 +                    } else {
 165.501 +                        sb.append("<b>See Also</b>: "); // NOI18N
 165.502 +                    }
 165.503 +                    sb.append("\n"); // NOI18N
 165.504 +                    inDiv = true;
 165.505 +                    lastIndent = getIndentation(line, 0);
 165.506 +                    maybeVerbatim = false;
 165.507 +                    return;
 165.508 +                } else if (trim.startsWith(".. versionadded::") || trim.startsWith(".. versionchanged::") || trim.startsWith(".. deprecated::")) { // NOI18N
 165.509 +                    // Truncate last whitespace separator before <pre> if any
 165.510 +                    if (sb.length() > BRBR.length() && sb.substring(sb.length() - BRBR.length()).equals(BRBR)) {
 165.511 +                        sb.setLength(sb.length() - BRBR.length());
 165.512 +                    }
 165.513 +                    sb.append("<div style=\"margin: 5px 5px; background: #dddddd; border-size: 1px; padding: 5px\">"); // NOI18N
 165.514 +                    if (trim.contains("added:")) {
 165.515 +                        sb.append("<b>Version Added</b>: "); // NOI18N
 165.516 +                    } else if (trim.contains("changed")) {
 165.517 +                        sb.append("<b>Version Changed</b>: "); // NOI18N
 165.518 +                    } else {
 165.519 +                        assert trim.contains("deprecated"); // NOI18N
 165.520 +                        sb.append("<b>Deprecated</b>: "); // NOI18N
 165.521 +                    }
 165.522 +                    sb.append(trim.substring(trim.indexOf("::") + 2));
 165.523 +                    sb.append("\n"); // NOI18N
 165.524 +                    inDiv = true;
 165.525 +                    lastIndent = getIndentation(line, 0);
 165.526 +                    maybeVerbatim = false;
 165.527 +                    return;
 165.528 +                } else if (trim.startsWith(".. index:")) { // NOI18N
 165.529 +                    inIndex = true;
 165.530 +                    lastIndent = getIndentation(line, 0);
 165.531 +                    return;
 165.532 +                } else if (trim.startsWith(".. _") && trim.endsWith(":")) {
 165.533 +                    // skip lines like .. _pyzipfile-objects: 
 165.534 +                    return;
 165.535 +                } else if (trim.startsWith(".. moduleauthor::") || trim.startsWith(".. sectionauthor::")) { // NOI18N
 165.536 +                    if (trim.startsWith(".. mod")) {
 165.537 +                        sb.append("<br>Module Author:</b>");
 165.538 +                    } else {
 165.539 +                        sb.append("<br>Section Author:</b>");
 165.540 +                    }
 165.541 +                    appendEscaped(trim.substring(trim.indexOf("::") + 2)); //
 165.542 +                    sb.append("\n");
 165.543 +                    return;
 165.544 +                } else if (trim.endsWith("::")) { // NOI18N
 165.545 +                    maybeVerbatim = true;
 165.546 +                    lastIndent = getIndentation(line, 0);
 165.547 +                } else if (trim.startsWith("+-----")) { // NOI18N
 165.548 +                    // A table
 165.549 +                    sb.append("<pre>"); // NOI18N
 165.550 +                    appendEscaped(line);
 165.551 +                    sb.append("\n"); // NOI18N
 165.552 +                    inTable = true;
 165.553 +                    lastIndent = getIndentation(line, 0) - 1;
 165.554 +                    return;
 165.555 +                } else if (line.startsWith("======") || line.startsWith("------") || line.startsWith("******") || line.startsWith("^^^^^^^^")) { // NOI18N
 165.556 +                    // PREVIOUS line could be a title.
 165.557 +                    // Note -- we're comparing on "line" and not "trim" here because in indented contexts,
 165.558 +                    //  === sometimes represents parts of tables -- see the turtle.rst file for examples.
 165.559 +
 165.560 +                    int n = sb.length();
 165.561 +                    if (n > 0 && sb.charAt(n - 1) == '\n') {
 165.562 +                        n--;
 165.563 +                    }
 165.564 +                    int index = n - 1;
 165.565 +                    for (; index >= 0; index--) {
 165.566 +                        char c = sb.charAt(index);
 165.567 +                        if (c == '\n') {
 165.568 +                            index++;
 165.569 +                            break;
 165.570 +                        }
 165.571 +                    }
 165.572 +                    if (index == -1) {
 165.573 +                        index = 0;
 165.574 +                    }
 165.575 +                    // Index now points to the beginning of the previous line
 165.576 +                    boolean empty = true;
 165.577 +//                    boolean okay = true;
 165.578 +                    int start = index;
 165.579 +                    for (; index < n; index++) {
 165.580 +                        char c = sb.charAt(index);
 165.581 +                        if (c == '\n') {
 165.582 +                            break;
 165.583 +                        }
 165.584 +                        empty = false;
 165.585 +//                        if (c == '<') {
 165.586 +//                            okay = false;
 165.587 +//                        }
 165.588 +                    }
 165.589 +                    if (!empty/* && okay*/) {
 165.590 +                        String tag = "h2"; // NOI18N
 165.591 +                        if (line.startsWith("-") || line.startsWith("^")) { // NOI18N
 165.592 +                            tag = "h3"; // NOI18N
 165.593 +                        }
 165.594 +                        sb.insert(start, "<" + tag + ">"); // NOI18N
 165.595 +                        sb.append("</" + tag + ">\n"); // NOI18N
 165.596 +                        lastWasEmpty = true;
 165.597 +                        return;
 165.598 +                    }
 165.599 +                }
 165.600 +
 165.601 +                //sb.append(line);
 165.602 +                appendRstLine(line);
 165.603 +
 165.604 +                sb.append("\n"); // NOI18N
 165.605 +            }
 165.606 +        } catch (CharConversionException ex) {
 165.607 +            Exceptions.printStackTrace(ex);
 165.608 +        }
 165.609 +    }
 165.610 +
 165.611 +    public void appendSignature(Element element) {
 165.612 +        sb.append("<pre>"); // NOI18N
 165.613 +
 165.614 +        if (element instanceof IndexedMethod) {
 165.615 +            IndexedMethod executable = (IndexedMethod)element;
 165.616 +            if (element.getIn() != null && !PythonIndex.isBuiltinModule(element.getIn())) {
 165.617 +                String in = element.getIn();
 165.618 +                sb.append("<i>"); // NOI18N
 165.619 +                sb.append(in);
 165.620 +                sb.append("</i>"); // NOI18N
 165.621 +                sb.append("<br>"); // NOI18N
 165.622 +            }
 165.623 +            // TODO - share this between Navigator implementation and here...
 165.624 +            sb.append("<b>"); // NOI18N
 165.625 +            sb.append(element.getName());
 165.626 +            sb.append("</b>"); // NOI18N
 165.627 +            String[] parameters = executable.getParams();
 165.628 +
 165.629 +            if ((parameters != null) && (parameters.length > 0)) {
 165.630 +                sb.append("("); // NOI18N
 165.631 +
 165.632 +                sb.append("<font color=\"#808080\">"); // NOI18N
 165.633 +
 165.634 +                boolean first = true;
 165.635 +                for (String parameter : parameters) {
 165.636 +                    if (first) {
 165.637 +                        first = false;
 165.638 +                    } else {
 165.639 +                        sb.append(", ");
 165.640 +                    }
 165.641 +                    sb.append(parameter);
 165.642 +                }
 165.643 +
 165.644 +                sb.append("</font>"); // NOI18N
 165.645 +
 165.646 +                sb.append(")"); // NOI18N
 165.647 +            }
 165.648 +        } else if (element instanceof IndexedElement) {
 165.649 +            //IndexedElement clz = (IndexedElement)element;
 165.650 +            String name = element.getName();
 165.651 +//            final String fqn = clz.getFqn();
 165.652 +//            if (fqn != null && !name.equals(fqn)) {
 165.653 +//                signature.append("<i>"); // NOI18N
 165.654 +//                signature.append(fqn); // NOI18N
 165.655 +//                signature.append("</i>"); // NOI18N
 165.656 +//                signature.append("<br>"); // NOI18N
 165.657 +//            }
 165.658 +            sb.append("<b>"); // NOI18N
 165.659 +            sb.append(name);
 165.660 +            sb.append("</b>"); // NOI18N
 165.661 +        } else {
 165.662 +            sb.append(element.getName());
 165.663 +        }
 165.664 +
 165.665 +        sb.append("</pre>\n"); // NOI18N
 165.666 +    }
 165.667 +
 165.668 +    public void appendHtml(String html) {
 165.669 +        sb.append(html);
 165.670 +    }
 165.671 +
 165.672 +    public void markEmpty() {
 165.673 +        beginPos = sb.length();
 165.674 +    }
 165.675 +
 165.676 +    public String toHtml() {
 165.677 +        flush();
 165.678 +        return sb.toString();
 165.679 +    }
 165.680 +
 165.681 +    public static String document(String rst) {
 165.682 +        RstFormatter formatter = new RstFormatter();
 165.683 +        String[] lines = rst.split("\n"); // NOI18N
 165.684 +        for (String line : lines) {
 165.685 +            formatter.append(line);
 165.686 +        }
 165.687 +        return formatter.toHtml();
 165.688 +    }
 165.689 +
 165.690 +    public static String getDocumentation(IndexedElement indexedElement) {
 165.691 +        RstFormatter formatter = new RstFormatter();
 165.692 +        FileObject fileObject = indexedElement.getFileObject();
 165.693 +        if (fileObject == null) {
 165.694 +            return null;
 165.695 +        }
 165.696 +        BaseDocument document = GsfUtilities.getDocument(fileObject, true);
 165.697 +        if (document == null) {
 165.698 +            return null;
 165.699 +        }
 165.700 +
 165.701 +        String[] signatureHolder = new String[1];
 165.702 +        String rst = formatter.extractRst(indexedElement, document, signatureHolder);
 165.703 +        if (rst != null && rst.length() > 0) {
 165.704 +            String signature = signatureHolder[0];
 165.705 +            if (signature == null) {
 165.706 +                formatter.appendSignature(indexedElement);
 165.707 +                formatter.appendHtml("\n<hr>\n"); // NOI18N
 165.708 +                formatter.markEmpty();
 165.709 +            } else {
 165.710 +                formatter.appendHtml("<pre>"); // NOI18N
 165.711 +                formatter.appendHtml("<b>"); // NOI18N
 165.712 +                int paren = signature.indexOf('(');
 165.713 +                if (paren != -1) {
 165.714 +                    formatter.appendHtml(signature.substring(0, paren));
 165.715 +                    formatter.appendHtml("</b>"); // NOI18N
 165.716 +                    formatter.appendHtml("<font color=\"#808080\">"); // NOI18N
 165.717 +                    formatter.appendHtml(signature.substring(paren));
 165.718 +                    formatter.appendHtml("</font>"); // NOI18N
 165.719 +                } else {
 165.720 +                    formatter.appendHtml(signature);
 165.721 +                    formatter.appendHtml("()"); // NOI18N
 165.722 +                    formatter.appendHtml("</b>"); // NOI18N
 165.723 +                }
 165.724 +                formatter.appendHtml("</pre>"); // NOI18N
 165.725 +                formatter.appendHtml("\n<hr>\n"); // NOI18N
 165.726 +                formatter.markEmpty();
 165.727 +            }
 165.728 +
 165.729 +            String[] lines = rst.split("\n"); // NOI18N
 165.730 +            for (String line : lines) {
 165.731 +                formatter.append(line);
 165.732 +            }
 165.733 +            return formatter.toHtml();
 165.734 +        }
 165.735 +
 165.736 +        return null;
 165.737 +    }
 165.738 +
 165.739 +    /**
 165.740 +     * Find the reStructured text for the documentation for the given element
 165.741 +     * in the given RST document
 165.742 +     * @param indexedElement
 165.743 +     * @param document
 165.744 +     * @return
 165.745 +     */
 165.746 +    private String extractRst(IndexedElement element, BaseDocument doc, String[] signatureHolder) {
 165.747 +        return extractRst(element.getName(), element.getClz(), element.getKind(), doc, signatureHolder);
 165.748 +    }
 165.749 +
 165.750 +    String extractRst(String name, String clz, ElementKind kind, BaseDocument doc, String[] signatureHolder) {
 165.751 +        try {
 165.752 +            String text = doc.getText(0, doc.getLength());
 165.753 +            // What about functions?
 165.754 +            if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
 165.755 +                int offset = findElementMatch(text, "function::", name, true); // NOI18N
 165.756 +                if (offset == -1) {
 165.757 +                    offset = findElementMatch(text, "method::", name, false); // NOI18N
 165.758 +                    if (offset == -1 && kind == ElementKind.CONSTRUCTOR) {
 165.759 +                        offset = findElementMatch(text, "class::", name, false); // NOI18N
 165.760 +                        if (offset == -1 && clz != null && clz.length() > 0 && "__init__".equals(name)) { // NOI18N
 165.761 +                            offset = findElementMatch(text, "method::", clz, false); // NOI18N
 165.762 +                            if (offset == -1) {
 165.763 +                                offset = findElementMatch(text, "class::", clz, false); // NOI18N
 165.764 +                            }
 165.765 +                        }
 165.766 +                    }
 165.767 +                }
 165.768 +                if (offset != -1) {
 165.769 +                    int end = findElementEnd(text, offset);
 165.770 +                    int nextLine = getNextLineOffset(text, offset);
 165.771 +                    if (nextLine < end) {
 165.772 +                        if (signatureHolder != null) {
 165.773 +                            String signature = text.substring(text.indexOf("::", offset) + 2, nextLine).trim(); // NOI18N
 165.774 +                            signatureHolder[0] = signature;
 165.775 +                        }
 165.776 +                        return text.substring(nextLine, end);
 165.777 +                    }
 165.778 +                }
 165.779 +            } else if (kind == ElementKind.CLASS) {
 165.780 +                int offset = findElementMatch(text, "class::", name, false); // NOI18N
 165.781 +                if (offset == -1) {
 165.782 +                    offset = findElementMatch(text, "exception::", name, false); // NOI18N
 165.783 +                }
 165.784 +                if (offset != -1) {
 165.785 +                    int end = findElementEnd(text, offset);
 165.786 +                    int nextLine = getNextLineOffset(text, offset);
 165.787 +                    if (nextLine < end) {
 165.788 +                        String elementText = text.substring(nextLine, end);
 165.789 +                        return elementText;
 165.790 +                    }
 165.791 +                }
 165.792 +            } else if (kind == ElementKind.MODULE) {
 165.793 +                int offset = findElementMatch(text, "module::", name, false); // NOI18N
 165.794 +                if (offset == -1) {
 165.795 +                    offset = findElementMatch(text, "currentmodule::", name, false); // NOI18N
 165.796 +                }
 165.797 +                if (offset != -1) {
 165.798 +                    int end = findElementEnd(text, offset);
 165.799 +                    int nextLine = getNextLineOffset(text, offset);
 165.800 +                    if (nextLine < end) {
 165.801 +                        String elementText = text.substring(nextLine, end);
 165.802 +                        return elementText;
 165.803 +                    }
 165.804 +                }
 165.805 +            } else {
 165.806 +//                assert kind == ElementKind.ATTRIBUTE :;
 165.807 +                int offset = findElementMatch(text, "data::", name, true); // NOI18N
 165.808 +                if (offset == -1) {
 165.809 +                    offset = findElementMatch(text, "attribute::", name, false); // NOI18N
 165.810 +                }
 165.811 +                if (offset != -1) {
 165.812 +                    int end = findElementEnd(text, offset);
 165.813 +                    int nextLine = getNextLineOffset(text, offset);
 165.814 +                    if (nextLine < end) {
 165.815 +                        String elementText = text.substring(nextLine, end);
 165.816 +                        return elementText;
 165.817 +                    }
 165.818 +                }
 165.819 +            }
 165.820 +        } catch (BadLocationException ex) {
 165.821 +            Exceptions.printStackTrace(ex);
 165.822 +            return "";
 165.823 +        }
 165.824 +
 165.825 +//        while (true) {
 165.826 +//            try {
 165.827 +//                int ret = doc.find(new FinderFactory.StringFwdFinder(".. " + key + "::", true), offset, -1);
 165.828 +//                if (ret == -1) {
 165.829 +//                    break;
 165.830 +//                }
 165.831 +//            } catch (BadLocationException ex) {
 165.832 +//                Exceptions.printStackTrace(ex);
 165.833 +//            }
 165.834 +//        }
 165.835 +
 165.836 +
 165.837 +        return "";
 165.838 +    }
 165.839 +
 165.840 +    public static int getIndentation(String text, int lineBegin) {
 165.841 +        for (int i = lineBegin; i < text.length(); i++) {
 165.842 +            char c = text.charAt(i);
 165.843 +            if (c == '\n') {
 165.844 +                // Empty lines don't count
 165.845 +                return -1;
 165.846 +            }
 165.847 +            if (!Character.isWhitespace(c)) {
 165.848 +                // Doesn't quite work for tabs etc. but those aren't
 165.849 +                // really used in rst files... Fix when I switch to
 165.850 +                // direct document iteration
 165.851 +                return i - lineBegin;
 165.852 +            }
 165.853 +        }
 165.854 +
 165.855 +        return -1;
 165.856 +    }
 165.857 +
 165.858 +    public static int getNextLineOffset(String text, int offset) {
 165.859 +        int index = text.indexOf('\n', offset);
 165.860 +        if (index == -1) {
 165.861 +            return -1;
 165.862 +        } else {
 165.863 +            return index + 1;
 165.864 +        }
 165.865 +    }
 165.866 +
 165.867 +    public static int findElementEnd(String text, int offset) {
 165.868 +        // Find beginning of line
 165.869 +        int lineBegin = 0;
 165.870 +        for (int i = offset; i > 0; i--) {
 165.871 +            char c = text.charAt(i);
 165.872 +            if (c == '\n') {
 165.873 +                lineBegin = i + 1;
 165.874 +                break;
 165.875 +            }
 165.876 +        }
 165.877 +
 165.878 +        // Compute indentation of the ..
 165.879 +        int firstIndent = getIndentation(text, lineBegin);
 165.880 +        offset = getNextLineOffset(text, lineBegin);
 165.881 +        while (true) {
 165.882 +            offset = getNextLineOffset(text, offset);
 165.883 +            if (offset == -1) {
 165.884 +                return text.length();
 165.885 +            }
 165.886 +            int indent = getIndentation(text, offset);
 165.887 +            if (indent == -1) {
 165.888 +                // Empty line - doesn't count
 165.889 +                continue;
 165.890 +            } else if (indent <= firstIndent) {
 165.891 +                return offset;
 165.892 +            }
 165.893 +        }
 165.894 +    }
 165.895 +
 165.896 +    public static int findElementMatch(String text, String key, String name, boolean checkAdjacentLines) {
 165.897 +        int nameLength = name.length();
 165.898 +        int offset = 0;
 165.899 +        int keyLength = key.length();
 165.900 +        while (true) {
 165.901 +            int next = text.indexOf(key, offset);
 165.902 +            if (next == -1) {
 165.903 +                break;
 165.904 +            }
 165.905 +            offset = next + keyLength;
 165.906 +
 165.907 +            int lineEnd = text.indexOf('\n', offset);
 165.908 +            if (lineEnd == -1) {
 165.909 +                lineEnd = text.length(); // on last line with no crlf at the end
 165.910 +            }
 165.911 +
 165.912 +            // Skip whitespace
 165.913 +            for (; offset < lineEnd; offset++) {
 165.914 +                char c = text.charAt(offset);
 165.915 +                if (c != ' ') {
 165.916 +                    break;
 165.917 +                }
 165.918 +            }
 165.919 +
 165.920 +            int nameBegin = offset;
 165.921 +            int nameEnd = -1;
 165.922 +
 165.923 +            // Pick out the bame
 165.924 +            for (int i = offset; i < lineEnd; i++) {
 165.925 +                char c = text.charAt(i);
 165.926 +                if (c == '(' || c == ' ') {
 165.927 +                    nameEnd = i;
 165.928 +                    break;
 165.929 +                } else if (c == '.') {
 165.930 +                    nameBegin = i + 1;
 165.931 +                }
 165.932 +            }
 165.933 +            if (nameEnd == -1) {
 165.934 +                nameEnd = lineEnd;
 165.935 +            }
 165.936 +
 165.937 +
 165.938 +            if (nameEnd - nameBegin == nameLength &&
 165.939 +                    text.regionMatches(nameBegin, name, 0, nameLength)) {
 165.940 +                // TODO - validate the arguments list?
 165.941 +                return next;
 165.942 +            }
 165.943 +
 165.944 +            // Look on subsequent lines too - we sometimes have adjacent lines
 165.945 +            // with additional signatures
 165.946 +            if (checkAdjacentLines) {
 165.947 +                while (true) {
 165.948 +                    int lineBegin = lineEnd+1;
 165.949 +                    if (lineBegin >= text.length()) {
 165.950 +                        break;
 165.951 +                    }
 165.952 +
 165.953 +                    lineEnd = text.indexOf('\n', lineBegin);
 165.954 +                    if (lineEnd == -1) {
 165.955 +                        lineEnd = text.length(); // on last line with no crlf at the end
 165.956 +                    }
 165.957 +
 165.958 +                    while (lineBegin < lineEnd) {
 165.959 +                        char c = text.charAt(lineBegin);
 165.960 +                        if (!Character.isWhitespace(c)) {
 165.961 +                            break;
 165.962 +                        }
 165.963 +                        lineBegin++;
 165.964 +                    }
 165.965 +
 165.966 +                    while (lineEnd > lineBegin) {
 165.967 +                        char c = text.charAt(lineEnd-1);
 165.968 +                        if (!Character.isWhitespace(c)) {
 165.969 +                            break;
 165.970 +                        }
 165.971 +                        lineEnd--;
 165.972 +                    }
 165.973 +
 165.974 +                    if (lineEnd <= lineBegin) {
 165.975 +                        break;
 165.976 +                    }
 165.977 +
 165.978 +                    nameBegin = lineBegin;
 165.979 +                    nameEnd = -1;
 165.980 +
 165.981 +                    // Pick out the name
 165.982 +                    for (int i = lineBegin; i < lineEnd; i++) {
 165.983 +                        char c = text.charAt(i);
 165.984 +                        if (c == '(' || c == ' ') {
 165.985 +                            nameEnd = i;
 165.986 +                            break;
 165.987 +                        } else if (c == '.') {
 165.988 +                            nameBegin = i + 1;
 165.989 +                        }
 165.990 +                    }
 165.991 +                    if (nameEnd == -1) {
 165.992 +                        nameEnd = lineEnd;
 165.993 +                    }
 165.994 +
 165.995 +                    if (nameEnd - nameBegin == nameLength &&
 165.996 +                            text.regionMatches(nameBegin, name, 0, nameLength)) {
 165.997 +                        // TODO - validate the arguments list?
 165.998 +                        return next;
 165.999 +                    }
165.1000 +                }
165.1001 +            }
165.1002 +
165.1003 +        }
165.1004 +
165.1005 +        return -1;
165.1006 +    }
165.1007 +
165.1008 +    public static String document(ParserResult info, ElementHandle element) {
165.1009 +        if (element instanceof IndexedElement) {
165.1010 +            IndexedElement indexedElement = (IndexedElement)element;
165.1011 +
165.1012 +            FileObject fo = indexedElement.getFileObject();
165.1013 +
165.1014 +            if (fo == null) {
165.1015 +                return null;
165.1016 +            }
165.1017 +
165.1018 +            if (PythonUtils.isRstFile(fo)) {
165.1019 +                return getDocumentation(indexedElement);
165.1020 +            }
165.1021 +
165.1022 +
165.1023 +            PythonTree node = indexedElement.getNode();
165.1024 +            if (node != null) {
165.1025 +                return document(info, node, indexedElement);
165.1026 +            }
165.1027 +        }
165.1028 +        return null;
165.1029 +    }
165.1030 +
165.1031 +    public static String document(ParserResult info, PythonTree node, IndexedElement element) {
165.1032 +        if (node != null) {
165.1033 +            String doc = PythonAstUtils.getDocumentation(node);
165.1034 +            if (doc != null) {
165.1035 +                // Honor empty lines: paragraphs
165.1036 +                RstFormatter formatter = new RstFormatter();
165.1037 +                if (element != null) {
165.1038 +                    formatter.appendSignature(element);
165.1039 +                }
165.1040 +                if (doc.indexOf('\n') != -1) {
165.1041 +                    formatter.appendHtml("\n<hr>\n"); // NOI18N
165.1042 +                    formatter.markEmpty();
165.1043 +                    String[] lines = doc.split("\n"); // NOI18N
165.1044 +                    for (String line : lines) {
165.1045 +                        formatter.append(line);
165.1046 +                    }
165.1047 +                } else if (doc.length() > 0) {
165.1048 +                    formatter.appendHtml("\n<hr>\n"); // NOI18N
165.1049 +                    formatter.markEmpty();
165.1050 +                    formatter.append(doc);
165.1051 +                }
165.1052 +
165.1053 +                return formatter.toHtml();
165.1054 +            }
165.1055 +        }
165.1056 +
165.1057 +        return null;
165.1058 +    }
165.1059 +
165.1060 +    public static String getSignature(Element element) {
165.1061 +        StringBuilder signature = new StringBuilder();
165.1062 +        // TODO:
165.1063 +        signature.append("<pre>"); // NOI18N
165.1064 +
165.1065 +        if (element instanceof IndexedMethod) {
165.1066 +            IndexedMethod executable = (IndexedMethod)element;
165.1067 +            if (element.getIn() != null) {
165.1068 +                String in = element.getIn();
165.1069 +                signature.append("<i>"); // NOI18N
165.1070 +                signature.append(in);
165.1071 +                signature.append("</i>"); // NOI18N
165.1072 +                signature.append("<br>"); // NOI18N
165.1073 +            }
165.1074 +            // TODO - share this between Navigator implementation and here...
165.1075 +            signature.append("<b>"); // NOI18N
165.1076 +            signature.append(element.getName());
165.1077 +            signature.append("</b>"); // NOI18N
165.1078 +            String[] parameters = executable.getParams();
165.1079 +
165.1080 +            if ((parameters != null) && (parameters.length > 0)) {
165.1081 +                signature.append("("); // NOI18N
165.1082 +
165.1083 +                signature.append("<font color=\"#808080\">"); // NOI18N
165.1084 +
165.1085 +                boolean first = true;
165.1086 +                for (String parameter : parameters) {
165.1087 +                    if (first) {
165.1088 +                        first = false;
165.1089 +                    } else {
165.1090 +                        signature.append(", "); // NOI18N
165.1091 +                    }
165.1092 +                    signature.append(parameter);
165.1093 +                }
165.1094 +
165.1095 +                signature.append("</font>"); // NOI18N
165.1096 +
165.1097 +                signature.append(")"); // NOI18N
165.1098 +            }
165.1099 +        } else if (element instanceof IndexedElement) {
165.1100 +//            IndexedElement clz = (IndexedElement)element;
165.1101 +            String name = element.getName();
165.1102 +//            final String fqn = clz.getFqn();
165.1103 +//            if (fqn != null && !name.equals(fqn)) {
165.1104 +//                signature.append("<i>"); // NOI18N
165.1105 +//                signature.append(fqn); // NOI18N
165.1106 +//                signature.append("</i>"); // NOI18N
165.1107 +//                signature.append("<br>"); // NOI18N
165.1108 +//            }
165.1109 +            signature.append("<b>"); // NOI18N
165.1110 +            signature.append(name);
165.1111 +            signature.append("</b>"); // NOI18N
165.1112 +        } else {
165.1113 +            signature.append(element.getName());
165.1114 +        }
165.1115 +
165.1116 +        signature.append("</pre>\n"); // NOI18N
165.1117 +
165.1118 +        return signature.toString();
165.1119 +    }
165.1120 +
165.1121 +    @SuppressWarnings("unchecked")
165.1122 +    private String getPythonHtml(List<String> source, boolean addPre) {
165.1123 +        StringBuilder python = new StringBuilder(500);
165.1124 +
165.1125 +        for (String s : source) {
165.1126 +            python.append(s);
165.1127 +            python.append("\n"); // NOI18N
165.1128 +        }
165.1129 +
165.1130 +        Language<?> language = PythonTokenId.language();
165.1131 +        String mimeType = PythonMIMEResolver.PYTHON_MIME_TYPE;
165.1132 +        // TODO - handle YAML and other languages I can see in the documentation...
165.1133 +        /*if (python.indexOf(" <%") != -1) { // NOI18N
165.1134 +        mimeType = "application/x-httpd-eruby"; // RHTML
165.1135 +        Collection<LanguageProvider> providers = (Collection<LanguageProvider>) Lookup.getDefault().lookupAll(LanguageProvider.class);
165.1136 +        for (LanguageProvider provider : providers) {
165.1137 +        language = provider.findLanguage(mimeType);
165.1138 +        if (language != null) {
165.1139 +        break;
165.1140 +        }
165.1141 +        }
165.1142 +
165.1143 +        if (language == null) {
165.1144 +        mimeType = PythonTokenId.PYTHON_MIME_TYPE;
165.1145 +        language = PythonTokenId.language();
165.1146 +        }
165.1147 +        } else*/ if (source.get(0).trim().startsWith("<")) {
165.1148 +            // Looks like markup (other than RHTML) - don't colorize it
165.1149 +            // since we don't know how
165.1150 +            return null;
165.1151 +        }
165.1152 +
165.1153 +        StringBuilder buffer = new StringBuilder(1500);
165.1154 +
165.1155 +        boolean errors = appendSequence(buffer, python.toString(), language, mimeType, addPre);
165.1156 +        return errors ? null : buffer.toString();
165.1157 +    }
165.1158 +
165.1159 +    @SuppressWarnings("unchecked")
165.1160 +    private boolean appendSequence(StringBuilder sb, String text,
165.1161 +            Language<?> language, String mimeType, boolean addPre) {
165.1162 +        // XXX is this getting called twice?
165.1163 +        MimePath mimePath = MimePath.parse(mimeType);
165.1164 +        Lookup lookup = MimeLookup.getLookup(mimePath);
165.1165 +        FontColorSettings fcs = lookup.lookup(FontColorSettings.class);
165.1166 +
165.1167 +        if (addPre) {
165.1168 +            sb.append("<pre style=\""); // NOI18N
165.1169 +
165.1170 +            sb.append("border-color: #dddddd; border-style: solid; border-width: 1px; ");
165.1171 +
165.1172 +            AttributeSet attribs = fcs.getTokenFontColors("default"); // NOI18N
165.1173 +            Color fg = (Color)attribs.getAttribute(StyleConstants.Foreground);
165.1174 +            if (fg != null) {
165.1175 +                sb.append("color:"); // NOI18N
165.1176 +                sb.append(getHtmlColor(fg));
165.1177 +                sb.append(";"); // NOI18N
165.1178 +            }
165.1179 +            Color bg = (Color)attribs.getAttribute(StyleConstants.Background);
165.1180 +            // Only set the background for dark colors
165.1181 +            if (bg != null && bg.getRed() < 128) {
165.1182 +                sb.append("background:"); // NOI18N
165.1183 +                sb.append(getHtmlColor(bg));
165.1184 +            }
165.1185 +
165.1186 +            sb.append("\">\n"); // NOI18N
165.1187 +        }
165.1188 +        TokenHierarchy hi = TokenHierarchy.create(text, language);
165.1189 +        TokenSequence ts = hi.tokenSequence();
165.1190 +
165.1191 +        int offset = 0;
165.1192 +        ts.move(offset);
165.1193 +
165.1194 +        if (ts.moveNext()) {
165.1195 +            do {
165.1196 +                Token t = ts.token();
165.1197 +                String tokenText = t.text().toString();
165.1198 +
165.1199 +                // TODO - make style classes instead of inlining everything as font!
165.1200 +                String category = t.id().name();
165.1201 +                String primaryCategory = t.id().primaryCategory();
165.1202 +
165.1203 +                if ("error".equals(primaryCategory)) { // NOI18N
165.1204 +                    // Abort: an error token means the output probably isn't
165.1205 +                    // code, or it's code or markup but in a different language
165.1206 +                    // than we're trying to process it as
165.1207 +                    return true;
165.1208 +                }
165.1209 +
165.1210 +                AttributeSet attribs = fcs.getTokenFontColors(category);
165.1211 +                String escapedText = tokenText;
165.1212 +                try {
165.1213 +                    escapedText = XMLUtil.toElementContent(tokenText);
165.1214 +                } catch (CharConversionException cce) {
165.1215 +                    Exceptions.printStackTrace(cce);
165.1216 +                }
165.1217 +
165.1218 +                if (attribs == null) {
165.1219 +                    category = primaryCategory;
165.1220 +                    attribs = fcs.getTokenFontColors(category);
165.1221 +
165.1222 +                }
165.1223 +
165.1224 +                TokenSequence embedded = ts.embedded();
165.1225 +                if (embedded != null) {
165.1226 +                    //embedded.languagePath().mimePath();
165.1227 +                    String embeddedMimeType = MimePath.parse(embedded.languagePath().mimePath()).getPath();
165.1228 +                    Color bg = null;
165.1229 +                    Color fg = null;
165.1230 +                    if (attribs != null) {
165.1231 +                        bg = (Color)attribs.getAttribute(StyleConstants.Background);
165.1232 +                        fg = (Color)attribs.getAttribute(StyleConstants.Foreground);
165.1233 +                        if (fg != null || bg != null) {
165.1234 +                            sb.append("<span style=\"");
165.1235 +                            if (bg != null) {
165.1236 +                                sb.append("background:"); // NOI18N
165.1237 +                                sb.append(getHtmlColor(bg));
165.1238 +                                sb.append(";");
165.1239 +                            }
165.1240 +                            if (fg != null) {
165.1241 +                                sb.append("color:"); // NOI18N
165.1242 +                                sb.append(getHtmlColor(fg));
165.1243 +                            }
165.1244 +                            sb.append("\">"); // NOI18N
165.1245 +                        }
165.1246 +                    }
165.1247 +                    appendSequence(sb, tokenText, embedded.language(), embeddedMimeType, false);
165.1248 +                    if (fg != null || bg != null) {
165.1249 +                        sb.append("</span>"); // NOI18N
165.1250 +                    }
165.1251 +                    continue;
165.1252 +                }
165.1253 +
165.1254 +                if (attribs == null) {
165.1255 +                    sb.append(escapedText);
165.1256 +
165.1257 +                    continue;
165.1258 +                }
165.1259 +
165.1260 +                if (escapedText.indexOf('\n') != -1) {
165.1261 +                    escapedText = escapedText.replace("\n", "<br>"); // NOI18N
165.1262 +                }
165.1263 +
165.1264 +                if (t.id() == PythonTokenId.WHITESPACE) {
165.1265 +                    sb.append(escapedText);
165.1266 +                } else {
165.1267 +                    sb.append("<span style=\""); // NOI18N
165.1268 +
165.1269 +                    Color fg = (Color)attribs.getAttribute(StyleConstants.Foreground);
165.1270 +
165.1271 +                    if (fg != null) {
165.1272 +                        sb.append("color:"); // NOI18N
165.1273 +                        sb.append(getHtmlColor(fg));
165.1274 +                        sb.append(";"); // NOI18N
165.1275 +                    }
165.1276 +
165.1277 +                    Color bg = (Color)attribs.getAttribute(StyleConstants.Background);
165.1278 +
165.1279 +                    if (bg != null) {
165.1280 +                        sb.append("background:"); // NOI18N
165.1281 +                        sb.append(getHtmlColor(bg));
165.1282 +                        sb.append(";"); // NOI18NP
165.1283 +                    }
165.1284 +
165.1285 +                    Boolean b = (Boolean)attribs.getAttribute(StyleConstants.Bold);
165.1286 +
165.1287 +                    if ((b != null) && b) {
165.1288 +                        sb.append("font-weight:bold;"); // NOI18N
165.1289 +                    }
165.1290 +
165.1291 +                    b = (Boolean)attribs.getAttribute(StyleConstants.Italic);
165.1292 +
165.1293 +                    if ((b != null) && b) {
165.1294 +                        sb.append("font-style:italic;"); // NOI18N
165.1295 +                    }
165.1296 +
165.1297 +                    // TODO - underline, strikethrough, ... and FONTS!
165.1298 +                    sb.append("\">"); // NOI18N
165.1299 +                    sb.append(escapedText);
165.1300 +                    sb.append("</span>"); // NOI18N
165.1301 +                }
165.1302 +            } while (ts.moveNext());
165.1303 +        }
165.1304 +
165.1305 +        if (addPre) {
165.1306 +            sb.append("</pre>\n");
165.1307 +        }
165.1308 +
165.1309 +        return false;
165.1310 +    }
165.1311 +
165.1312 +
165.1313 +    // TODO - move to GsfUtilities?
165.1314 +    private static String getHtmlColor(Color c) {
165.1315 +        int r = c.getRed();
165.1316 +        int g = c.getGreen();
165.1317 +        int b = c.getBlue();
165.1318 +        StringBuffer result = new StringBuffer();
165.1319 +        result.append('#');
165.1320 +
165.1321 +        String rs = Integer.toHexString(r);
165.1322 +        String gs = Integer.toHexString(g);
165.1323 +        String bs = Integer.toHexString(b);
165.1324 +
165.1325 +        if (r < 0x10) {
165.1326 +            result.append('0');
165.1327 +        }
165.1328 +
165.1329 +        result.append(rs);
165.1330 +
165.1331 +        if (g < 0x10) {
165.1332 +            result.append('0');
165.1333 +        }
165.1334 +
165.1335 +        result.append(gs);
165.1336 +
165.1337 +        if (b < 0x10) {
165.1338 +            result.append('0');
165.1339 +        }
165.1340 +
165.1341 +        result.append(bs);
165.1342 +
165.1343 +        return result.toString();
165.1344 +    }
165.1345 +}
   166.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   166.2 +++ b/python.source/src/org/netbeans/modules/python/source/elements/AstElement.java	Mon Sep 21 13:01:16 2015 +0200
   166.3 @@ -0,0 +1,117 @@
   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 java.util.Set;
  166.37 +import org.netbeans.modules.csl.api.ElementKind;
  166.38 +import org.netbeans.modules.csl.api.Modifier;
  166.39 +import org.netbeans.modules.csl.api.OffsetRange;
  166.40 +import org.netbeans.modules.csl.spi.ParserResult;
  166.41 +import org.netbeans.modules.python.source.PythonAstUtils;
  166.42 +import org.netbeans.modules.python.source.PythonParserResult;
  166.43 +import org.netbeans.modules.python.source.PythonStructureItem;
  166.44 +import org.netbeans.modules.python.source.PythonStructureScanner;
  166.45 +import org.netbeans.modules.python.source.scopes.SymbolTable;
  166.46 +import org.python.antlr.PythonTree;
  166.47 +import org.python.antlr.ast.Call;
  166.48 +import org.python.antlr.ast.ClassDef;
  166.49 +import org.python.antlr.ast.FunctionDef;
  166.50 +import org.python.antlr.ast.Name;
  166.51 +
  166.52 +/**
  166.53 + * Elements representing a node in a parse tree
  166.54 + *
  166.55 + * @author Tor Norbye
  166.56 + */
  166.57 +public class AstElement extends Element {
  166.58 +    protected PythonTree node;
  166.59 +    protected String name;
  166.60 +    protected ElementKind kind;
  166.61 +    //protected CompilationInfo info;
  166.62 +    protected Set<Modifier> modifiers;
  166.63 +    protected SymbolTable scopes;
  166.64 +
  166.65 +    public AstElement(SymbolTable scopes, PythonTree node, String name, ElementKind kind) {
  166.66 +        //this.info = info;
  166.67 +        this.scopes = scopes;
  166.68 +        this.node = node;
  166.69 +        this.name = name;
  166.70 +        this.kind = kind;
  166.71 +    }
  166.72 +
  166.73 +    public static AstElement create(PythonParserResult result, PythonTree node) {
  166.74 +        SymbolTable scopes = result.getSymbolTable();
  166.75 +
  166.76 +        if (node instanceof FunctionDef) {
  166.77 +            return new PythonStructureItem(scopes, (FunctionDef)node);
  166.78 +        } else if (node instanceof ClassDef) {
  166.79 +            return new PythonStructureItem(scopes, (ClassDef)node);
  166.80 +        } else if (node instanceof Call) {
  166.81 +            String name = PythonAstUtils.getCallName((Call)node);
  166.82 +            return new AstElement(scopes, node, name, ElementKind.METHOD);
  166.83 +        } else if (node instanceof Name) {
  166.84 +            return new AstElement(scopes, node, ((Name)node).getInternalId(), ElementKind.VARIABLE);
  166.85 +        } else {
  166.86 +            return new AstElement(scopes, node, null, ElementKind.OTHER);
  166.87 +        }
  166.88 +    }
  166.89 +
  166.90 +    public PythonTree getNode() {
  166.91 +        return node;
  166.92 +    }
  166.93 +
  166.94 +    @Override
  166.95 +    public String getName() {
  166.96 +        return name;
  166.97 +    }
  166.98 +
  166.99 +    @Override
 166.100 +    public ElementKind getKind() {
 166.101 +        return kind;
 166.102 +    }
 166.103 +
 166.104 +    @Override
 166.105 +    public Set<Modifier> getModifiers() {
 166.106 +        if (modifiers == null) {
 166.107 +            if (name != null && scopes.isPrivate(node, name)) {
 166.108 +                modifiers = IndexedElement.PRIVATE_MODIFIERS;
 166.109 +            } else {
 166.110 +                modifiers = IndexedElement.PUBLIC_MODIFIERS;
 166.111 +            }
 166.112 +        }
 166.113 +
 166.114 +        return modifiers;
 166.115 +    }
 166.116 +
 166.117 +    public Object getSignature() {
 166.118 +        return name;
 166.119 +    }
 166.120 +}
   167.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   167.2 +++ b/python.source/src/org/netbeans/modules/python/source/elements/Element.java	Mon Sep 21 13:01:16 2015 +0200
   167.3 @@ -0,0 +1,85 @@
   167.4 +/*
   167.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   167.6 + *
   167.7 + * Copyright 1997-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 + * Contributor(s):
  167.31 + *
  167.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  167.33 + */
  167.34 +package org.netbeans.modules.python.source.elements;
  167.35 +
  167.36 +import java.util.Collections;
  167.37 +import java.util.Set;
  167.38 +import org.netbeans.modules.csl.api.ElementHandle;
  167.39 +import org.netbeans.modules.csl.api.ElementKind;
  167.40 +import org.netbeans.modules.csl.api.Modifier;
  167.41 +import org.netbeans.modules.csl.api.OffsetRange;
  167.42 +import org.netbeans.modules.csl.spi.ParserResult;
  167.43 +import org.netbeans.modules.python.api.PythonMIMEResolver;
  167.44 +import org.openide.filesystems.FileObject;
  167.45 +
  167.46 +/**
  167.47 + *
  167.48 + * @author Tor Norbye
  167.49 + */
  167.50 +public abstract class Element implements ElementHandle {
  167.51 +    @Override
  167.52 +    public abstract String getName();
  167.53 +
  167.54 +    @Override
  167.55 +    public abstract ElementKind getKind();
  167.56 +
  167.57 +    @Override
  167.58 +    public String getMimeType() {
  167.59 +        return PythonMIMEResolver.PYTHON_MIME_TYPE;
  167.60 +    }
  167.61 +
  167.62 +    @Override
  167.63 +    public boolean signatureEquals(ElementHandle handle) {
  167.64 +        // XXX TODO
  167.65 +        return false;
  167.66 +    }
  167.67 +
  167.68 +    @Override
  167.69 +    public OffsetRange getOffsetRange(ParserResult pr) {
  167.70 +        // XXX TODO
  167.71 +        return null;
  167.72 +    }
  167.73 +
  167.74 +    @Override
  167.75 +    public FileObject getFileObject() {
  167.76 +        return null;
  167.77 +    }
  167.78 +
  167.79 +    @Override
  167.80 +    public Set<Modifier> getModifiers() {
  167.81 +        return Collections.emptySet();
  167.82 +    }
  167.83 +
  167.84 +    @Override
  167.85 +    public String getIn() {
  167.86 +        return null;
  167.87 +    }
  167.88 +}
   168.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   168.2 +++ b/python.source/src/org/netbeans/modules/python/source/elements/IndexedElement.java	Mon Sep 21 13:01:16 2015 +0200
   168.3 @@ -0,0 +1,527 @@
   168.4 +/*
   168.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   168.6 + *
   168.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   168.8 + *
   168.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  168.10 + * Other names may be trademarks of their respective owners.
  168.11 + *
  168.12 + * The contents of this file are subject to the terms of either the GNU
  168.13 + * General Public License Version 2 only ("GPL") or the Common
  168.14 + * Development and Distribution License("CDDL") (collectively, the
  168.15 + * "License"). You may not use this file except in compliance with the
  168.16 + * License. You can obtain a copy of the License at
  168.17 + * http://www.netbeans.org/cddl-gplv2.html
  168.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  168.19 + * specific language governing permissions and limitations under the
  168.20 + * License.  When distributing the software, include this License Header
  168.21 + * Notice in each file and include the License file at
  168.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  168.23 + * particular file as subject to the "Classpath" exception as provided
  168.24 + * by Oracle in the GPL Version 2 section of the License file that
  168.25 + * accompanied this code. If applicable, add the following below the
  168.26 + * License Header, with the fields enclosed by brackets [] replaced by
  168.27 + * your own identifying information:
  168.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  168.29 + *
  168.30 + * Contributor(s):
  168.31 + *
  168.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  168.33 + */
  168.34 +package org.netbeans.modules.python.source.elements;
  168.35 +
  168.36 +import java.util.Collections;
  168.37 +import java.util.EnumSet;
  168.38 +import java.util.Set;
  168.39 +import org.netbeans.modules.csl.api.ElementKind;
  168.40 +import org.netbeans.modules.csl.api.Modifier;
  168.41 +import org.netbeans.modules.csl.api.OffsetRange;
  168.42 +import org.netbeans.modules.csl.spi.ParserResult;
  168.43 +import org.netbeans.modules.python.source.PythonIndex;
  168.44 +import org.netbeans.modules.python.source.PythonAstUtils;
  168.45 +import org.openide.filesystems.FileObject;
  168.46 +import org.python.antlr.PythonTree;
  168.47 +
  168.48 +/**
  168.49 + * Elements representing information coming from the persistent index
  168.50 + *
  168.51 + * @author Tor Norbye
  168.52 + */
  168.53 +public class IndexedElement extends Element {
  168.54 +    public static final EnumSet<Modifier> PRIVATE_MODIFIERS = EnumSet.of(Modifier.PRIVATE);
  168.55 +    public static final EnumSet<Modifier> PROTECTED_MODIFIERS = EnumSet.of(Modifier.PROTECTED);
  168.56 +    public static final EnumSet<Modifier> STATIC_MODIFIERS = EnumSet.of(Modifier.STATIC);
  168.57 +    public static final EnumSet<Modifier> PRIVATE_STATIC_MODIFIERS = EnumSet.of(Modifier.STATIC, Modifier.PRIVATE);
  168.58 +    public static final EnumSet<Modifier> PROTECTED_STATIC_MODIFIERS = EnumSet.of(Modifier.STATIC, Modifier.PROTECTED);
  168.59 +    public static final Set<Modifier> PUBLIC_MODIFIERS = Collections.emptySet();
  168.60 +
  168.61 +    // Plan: Stash a single item for class entries so I can search by document for the class.
  168.62 +    // Add more types into the types
  168.63 +    /** This method is documented */
  168.64 +    public static final int DOCUMENTED = 1 << 0;
  168.65 +    /** This method is private */
  168.66 +    public static final int PRIVATE = 1 << 2;
  168.67 +    /** This is a function, not a property */
  168.68 +    public static final int FUNCTION = 1 << 3;
  168.69 +    /** This element is "static" (e.g. it's a classvar for fields, class method for methods etc) */
  168.70 +    public static final int STATIC = 1 << 4;
  168.71 +    /** This element is deliberately not documented (rdoc :nodoc:) */
  168.72 +    public static final int NODOC = 1 << 5;
  168.73 +    /** This is a global variable */
  168.74 +    public static final int GLOBAL = 1 << 6;
  168.75 +    /** This is a constructor */
  168.76 +    public static final int CONSTRUCTOR = 1 << 7;
  168.77 +    /** This is a deprecated */
  168.78 +    public static final int DEPRECATED = 1 << 8;
  168.79 +    /** This is a documentation-only definition */
  168.80 +    public static final int DOC_ONLY = 1 << 9;
  168.81 +    /** This is a constant/final */
  168.82 +    public static final int FINAL = 1 << 10;
  168.83 +
  168.84 +    // Flags noting semicolon positions in attributes
  168.85 +    public static final int NAME_INDEX = 0;
  168.86 +    public static final int TYPE_INDEX = 1;
  168.87 +    public static final int FLAG_INDEX = 2;
  168.88 +    public static final int ARG_INDEX = 3;
  168.89 +//    public static final int IN_INDEX = 1;
  168.90 +//    public static final int CASE_SENSITIVE_INDEX = 2;
  168.91 +//    public static final int FLAG_INDEX = 3;
  168.92 +//    public static final int ARG_INDEX = 4;
  168.93 +//    public static final int NODE_INDEX = 5;
  168.94 +//    public static final int DOC_INDEX = 6;
  168.95 +//    public static final int BROWSER_INDEX = 7;
  168.96 +//    public static final int TYPE_INDEX = 8;
  168.97 +    protected final String name;
  168.98 +    protected final ElementKind kind;
  168.99 +    protected String url;
 168.100 +    protected FileObject fileObject;
 168.101 +    protected final String module;
 168.102 +    protected String rhs;
 168.103 +    protected boolean smart;
 168.104 +    protected boolean inherited;
 168.105 +    protected Set<Modifier> modifiers;
 168.106 +    protected PythonTree node;
 168.107 +    protected int flags;
 168.108 +    protected final String attributes;
 168.109 +    protected final String clz;
 168.110 +    protected int order;
 168.111 +
 168.112 +    public IndexedElement(String name, ElementKind kind, String url, String module, String clz, String attributes) {
 168.113 +        this.name = name;
 168.114 +        this.kind = kind;
 168.115 +        this.url = url;
 168.116 +        this.module = module;
 168.117 +        this.clz = clz;
 168.118 +        this.attributes = attributes;
 168.119 +
 168.120 +    // Should be IndexedMethod:
 168.121 +    //assert !((!(this instanceof IndexedMethod)) && (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR)) : this;
 168.122 +    }
 168.123 +
 168.124 +    public static IndexedElement create(String signature, String module, String url, String clz) {
 168.125 +        int semi = signature.indexOf(';');
 168.126 +        assert semi != -1;
 168.127 +
 168.128 +        String name = signature.substring(0, semi);
 168.129 +        int flags = IndexedElement.decode(signature, semi + 3, 0);
 168.130 +
 168.131 +        char type = signature.charAt(semi + 1);
 168.132 +        ElementKind kind;
 168.133 +        switch (type) {
 168.134 +        case 'C':
 168.135 +            kind = ElementKind.CLASS;
 168.136 +            break;
 168.137 +        case 'I':
 168.138 +            kind = ElementKind.MODULE;
 168.139 +            break;
 168.140 +        case 'D':
 168.141 +            kind = ElementKind.VARIABLE;
 168.142 +            break;
 168.143 +        case 'A':
 168.144 +            kind = ElementKind.ATTRIBUTE;
 168.145 +            break;
 168.146 +        case 'F':
 168.147 +        case 'M':
 168.148 +        case 'c': {
 168.149 +            kind = type == 'c' ? ElementKind.CONSTRUCTOR : ElementKind.METHOD;
 168.150 +            IndexedMethod method = new IndexedMethod(name, kind, url, module, clz, signature);
 168.151 +            method.flags = flags;
 168.152 +            return method;
 168.153 +        }
 168.154 +        default:
 168.155 +            kind = ElementKind.OTHER;
 168.156 +            break;
 168.157 +        }
 168.158 +
 168.159 +        IndexedElement element = new IndexedElement(name, kind, url, module, clz, signature);
 168.160 +        element.flags = flags;
 168.161 +        return element;
 168.162 +    }
 168.163 +
 168.164 +    @Override
 168.165 +    public boolean equals(Object obj) {
 168.166 +        if (obj == null) {
 168.167 +            return false;
 168.168 +        }
 168.169 +        if (getClass() != obj.getClass()) {
 168.170 +            return false;
 168.171 +        }
 168.172 +        final IndexedElement other = (IndexedElement)obj;
 168.173 +        if (this.name != other.name && (this.name == null || !this.name.equals(other.name))) {
 168.174 +            return false;
 168.175 +        }
 168.176 +        if (this.module != other.module && (this.module == null || !this.module.equals(other.module))) {
 168.177 +            return false;
 168.178 +        }
 168.179 +        if (this.kind != other.kind) {
 168.180 +            return false;
 168.181 +        }
 168.182 +        return true;
 168.183 +    }
 168.184 +
 168.185 +    public String getModule() {
 168.186 +        return module;
 168.187 +    }
 168.188 +
 168.189 +    @Override
 168.190 +    public int hashCode() {
 168.191 +        int hash = 3;
 168.192 +        hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0);
 168.193 +        hash = 67 * hash + (this.kind != null ? this.kind.hashCode() : 0);
 168.194 +        return hash;
 168.195 +    }
 168.196 +
 168.197 +    @Override
 168.198 +    public String getName() {
 168.199 +        return name;
 168.200 +    }
 168.201 +
 168.202 +    @Override
 168.203 +    public ElementKind getKind() {
 168.204 +        return kind;
 168.205 +    }
 168.206 +
 168.207 +    public String getFilenameUrl() {
 168.208 +        return url;
 168.209 +    }
 168.210 +
 168.211 +    @Override
 168.212 +    public FileObject getFileObject() {
 168.213 +        if ((fileObject == null) && (url != null)) {
 168.214 +            fileObject = PythonIndex.getFileObject(url);
 168.215 +
 168.216 +            if (fileObject == null) {
 168.217 +                // Don't try again
 168.218 +                url = null;
 168.219 +            }
 168.220 +        }
 168.221 +
 168.222 +        return fileObject;
 168.223 +    }
 168.224 +
 168.225 +    public void setFlags(int flags) {
 168.226 +        this.flags = flags;
 168.227 +    }
 168.228 +
 168.229 +    public void setInherited(boolean inherited) {
 168.230 +        this.inherited = inherited;
 168.231 +    }
 168.232 +
 168.233 +    public boolean isInherited() {
 168.234 +        return inherited;
 168.235 +    }
 168.236 +
 168.237 +    public String getType() {
 168.238 +        return null;
 168.239 +    }
 168.240 +
 168.241 +    public String getOrigin() {
 168.242 +        return module;
 168.243 +    }
 168.244 +
 168.245 +    public boolean isSmart() {
 168.246 +        return smart;
 168.247 +    }
 168.248 +
 168.249 +    public void setSmart(boolean smart) {
 168.250 +        this.smart = smart;
 168.251 +    }
 168.252 +
 168.253 +    public String getRhs() {
 168.254 +        if (rhs == null) {
 168.255 +            rhs = module;
 168.256 +            if (rhs.equals("stub_missing")) { // NOI18N
 168.257 +                rhs = "<i>builtin</i>";
 168.258 +            }
 168.259 +        }
 168.260 +        return rhs;
 168.261 +    }
 168.262 +
 168.263 +    public void setRhs(String rhs) {
 168.264 +        this.rhs = rhs;
 168.265 +    }
 168.266 +
 168.267 +    @Override
 168.268 +    public String getIn() {
 168.269 +        return module;
 168.270 +    }
 168.271 +
 168.272 +    public String getSignature() {
 168.273 +        if (clz != null) {
 168.274 +            return clz + "." + name;
 168.275 +        }
 168.276 +
 168.277 +        return name;
 168.278 +    }
 168.279 +
 168.280 +    public String getClz() {
 168.281 +        return clz;
 168.282 +    }
 168.283 +
 168.284 +    public int getOrder() {
 168.285 +        return order;
 168.286 +    }
 168.287 +
 168.288 +    public void setOrder(int order) {
 168.289 +        this.order = order;
 168.290 +    }
 168.291 +
 168.292 +    public static Set<Modifier> getModifiersForName(String name, boolean isPrivate, boolean isProtected, boolean isStatic) {
 168.293 +        Set<Modifier> modifiers;
 168.294 +
 168.295 +        // Private variables: start with __ but doesn't end with __
 168.296 +        // Section 9.6 Private Variables - http://docs.python.org/tut/node11.html
 168.297 +        if (name != null && name.startsWith("__") && !name.endsWith("__")) { // NOI18N
 168.298 +            isPrivate = true;
 168.299 +        } else if (name != null && name.startsWith("_") && !name.endsWith("_")) { // NOI18N
 168.300 +            // From PEP8: Single_leading_underscore: weak "internal use" indicator
 168.301 +            // (e.g. "from M import *" does not import objects whose name
 168.302 +            // starts with an underscore).
 168.303 +            // The protected modifier might work well to visually indicate this.
 168.304 +            isProtected = true;
 168.305 +        }
 168.306 +        if (isPrivate) {
 168.307 +            if (isStatic) {
 168.308 +                modifiers = PRIVATE_STATIC_MODIFIERS;
 168.309 +            } else {
 168.310 +                modifiers = PRIVATE_MODIFIERS;
 168.311 +            }
 168.312 +        } else if (isProtected) {
 168.313 +            if (isStatic) {
 168.314 +                modifiers = PROTECTED_STATIC_MODIFIERS;
 168.315 +            } else {
 168.316 +                modifiers = PROTECTED_MODIFIERS;
 168.317 +            }
 168.318 +        } else {
 168.319 +            if (isStatic) {
 168.320 +                modifiers = STATIC_MODIFIERS;
 168.321 +            } else {
 168.322 +                modifiers = PUBLIC_MODIFIERS;
 168.323 +            }
 168.324 +        }
 168.325 +
 168.326 +        return modifiers;
 168.327 +    }
 168.328 +
 168.329 +    @Override
 168.330 +    public Set<Modifier> getModifiers() {
 168.331 +        if (modifiers == null) {
 168.332 +            modifiers = getModifiersForName(name, isPrivate(), false, isStatic());
 168.333 +        }
 168.334 +
 168.335 +        return modifiers;
 168.336 +    }
 168.337 +
 168.338 +    public PythonTree getNode() {
 168.339 +        if (node == null) {
 168.340 +            node = PythonAstUtils.getForeignNode(this, null);
 168.341 +        }
 168.342 +        return node;
 168.343 +    }
 168.344 +
 168.345 +    @Override
 168.346 +    public String toString() {
 168.347 +        return "IndexedElement:" + name + "," + kind + "," + rhs;
 168.348 +    }
 168.349 +
 168.350 +    protected int getAttributeSection(int section) {
 168.351 +        assert section != 0; // Obtain directly, and logic below (+1) is wrong
 168.352 +        int attributeIndex = 0;
 168.353 +        for (int i = 0; i < section; i++) {
 168.354 +            attributeIndex = attributes.indexOf(';', attributeIndex + 1);
 168.355 +        }
 168.356 +
 168.357 +        assert attributeIndex != -1;
 168.358 +        return attributeIndex + 1;
 168.359 +    }
 168.360 +
 168.361 +    /** Return a string (suitable for persistence) encoding the given flags */
 168.362 +    public static String encode(int flags) {
 168.363 +        return Integer.toString(flags, 16);
 168.364 +    }
 168.365 +
 168.366 +    /** Return flag corresponding to the given encoding chars */
 168.367 +    public static int decode(String s, int startIndex, int defaultValue) {
 168.368 +        int value = 0;
 168.369 +        for (int i = startIndex, n = s.length(); i < n; i++) {
 168.370 +            char c = s.charAt(i);
 168.371 +            if (c == ';') {
 168.372 +                if (i == startIndex) {
 168.373 +                    return defaultValue;
 168.374 +                }
 168.375 +                break;
 168.376 +            }
 168.377 +
 168.378 +            value = value << 4;
 168.379 +
 168.380 +            if (c > '9') {
 168.381 +                value += c - 'a' + 10;
 168.382 +            } else {
 168.383 +                value += c - '0';
 168.384 +            }
 168.385 +        }
 168.386 +
 168.387 +        return value;
 168.388 +    }
 168.389 +
 168.390 +    public static int getFlags(AstElement element) {
 168.391 +        // Return the flags corresponding to the given AST element
 168.392 +        int value = 0;
 168.393 +
 168.394 +        ElementKind k = element.getKind();
 168.395 +        if (k == ElementKind.CONSTRUCTOR) {
 168.396 +            value = value | CONSTRUCTOR;
 168.397 +        }
 168.398 +        if (k == ElementKind.METHOD || k == ElementKind.CONSTRUCTOR) {
 168.399 +            value = value | FUNCTION;
 168.400 +        } else if (k == ElementKind.GLOBAL) {
 168.401 +            value = value | GLOBAL;
 168.402 +        }
 168.403 +        if (element.getModifiers().contains(Modifier.STATIC)) {
 168.404 +            value = value | STATIC;
 168.405 +        }
 168.406 +        if (element.getModifiers().contains(Modifier.DEPRECATED)) {
 168.407 +            value = value | DEPRECATED;
 168.408 +        }
 168.409 +        if (element.getModifiers().contains(Modifier.PRIVATE)) {
 168.410 +            value = value | PRIVATE;
 168.411 +        }
 168.412 +
 168.413 +        return value;
 168.414 +    }
 168.415 +
 168.416 +    public boolean isDocumented() {
 168.417 +        return (flags & DOCUMENTED) != 0;
 168.418 +    }
 168.419 +
 168.420 +    public boolean isPublic() {
 168.421 +        return (flags & PRIVATE) == 0;
 168.422 +    }
 168.423 +
 168.424 +    public boolean isPrivate() {
 168.425 +        return (flags & PRIVATE) != 0;
 168.426 +    }
 168.427 +
 168.428 +    public boolean isFunction() {
 168.429 +        return (flags & FUNCTION) != 0;
 168.430 +    }
 168.431 +
 168.432 +    public boolean isStatic() {
 168.433 +        return (flags & STATIC) != 0;
 168.434 +    }
 168.435 +
 168.436 +    public boolean isNoDoc() {
 168.437 +        return (flags & NODOC) != 0;
 168.438 +    }
 168.439 +
 168.440 +    public boolean isFinal() {
 168.441 +        return (flags & FINAL) != 0;
 168.442 +    }
 168.443 +
 168.444 +    public boolean isConstructor() {
 168.445 +        return (flags & CONSTRUCTOR) != 0;
 168.446 +    }
 168.447 +
 168.448 +    public boolean isDeprecated() {
 168.449 +        return (flags & DEPRECATED) != 0;
 168.450 +    }
 168.451 +
 168.452 +    public boolean isDocOnly() {
 168.453 +        return (flags & DOC_ONLY) != 0;
 168.454 +    }
 168.455 +
 168.456 +    public static String decodeFlags(int flags) {
 168.457 +        StringBuilder sb = new StringBuilder();
 168.458 +        if ((flags & DOCUMENTED) != 0) {
 168.459 +            sb.append("|DOCUMENTED");
 168.460 +        }
 168.461 +
 168.462 +        if ((flags & PRIVATE) != 0) {
 168.463 +            sb.append("|PRIVATE");
 168.464 +        }
 168.465 +
 168.466 +        if ((flags & CONSTRUCTOR) != 0) {
 168.467 +            sb.append("|CONSTRUCTOR");
 168.468 +        } else if ((flags & FUNCTION) != 0) {
 168.469 +            sb.append("|FUNCTION");
 168.470 +        } else if ((flags & GLOBAL) != 0) {
 168.471 +            sb.append("|GLOBAL");
 168.472 +        }
 168.473 +
 168.474 +        if ((flags & STATIC) != 0) {
 168.475 +            sb.append("|STATIC");
 168.476 +        }
 168.477 +
 168.478 +        if ((flags & NODOC) != 0) {
 168.479 +            sb.append("|NODOC");
 168.480 +        }
 168.481 +
 168.482 +        if ((flags & DEPRECATED) != 0) {
 168.483 +            sb.append("|DEPRECATED");
 168.484 +        }
 168.485 +
 168.486 +        if ((flags & DOC_ONLY) != 0) {
 168.487 +            sb.append("|DOC_ONLY");
 168.488 +        }
 168.489 +
 168.490 +        if ((flags & FINAL) != 0) {
 168.491 +            sb.append("|FINAL");
 168.492 +        }
 168.493 +
 168.494 +        if (sb.length() > 0) {
 168.495 +            sb.append("|");
 168.496 +        }
 168.497 +        return sb.toString();
 168.498 +    }
 168.499 +
 168.500 +    // For testsuite
 168.501 +    public static int stringToFlags(String string) {
 168.502 +        int flags = 0;
 168.503 +        if (string.contains("|DOCUMENTED")) {
 168.504 +            flags |= DOCUMENTED;
 168.505 +        }
 168.506 +        if (string.contains("|PRIVATE")) {
 168.507 +            flags |= PRIVATE;
 168.508 +        }
 168.509 +        if (string.contains("|DEPRECATED")) {
 168.510 +            flags |= DEPRECATED;
 168.511 +        }
 168.512 +        if (string.contains("|CONSTRUCTOR")) {
 168.513 +            flags |= CONSTRUCTOR;
 168.514 +        }
 168.515 +//        if (string.indexOf("|PROTECTED") != -1) {
 168.516 +//            flags |= PROTECTED;
 168.517 +//        }
 168.518 +//        if (string.indexOf("|TOPLEVEL") != -1) {
 168.519 +//            flags |= TOPLEVEL;
 168.520 +//        }
 168.521 +        if (string.contains("|STATIC")) {
 168.522 +            flags |= STATIC;
 168.523 +        }
 168.524 +        if (string.contains("|NODOC")) {
 168.525 +            flags |= NODOC;
 168.526 +        }
 168.527 +
 168.528 +        return flags;
 168.529 +    }
 168.530 +}
   169.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   169.2 +++ b/python.source/src/org/netbeans/modules/python/source/elements/IndexedMethod.java	Mon Sep 21 13:01:16 2015 +0200
   169.3 @@ -0,0 +1,88 @@
   169.4 +/*
   169.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   169.6 + *
   169.7 + * Copyright 1997-2010 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 + * Contributor(s):
  169.31 + *
  169.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
  169.33 + */
  169.34 +package org.netbeans.modules.python.source.elements;
  169.35 +
  169.36 +import org.netbeans.modules.csl.api.ElementKind;
  169.37 +
  169.38 +/**
  169.39 + *
  169.40 + * @author Tor Norbye
  169.41 + */
  169.42 +public class IndexedMethod extends IndexedElement {
  169.43 +    private String[] params;
  169.44 +
  169.45 +    public IndexedMethod(String name, ElementKind kind, String url, String module, String clz, String signature) {
  169.46 +        super(name, kind, url, module, clz, signature);
  169.47 +    }
  169.48 +
  169.49 +    public String[] getParams() {
  169.50 +        if (params == null) {
  169.51 +            //int argsBegin = name.length()+3;
  169.52 +            int argsBegin = getAttributeSection(IndexedElement.ARG_INDEX);
  169.53 +            int argsEnd = attributes.indexOf(';', argsBegin);
  169.54 +            assert argsEnd != -1 : attributes;
  169.55 +            if (argsEnd > argsBegin) {
  169.56 +                String paramString = attributes.substring(argsBegin, argsEnd);
  169.57 +                params = paramString.split(",");
  169.58 +            } else {
  169.59 +                params = new String[0];
  169.60 +            }
  169.61 +        }
  169.62 +
  169.63 +        return params;
  169.64 +    }
  169.65 +
  169.66 +    @Override
  169.67 +    public boolean equals(Object obj) {
  169.68 +        if (obj == null) {
  169.69 +            return false;
  169.70 +        }
  169.71 +        if (getClass() != obj.getClass()) {
  169.72 +            return false;
  169.73 +        }
  169.74 +        final IndexedMethod other = (IndexedMethod)obj;
  169.75 +        if (this.attributes != other.attributes && (this.attributes == null || !this.attributes.equals(other.attributes))) {
  169.76 +            return false;
  169.77 +        }
  169.78 +        if (this.clz != other.clz && (this.clz == null || !this.clz.equals(other.clz))) {
  169.79 +            return false;
  169.80 +        }
  169.81 +        return true;
  169.82 +    }
  169.83 +
  169.84 +    @Override
  169.85 +    public int hashCode() {
  169.86 +        int hash = 7;
  169.87 +        hash = 53 * hash + (this.attributes != null ? this.attributes.hashCode() : 0);
  169.88 +        hash = 53 * hash + (this.clz != null ? this.clz.hashCode() : 0);
  169.89 +        return hash;
  169.90 +    }
  169.91 +}
   170.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   170.2 +++ b/python.source/src/org/netbeans/modules/python/source/elements/IndexedPackage.java	Mon Sep 21 13:01:16 2015 +0200
   170.3 @@ -0,0 +1,106 @@
   170.4 +/*
   170.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   170.6 + *
   170.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   170.8 + *
   170.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  170.10 + * Other names may be trademarks of their respective owners.
  170.11 + *
  170.12 + * The contents of this file are subject to the terms of either the GNU
  170.13 + * General Public License Version 2 only ("GPL") or the Common
  170.14 + * Development and Distribution License("CDDL") (collectively, the
  170.15 + * "License"). You may not use this file except in compliance with the
  170.16 + * License. You can obtain a copy of the License at
  170.17 + * http://www.netbeans.org/cddl-gplv2.html
  170.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  170.19 + * specific language governing permissions and limitations under the
  170.20 + * License.  When distributing the software, include this License Header
  170.21 + * Notice in each file and include the License file at
  170.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  170.23 + * particular file as subject to the "Classpath" exception as provided
  170.24 + * by Oracle in the GPL Version 2 section of the License file that
  170.25 + * accompanied this code. If applicable, add the following below the
  170.26 + * License Header, with the fields enclosed by brackets [] replaced by
  170.27 + * your own identifying information:
  170.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  170.29 + *
  170.30 + * If you wish your version of this file to be governed by only the CDDL
  170.31 + * or only the GPL Version 2, indicate your decision by adding
  170.32 + * "[Contributor] elects to include this software in this distribution
  170.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  170.34 + * single choice of license, a recipient has the option to distribute
  170.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  170.36 + * to extend the choice of license to its licensees as provided above.
  170.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  170.38 + * Version 2 license, then the option applies only if the new code is
  170.39 + * made subject to such option by the copyright holder.
  170.40 + *
  170.41 + * Contributor(s):
  170.42 + *
  170.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  170.44 + */
  170.45 +package org.netbeans.modules.python.source.elements;
  170.46 +
  170.47 +import java.util.Collections;
  170.48 +import java.util.Set;
  170.49 +import org.netbeans.modules.csl.api.ElementKind;
  170.50 +import org.netbeans.modules.csl.api.Modifier;
  170.51 +
  170.52 +/**
  170.53 + *
  170.54 + * @author Tor Norbye
  170.55 + */
  170.56 +public class IndexedPackage extends IndexedElement {
  170.57 +    private String pkg;
  170.58 +    private boolean hasMore;
  170.59 +
  170.60 +    public IndexedPackage(String name, String pkg, String url, boolean hasMore) {
  170.61 +        super(name, ElementKind.PACKAGE, url, null, null, null);
  170.62 +        this.pkg = pkg;
  170.63 +        this.hasMore = hasMore;
  170.64 +    }
  170.65 +
  170.66 +    @Override
  170.67 +    public Set<Modifier> getModifiers() {
  170.68 +        return Collections.emptySet();
  170.69 +    }
  170.70 +
  170.71 +    public String getPkg() {
  170.72 +        return pkg;
  170.73 +    }
  170.74 +
  170.75 +    public boolean hasMore() {
  170.76 +        return hasMore;
  170.77 +    }
  170.78 +
  170.79 +    @Override
  170.80 +    public boolean equals(Object obj) {
  170.81 +        if (obj == null) {
  170.82 +            return false;
  170.83 +        }
  170.84 +        if (getClass() != obj.getClass()) {
  170.85 +            return false;
  170.86 +        }
  170.87 +        final IndexedPackage other = (IndexedPackage)obj;
  170.88 +
  170.89 +        // Side effect:
  170.90 +        // If any element thinks we have more
  170.91 +        if (other.hasMore) {
  170.92 +            this.hasMore = other.hasMore;
  170.93 +        } else if (this.hasMore) {
  170.94 +            other.hasMore = this.hasMore;
  170.95 +        }
  170.96 +
  170.97 +        if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
  170.98 +            return false;
  170.99 +        }
 170.100 +        return true;
 170.101 +    }
 170.102 +
 170.103 +    @Override
 170.104 +    public int hashCode() {
 170.105 +        int hash = 7;
 170.106 +        hash = 73 * hash + (this.name != null ? this.name.hashCode() : 0);
 170.107 +        return hash;
 170.108 +    }
 170.109 +}
   171.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   171.2 +++ b/python.source/src/org/netbeans/modules/python/source/impl/PythonProjectSourceLevelQuery.java	Mon Sep 21 13:01:16 2015 +0200
   171.3 @@ -0,0 +1,29 @@
   171.4 +/*
   171.5 + * To change this license header, choose License Headers in Project Properties.
   171.6 + * To change this template file, choose Tools | Templates
   171.7 + * and open the template in the editor.
   171.8 + */
   171.9 +package org.netbeans.modules.python.source.impl;
  171.10 +
  171.11 +import org.netbeans.modules.python.source.queries.SourceLevelQueryImplementation;
  171.12 +import org.netbeans.api.project.FileOwnerQuery;
  171.13 +import org.netbeans.api.project.Project;
  171.14 +import org.openide.filesystems.FileObject;
  171.15 +import org.openide.util.lookup.ServiceProvider;
  171.16 +
  171.17 +@ServiceProvider(service = SourceLevelQueryImplementation.class, position = 400)
  171.18 +public class PythonProjectSourceLevelQuery implements SourceLevelQueryImplementation {
  171.19 +
  171.20 +    @Override
  171.21 +    public Result getSourceLevel(FileObject pythonFile) {
  171.22 +        final Project project = FileOwnerQuery.getOwner(pythonFile);
  171.23 +        if (project != null) {
  171.24 +            SourceLevelQueryImplementation impl = project.getLookup().lookup(SourceLevelQueryImplementation.class);
  171.25 +            if (impl != null) {
  171.26 +                return impl.getSourceLevel(pythonFile);
  171.27 +            }
  171.28 +        }
  171.29 +        return null;
  171.30 +    }
  171.31 +
  171.32 +}
   172.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   172.2 +++ b/python.source/src/org/netbeans/modules/python/source/impl/QuerySupportFactory.java	Mon Sep 21 13:01:16 2015 +0200
   172.3 @@ -0,0 +1,80 @@
   172.4 +/*
   172.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   172.6 + *
   172.7 + * Copyright 2015 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 + * If you wish your version of this file to be governed by only the CDDL
  172.31 + * or only the GPL Version 2, indicate your decision by adding
  172.32 + * "[Contributor] elects to include this software in this distribution
  172.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  172.34 + * single choice of license, a recipient has the option to distribute
  172.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  172.36 + * to extend the choice of license to its licensees as provided above.
  172.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  172.38 + * Version 2 license, then the option applies only if the new code is
  172.39 + * made subject to such option by the copyright holder.
  172.40 + *
  172.41 + * Contributor(s):
  172.42 + *
  172.43 + * Portions Copyrighted 2015 Sun Microsystems, Inc.
  172.44 + */
  172.45 +package org.netbeans.modules.python.source.impl;
  172.46 +
  172.47 +import java.io.IOException;
  172.48 +import java.util.Collection;
  172.49 +import java.util.Collections;
  172.50 +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
  172.51 +import org.netbeans.modules.python.source.PythonIndexer;
  172.52 +import org.openide.filesystems.FileObject;
  172.53 +import org.openide.util.Exceptions;
  172.54 +
  172.55 +/**
  172.56 + *
  172.57 + * @author Ralph Ruijs
  172.58 + */
  172.59 +public final class QuerySupportFactory {
  172.60 +
  172.61 +    
  172.62 +    public static QuerySupport getQuerySupport(final Collection<FileObject> roots) {
  172.63 +        try {
  172.64 +            return QuerySupport.forRoots(PythonIndexer.NAME,
  172.65 +                    PythonIndexer.VERSION,
  172.66 +                    roots.toArray(new FileObject[roots.size()]));
  172.67 +        } catch (IOException ex) {
  172.68 +            Exceptions.printStackTrace(ex);
  172.69 +        }
  172.70 +        return null;
  172.71 +    }
  172.72 +    
  172.73 +    public static QuerySupport getQuerySupport(final FileObject source) {
  172.74 +        return getQuerySupport(QuerySupport.findRoots(source,
  172.75 +                null,
  172.76 +                null,
  172.77 +                Collections.<String>emptySet()));
  172.78 +    }
  172.79 +
  172.80 +    private QuerySupportFactory() {
  172.81 +    }
  172.82 +    
  172.83 +}
   173.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   173.2 +++ b/python.source/src/org/netbeans/modules/python/source/layer.xml	Mon Sep 21 13:01:16 2015 +0200
   173.3 @@ -0,0 +1,71 @@
   173.4 +<?xml version="1.0" encoding="UTF-8"?>
   173.5 +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
   173.6 +<filesystem>
   173.7 +    <folder name="CslPlugins">
   173.8 +        <folder name="text">
   173.9 +            <folder name="x-python">
  173.10 +                <file name="structure.instance">
  173.11 +                    <attr name="instanceClass" stringvalue="org.netbeans.modules.python.source.PythonStructureScanner"/>
  173.12 +                </file>
  173.13 +            </folder>
  173.14 +        </folder>
  173.15 +    </folder>
  173.16 +    <folder name="Editors">
  173.17 +        <folder name="text">
  173.18 +            <folder name="x-python">
  173.19 +                <file name="language.instance">
  173.20 +                    <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.source.lexer.PythonTokenId.language"/>
  173.21 +                    <attr name="instanceOf" stringvalue="org.netbeans.api.lexer.Language"/>
  173.22 +                </file>
  173.23 +            </folder>
  173.24 +        </folder>
  173.25 +    </folder>
  173.26 +    <folder name="OptionsDialog">
  173.27 +        <folder name="PreviewExamples">
  173.28 +            <folder name="text">
  173.29 +                <file name="x-python" url="PythonExample.py"/>
  173.30 +            </folder>
  173.31 +        </folder>
  173.32 +        <folder name="Editor">
  173.33 +            <folder name="Formatting">
  173.34 +                <attr name="position" intvalue="0"/>
  173.35 +                <folder name="text">
  173.36 +                    <folder name="x-python">
  173.37 +                        <file name="Imports.instance">
  173.38 +                            <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  173.39 +                            <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.source.ui.FmtImports.getController"/>
  173.40 +                            <attr name="position" intvalue="150"/>
  173.41 +                        </file>
  173.42 +                      <!-- Not yet implemented
  173.43 +                      <file name="TabsAndIndents.instance">
  173.44 +                          <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  173.45 +                          <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.source.ui.FmtTabsIndents.getController"/>
  173.46 +                          <attr name="position" intvalue="100"/>
  173.47 +                      </file>
  173.48 +                      <file name="Alignment.instance">
  173.49 +                          <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  173.50 +                          <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.source.ui.FmtAlignment.getController"/>
  173.51 +                          <attr name="position" intvalue="200"/>
  173.52 +                      </file>
  173.53 +                      <file name="Wrapping.instance">
  173.54 +                          <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  173.55 +                          <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.source.ui.FmtWrapping.getController"/>
  173.56 +                          <attr name="position" intvalue="400"/>
  173.57 +                      </file>
  173.58 +                      <file name="BlankLines.instance">
  173.59 +                          <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  173.60 +                          <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.source.ui.FmtBlankLines.getController"/>
  173.61 +                          <attr name="position" intvalue="500"/>
  173.62 +                      </file>
  173.63 +                      -->
  173.64 +                        <file name="Spaces.instance">
  173.65 +                            <attr name="instanceOf" stringvalue="org.netbeans.modules.options.editor.spi.PreferencesCustomizer$Factory"/>
  173.66 +                            <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.source.ui.FmtSpaces.getController"/>
  173.67 +                            <attr name="position" intvalue="600"/>
  173.68 +                        </file>
  173.69 +                    </folder>
  173.70 +                </folder>
  173.71 +            </folder>
  173.72 +        </folder>
  173.73 +    </folder>
  173.74 +</filesystem>
   174.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   174.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/BuiltinException.java	Mon Sep 21 13:01:16 2015 +0200
   174.3 @@ -0,0 +1,127 @@
   174.4 +/*
   174.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   174.6 + *
   174.7 + * Copyright 2015 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 + * If you wish your version of this file to be governed by only the CDDL
  174.31 + * or only the GPL Version 2, indicate your decision by adding
  174.32 + * "[Contributor] elects to include this software in this distribution
  174.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  174.34 + * single choice of license, a recipient has the option to distribute
  174.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  174.36 + * to extend the choice of license to its licensees as provided above.
  174.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  174.38 + * Version 2 license, then the option applies only if the new code is
  174.39 + * made subject to such option by the copyright holder.
  174.40 + *
  174.41 + * Contributor(s):
  174.42 + *
  174.43 + * Portions Copyrighted 2015 Sun Microsystems, Inc.
  174.44 + */
  174.45 +package org.netbeans.modules.python.editor.lexer;
  174.46 +
  174.47 +import java.util.Arrays;
  174.48 +import java.util.HashSet;
  174.49 +import java.util.Set;
  174.50 +
  174.51 +/**
  174.52 + *
  174.53 + * @author jenselme
  174.54 + */
  174.55 +public class BuiltinException {
  174.56 +    private final static String[] BUILTIN_EXCEPTIONS_ARRAY = {
  174.57 +        "ArithmeticError",
  174.58 +        "AssertionError",
  174.59 +        "AttributeError",
  174.60 +        "BaseException",
  174.61 +        "BlockingIOError",
  174.62 +        "BrokenPipeError",
  174.63 +        "BufferError",
  174.64 +        "BytesWarning",
  174.65 +        "BytesWarningBaseException",
  174.66 +        "ChildProcessError",
  174.67 +        "ConnectionAbortedError",
  174.68 +        "ConnectionError",
  174.69 +        "ConnectionRefusedError",
  174.70 +        "ConnectionResetError",
  174.71 +        "DeprecationWarning",
  174.72 +        "EnvironmentError",
  174.73 +        "EOFError",
  174.74 +        "Exception",
  174.75 +        "FileExistsError",
  174.76 +        "FileNotFoundError",
  174.77 +        "FloatingPointError",
  174.78 +        "FutureWarning",
  174.79 +        "GeneratorExit",
  174.80 +        "ImportError",
  174.81 +        "ImportWarning",
  174.82 +        "IndentationError",
  174.83 +        "IndexError",
  174.84 +        "InterruptedError",
  174.85 +        "IOError",
  174.86 +        "IsADirectoryError",
  174.87 +        "KeyboardInterrupt",
  174.88 +        "KeyError",
  174.89 +        "LookupError",
  174.90 +        "MemoryError",
  174.91 +        "NameError",
  174.92 +        "NotADirectoryError",
  174.93 +        "NotImplementedError",
  174.94 +        "OSError",
  174.95 +        "OverflowError",
  174.96 +        "PendingDeprecationWarning",
  174.97 +        "PermissionError",
  174.98 +        "ProcessLookupError",
  174.99 +        "ReferenceError",
 174.100 +        "ResourceWarning",
 174.101 +        "RuntimeError",
 174.102 +        "RuntimeWarning",
 174.103 +        "StandardError",
 174.104 +        "StopIteration",
 174.105 +        "SyntaxError",
 174.106 +        "SyntaxWarning",
 174.107 +        "SystemError",
 174.108 +        "SystemExit",
 174.109 +        "TabError",
 174.110 +        "TimeoutError",
 174.111 +        "TypeError",
 174.112 +        "UnboundLocalError",
 174.113 +        "UnicodeDecodeError",
 174.114 +        "UnicodeEncodeError",
 174.115 +        "UnicodeError",
 174.116 +        "UnicodeTranslateError",
 174.117 +        "UnicodeWarning",
 174.118 +        "UserWarning",
 174.119 +        "ValueError",
 174.120 +        "VMSError",
 174.121 +        "Warning",
 174.122 +        "WindowsError",
 174.123 +        "ZeroDivisionError"
 174.124 +    };
 174.125 +    private final static Set<String> BUILTIN_EXCEPTIONS = new HashSet<String>(Arrays.asList(BUILTIN_EXCEPTIONS_ARRAY));
 174.126 +
 174.127 +    public static boolean isBuiltInException(CharSequence name) {
 174.128 +        return BUILTIN_EXCEPTIONS.contains(name.toString());
 174.129 +    }
 174.130 +}
   175.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   175.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/Call.java	Mon Sep 21 13:01:16 2015 +0200
   175.3 @@ -0,0 +1,322 @@
   175.4 +/*
   175.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   175.6 + *
   175.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   175.8 + *
   175.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  175.10 + * Other names may be trademarks of their respective owners.
  175.11 + *
  175.12 + * The contents of this file are subject to the terms of either the GNU
  175.13 + * General Public License Version 2 only ("GPL") or the Common
  175.14 + * Development and Distribution License("CDDL") (collectively, the
  175.15 + * "License"). You may not use this file except in compliance with the
  175.16 + * License. You can obtain a copy of the License at
  175.17 + * http://www.netbeans.org/cddl-gplv2.html
  175.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  175.19 + * specific language governing permissions and limitations under the
  175.20 + * License.  When distributing the software, include this License Header
  175.21 + * Notice in each file and include the License file at
  175.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  175.23 + * particular file as subject to the "Classpath" exception as provided
  175.24 + * by Oracle in the GPL Version 2 section of the License file that
  175.25 + * accompanied this code. If applicable, add the following below the
  175.26 + * License Header, with the fields enclosed by brackets [] replaced by
  175.27 + * your own identifying information:
  175.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  175.29 + *
  175.30 + * Contributor(s):
  175.31 + *
  175.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  175.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  175.34 + * Microsystems, Inc. All Rights Reserved.
  175.35 + *
  175.36 + * If you wish your version of this file to be governed by only the CDDL
  175.37 + * or only the GPL Version 2, indicate your decision by adding
  175.38 + * "[Contributor] elects to include this software in this distribution
  175.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  175.40 + * single choice of license, a recipient has the option to distribute
  175.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  175.42 + * to extend the choice of license to its licensees as provided above.
  175.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  175.44 + * Version 2 license, then the option applies only if the new code is
  175.45 + * made subject to such option by the copyright holder.
  175.46 + */
  175.47 +package org.netbeans.modules.python.source.lexer;
  175.48 +
  175.49 +import javax.swing.text.BadLocationException;
  175.50 +import javax.swing.text.Document;
  175.51 +import org.netbeans.api.annotations.common.NonNull;
  175.52 +
  175.53 +import org.netbeans.api.lexer.Token;
  175.54 +import org.netbeans.api.lexer.TokenHierarchy;
  175.55 +import org.netbeans.api.lexer.TokenId;
  175.56 +import org.netbeans.api.lexer.TokenSequence;
  175.57 +import org.netbeans.editor.BaseDocument;
  175.58 +import org.netbeans.editor.Utilities;
  175.59 +import org.openide.util.Exceptions;
  175.60 +
  175.61 +/**
  175.62 + * Class which represents a Call in the source
  175.63 + */
  175.64 +public class Call {
  175.65 +    public static final Call LOCAL = new Call(null, null, false, false);
  175.66 +    public static final Call NONE = new Call(null, null, false, false);
  175.67 +    public static final Call UNKNOWN = new Call(null, null, false, false);
  175.68 +    private final String type;
  175.69 +    private final String lhs;
  175.70 +    private final boolean isStatic;
  175.71 +    private final boolean methodExpected;
  175.72 +
  175.73 +    public Call(String type, String lhs, boolean isStatic, boolean methodExpected) {
  175.74 +        super();
  175.75 +        this.type = type;
  175.76 +        this.lhs = lhs;
  175.77 +        this.methodExpected = methodExpected;
  175.78 +        if (lhs == null) {
  175.79 +            lhs = type;
  175.80 +        }
  175.81 +        this.isStatic = isStatic;
  175.82 +    }
  175.83 +
  175.84 +    public String getType() {
  175.85 +        return type;
  175.86 +    }
  175.87 +
  175.88 +    public String getLhs() {
  175.89 +        return lhs;
  175.90 +    }
  175.91 +
  175.92 +    public boolean isStatic() {
  175.93 +        return isStatic;
  175.94 +    }
  175.95 +
  175.96 +    public boolean isSimpleIdentifier() {
  175.97 +        if (lhs == null) {
  175.98 +            return false;
  175.99 +        }
 175.100 +        // TODO - replace with the new PythonUtil validations
 175.101 +        for (int i = 0, n = lhs.length(); i < n; i++) {
 175.102 +            char c = lhs.charAt(i);
 175.103 +            if (Character.isJavaIdentifierPart(c)) {
 175.104 +                continue;
 175.105 +            }
 175.106 +            return false;
 175.107 +        }
 175.108 +        return true;
 175.109 +    }
 175.110 +
 175.111 +    @Override
 175.112 +    public String toString() {
 175.113 +        if (this == LOCAL) {
 175.114 +            return "LOCAL";
 175.115 +        } else if (this == NONE) {
 175.116 +            return "NONE";
 175.117 +        } else if (this == UNKNOWN) {
 175.118 +            return "UNKNOWN";
 175.119 +        } else {
 175.120 +            return "Call(" + type + "," + lhs + "," + isStatic + ")";
 175.121 +        }
 175.122 +    }
 175.123 +
 175.124 +    /** foo.| or foo.b|  -> we're expecting a method call. For Foo:: we don't know. */
 175.125 +    public boolean isMethodExpected() {
 175.126 +        return this.methodExpected;
 175.127 +    }
 175.128 +
 175.129 +    /**
 175.130 +     * Determine whether the given offset corresponds to a method call on another
 175.131 +     * object. This would happen in these cases:
 175.132 +     *    Foo::|, Foo::Bar::|, Foo.|, Foo.x|, foo.|, foo.x|
 175.133 +     * and not here:
 175.134 +     *   |, Foo|, foo|
 175.135 +     * The method returns the left hand side token, if any, such as "Foo", Foo::Bar",
 175.136 +     * and "foo". If not, it will return null.
 175.137 +     * Note that "self" and "super" are possible return values for the lhs, which mean
 175.138 +     * that you don't have a call on another object. Clients of this method should
 175.139 +     * handle that return value properly (I could return null here, but clients probably
 175.140 +     * want to distinguish self and super in this case so it's useful to return the info.)
 175.141 +     *
 175.142 +     * This method will also try to be smart such that if you have a block or array
 175.143 +     * call, it will return the relevant classnames (e.g. for [1,2].x| it returns "Array").
 175.144 +     */
 175.145 +    @SuppressWarnings("unchecked")
 175.146 +    @NonNull
 175.147 +    public static Call getCallType(BaseDocument doc, TokenHierarchy<Document> th, int offset) {
 175.148 +        TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(th, offset);
 175.149 +
 175.150 +        if (ts == null) {
 175.151 +            return Call.NONE;
 175.152 +        }
 175.153 +
 175.154 +        ts.move(offset);
 175.155 +
 175.156 +        boolean methodExpected = false;
 175.157 +
 175.158 +        if (!ts.moveNext() && !ts.movePrevious()) {
 175.159 +            return Call.NONE;
 175.160 +        }
 175.161 +
 175.162 +        if (ts.offset() == offset) {
 175.163 +            // We're looking at the offset to the RIGHT of the caret
 175.164 +            // position, which could be whitespace, e.g.
 175.165 +            //  "foo.x| " <-- looking at the whitespace
 175.166 +            ts.movePrevious();
 175.167 +        }
 175.168 +
 175.169 +        Token<? extends PythonTokenId> token = ts.token();
 175.170 +
 175.171 +        if (token != null) {
 175.172 +            TokenId id = token.id();
 175.173 +
 175.174 +            if (id == PythonTokenId.WHITESPACE) {
 175.175 +                return Call.LOCAL;
 175.176 +            }
 175.177 +
 175.178 +            // See if we're in the identifier - "x" in "foo.x"
 175.179 +            // I could also be a keyword in case the prefix happens to currently
 175.180 +            // match a keyword, such as "next"
 175.181 +            // However, if we're at the end of the document, x. will lex . as an
 175.182 +            // identifier of text ".", so handle this case specially
 175.183 +            if ((id == PythonTokenId.IDENTIFIER)/* || (id == PythonTokenId.CONSTANT)*/ ||
 175.184 +                    id.primaryCategory().equals("keyword")) {
 175.185 +                String tokenText = token.text().toString();
 175.186 +
 175.187 +                if (".".equals(tokenText)) {
 175.188 +                    // Special case - continue - we'll handle this part next
 175.189 +                    methodExpected = true;
 175.190 +                } else {
 175.191 +                    methodExpected = true;
 175.192 +
 175.193 +                    if (Character.isUpperCase(tokenText.charAt(0))) {
 175.194 +                        methodExpected = false;
 175.195 +                    }
 175.196 +
 175.197 +                    if (!ts.movePrevious()) {
 175.198 +                        return Call.LOCAL;
 175.199 +                    }
 175.200 +                }
 175.201 +
 175.202 +                token = ts.token();
 175.203 +                id = token.id();
 175.204 +            }
 175.205 +
 175.206 +            // If we're not in the identifier we need to be in the dot (in "foo.x").
 175.207 +            // I can't just check for tokens DOT and COLON3 because for unparseable source
 175.208 +            // (like "File.|") the lexer will return the "." as an identifier.
 175.209 +            if (id == PythonTokenId.DOT) {
 175.210 +                methodExpected = true;
 175.211 +            } else if (id == PythonTokenId.IDENTIFIER) {
 175.212 +                String t = token.text().toString();
 175.213 +
 175.214 +                if (t.equals(".")) {
 175.215 +                    methodExpected = true;
 175.216 +                } else {
 175.217 +                    return Call.LOCAL;
 175.218 +                }
 175.219 +            } else {
 175.220 +                return Call.LOCAL;
 175.221 +            }
 175.222 +
 175.223 +            int lastSeparatorOffset = ts.offset();
 175.224 +            int beginOffset = lastSeparatorOffset;
 175.225 +            int lineStart = 0;
 175.226 +
 175.227 +            try {
 175.228 +                if (offset > doc.getLength()) {
 175.229 +                    offset = doc.getLength();
 175.230 +                }
 175.231 +
 175.232 +                lineStart = Utilities.getRowStart(doc, offset);
 175.233 +            } catch (BadLocationException ble) {
 175.234 +                Exceptions.printStackTrace(ble);
 175.235 +            }
 175.236 +
 175.237 +            // Find the beginning of the expression. We'll go past keywords, identifiers
 175.238 +            // and dots or double-colons
 175.239 +            while (ts.movePrevious()) {
 175.240 +                // If we get to the previous line we're done
 175.241 +                if (ts.offset() < lineStart) {
 175.242 +                    break;
 175.243 +                }
 175.244 +
 175.245 +                token = ts.token();
 175.246 +                id = token.id();
 175.247 +
 175.248 +                String tokenText = null;
 175.249 +                if (id == PythonTokenId.ANY_KEYWORD || id == PythonTokenId.IDENTIFIER) {
 175.250 +                    tokenText = token.text().toString();
 175.251 +                }
 175.252 +
 175.253 +                if (id == PythonTokenId.WHITESPACE) {
 175.254 +                    break;
 175.255 +                } else if (id == PythonTokenId.RBRACKET) {
 175.256 +                    return new Call("ListType", null, false, methodExpected);
 175.257 +                } else if (id == PythonTokenId.RBRACE) {
 175.258 +                    return new Call("DictType", null, false, methodExpected);
 175.259 +                } else if ((id == PythonTokenId.STRING_END)/* || (id == PythonTokenId.QUOTED_STRING_END)*/) {
 175.260 +                    return new Call("StringType", null, false, methodExpected);
 175.261 +                } else if ((id == PythonTokenId.IDENTIFIER) && "True".equals(tokenText)) { // NOI18N
 175.262 +                    return new Call("BooleanType", null, false, methodExpected);
 175.263 +                } else if ((id == PythonTokenId.IDENTIFIER) && "False".equals(tokenText)) { // NOI18N
 175.264 +                    return new Call("BooleanType", null, false, methodExpected);
 175.265 +                } else if (((id == PythonTokenId.IDENTIFIER)) ||
 175.266 +                        id.primaryCategory().equals("keyword") || (id == PythonTokenId.DOT)) {
 175.267 +
 175.268 +                    // We're building up a potential expression such as "Test::Unit" so continue looking
 175.269 +                    beginOffset = ts.offset();
 175.270 +
 175.271 +                    continue;
 175.272 +                } else if ((id == PythonTokenId.LPAREN) || (id == PythonTokenId.LBRACE) ||
 175.273 +                        (id == PythonTokenId.LBRACKET)) {
 175.274 +                    // It's an expression for example within a parenthesis, e.g.
 175.275 +                    // yield(^File.join())
 175.276 +                    // in this case we can do top level completion
 175.277 +                    // TODO: There are probably more valid contexts here
 175.278 +                    break;
 175.279 +                } else if (id == PythonTokenId.ANY_OPERATOR) {
 175.280 +                    break;
 175.281 +                } else {
 175.282 +                    // Something else - such as "getFoo().x|" - at this point we don't know the type
 175.283 +                    // so we'll just return unknown
 175.284 +                    return Call.UNKNOWN;
 175.285 +                }
 175.286 +            }
 175.287 +
 175.288 +            if (beginOffset < lastSeparatorOffset) {
 175.289 +                try {
 175.290 +                    String lhs = doc.getText(beginOffset, lastSeparatorOffset - beginOffset);
 175.291 +
 175.292 +                    if (lhs.equals("super") || lhs.equals("self")) { // NOI18N
 175.293 +
 175.294 +                        return new Call(lhs, lhs, false, true);
 175.295 +                    } else if (Character.isUpperCase(lhs.charAt(0))) {
 175.296 +
 175.297 +//                        // Detect constructor calls of the form String.new.^
 175.298 +//                        if (lhs.endsWith(".new")) { // NOI18N
 175.299 +//                            // See if it looks like a type prior to that
 175.300 +//                            String type = lhs.substring(0, lhs.length()-4); // 4=".new".length()
 175.301 +//                            if (PythonUtils.isValidPythonModuleName(type)) {
 175.302 +//                                return new Call(type, lhs, false, methodExpected);
 175.303 +//                            }
 175.304 +//                        }
 175.305 +
 175.306 +                        String type = null;
 175.307 +//                        if (PythonUtils.isValidPythonModuleName(lhs)) {
 175.308 +                        type = lhs;
 175.309 +//                        }
 175.310 +
 175.311 +                        return new Call(type, lhs, true, methodExpected);
 175.312 +                    } else {
 175.313 +                        return new Call(null, lhs, false, methodExpected);
 175.314 +                    }
 175.315 +                } catch (BadLocationException ble) {
 175.316 +                    Exceptions.printStackTrace(ble);
 175.317 +                }
 175.318 +            } else {
 175.319 +                return Call.UNKNOWN;
 175.320 +            }
 175.321 +        }
 175.322 +
 175.323 +        return Call.LOCAL;
 175.324 +    }
 175.325 +}
   176.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   176.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/PythonCommentLexer.java	Mon Sep 21 13:01:16 2015 +0200
   176.3 @@ -0,0 +1,229 @@
   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 comments.
  176.57 + *
  176.58 + * Highlights TODO items and certain keywords (like @-param and @-type (without -)).
  176.59 + *
  176.60 + * @author Tor Norbye
  176.61 + */
  176.62 +public class PythonCommentLexer implements Lexer<PythonCommentTokenId> {
  176.63 +    private static final int EOF = LexerInput.EOF;
  176.64 +    private final LexerInput input;
  176.65 +    private final TokenFactory<PythonCommentTokenId> tokenFactory;
  176.66 +    private final boolean substituting;
  176.67 +
  176.68 +    private static enum State {
  176.69 +        INIT,
  176.70 +        /** We've just seen @type */
  176.71 +        SEEN_TYPE_KEY,
  176.72 +        /** We've just seen @type< > */
  176.73 +        SEEN_TYPE_WS,
  176.74 +        /** We've just seen @type <varname> */
  176.75 +        SEEN_NAME,
  176.76 +        /** We've just seen @type varname< > */
  176.77 +        SEEN_NAME_WS
  176.78 +    };
  176.79 +    private State state;
  176.80 +
  176.81 +    /**
  176.82 +     * A Lexer for Python strings
  176.83 +     * @param substituting If true, handle substitution rules for double quoted strings, otherwise
  176.84 +     *    single quoted strings.
  176.85 +     */
  176.86 +    public PythonCommentLexer(LexerRestartInfo<PythonCommentTokenId> info, boolean substituting) {
  176.87 +        this.input = info.input();
  176.88 +        this.tokenFactory = info.tokenFactory();
  176.89 +        this.substituting = substituting;
  176.90 +        state = (State)info.state();
  176.91 +        if (state == null) {
  176.92 +            state = State.INIT;
  176.93 +        }
  176.94 +    }
  176.95 +
  176.96 +    @Override
  176.97 +    public Object state() {
  176.98 +        return state;
  176.99 +    }
 176.100 +
 176.101 +    @Override
 176.102 +    public Token<PythonCommentTokenId> nextToken() {
 176.103 +        switch (state) {
 176.104 +        case SEEN_NAME:
 176.105 +        case SEEN_TYPE_KEY:
 176.106 +            while (true) {
 176.107 +                int ch = input.read();
 176.108 +                if (ch == ':' && state == State.SEEN_NAME && input.readLength() == 1) {
 176.109 +                    continue;
 176.110 +                }
 176.111 +                if (ch == EOF || !Character.isWhitespace(ch)) {
 176.112 +                    if (ch != EOF) {
 176.113 +                        input.backup(1);
 176.114 +                    }
 176.115 +                    if (input.readLength() > 0) {
 176.116 +                        state = (state == State.SEEN_TYPE_KEY) ? State.SEEN_TYPE_WS : State.SEEN_NAME_WS;
 176.117 +                        return tokenFactory.createToken(PythonCommentTokenId.SEPARATOR,
 176.118 +                                input.readLength());
 176.119 +                    } else {
 176.120 +                        return null;
 176.121 +                    }
 176.122 +                }
 176.123 +            }
 176.124 +
 176.125 +        case SEEN_NAME_WS:
 176.126 +        case SEEN_TYPE_WS:
 176.127 +            while (true) {
 176.128 +                int ch = input.read();
 176.129 +                if (ch == EOF || Character.isWhitespace(ch) || ch == ':') {
 176.130 +                    if (ch != EOF) {
 176.131 +                        input.backup(1);
 176.132 +                    }
 176.133 +                    if (input.readLength() > 0) {
 176.134 +                        State nextState;
 176.135 +                        PythonCommentTokenId id;
 176.136 +                        if (state == State.SEEN_TYPE_WS) {
 176.137 +                            nextState = State.SEEN_NAME;
 176.138 +                            id = PythonCommentTokenId.VARNAME;
 176.139 +                        } else {
 176.140 +                            nextState = State.INIT;
 176.141 +                            id = PythonCommentTokenId.TYPE;
 176.142 +                        }
 176.143 +                        state = nextState;
 176.144 +                        return tokenFactory.createToken(id, input.readLength());
 176.145 +                    } else if (ch == EOF) {
 176.146 +                        return null;
 176.147 +                    } else {
 176.148 +                        // Error - : without an actual var name
 176.149 +                        state = State.INIT;
 176.150 +                        return nextToken(); // recurse
 176.151 +                    }
 176.152 +                }
 176.153 +            }
 176.154 +        default:
 176.155 +        case INIT: {
 176.156 +
 176.157 +            int last = EOF;
 176.158 +            while (true) {
 176.159 +                int ch = input.read();
 176.160 +
 176.161 +                switch (ch) {
 176.162 +                case EOF:
 176.163 +                    if (input.readLength() > 0) {
 176.164 +                        return tokenFactory.createToken(PythonCommentTokenId.TEXT,
 176.165 +                                input.readLength());
 176.166 +                    } else {
 176.167 +                        return null;
 176.168 +                    }
 176.169 +
 176.170 +                case '@': {
 176.171 +                    // Is it "@type"
 176.172 +                    int initialReadLength = input.readLength();
 176.173 +                    if (input.read() == 't' && input.read() == 'y' && input.read() == 'p' && input.read() == 'e') {
 176.174 +                        if (input.readLength() > 5) {
 176.175 +                            input.backup(5);
 176.176 +                            // Finish this token such that we can do a dedicated token for the @type item.
 176.177 +                            return tokenFactory.createToken(PythonCommentTokenId.TEXT,
 176.178 +                                    input.readLength());
 176.179 +                        }
 176.180 +                        state = State.SEEN_TYPE_KEY;
 176.181 +                        return tokenFactory.createToken(PythonCommentTokenId.TYPEKEY,
 176.182 +                                input.readLength());
 176.183 +                    }
 176.184 +                    if (input.readLength() > initialReadLength) {
 176.185 +                        input.backup(input.readLength() - initialReadLength);
 176.186 +                    } else {
 176.187 +                        return tokenFactory.createToken(PythonCommentTokenId.TEXT,
 176.188 +                                input.readLength());
 176.189 +                    }
 176.190 +                }
 176.191 +                break;
 176.192 +
 176.193 +                case 'T': {
 176.194 +                    if (last == EOF || !Character.isLetter(last)) {
 176.195 +                        // Is it "\wTODO\w" ?
 176.196 +                        int initialReadLength = input.readLength();
 176.197 +                        if (input.read() == 'O' && input.read() == 'D' && input.read() == 'O') {
 176.198 +                            int peek = input.read();
 176.199 +                            input.backup(1);
 176.200 +                            if (peek == EOF || !Character.isLetter(peek)) {
 176.201 +                                if (input.readLength() > 4) {
 176.202 +                                    input.backup(4);
 176.203 +                                    // Finish this token such that we can do a dedicated token for the @type item.
 176.204 +                                    return tokenFactory.createToken(PythonCommentTokenId.TEXT,
 176.205 +                                            input.readLength());
 176.206 +                                }
 176.207 +                                return tokenFactory.createToken(PythonCommentTokenId.TODO,
 176.208 +                                        input.readLength());
 176.209 +                            }
 176.210 +                        }
 176.211 +                        if (input.readLength() > initialReadLength) {
 176.212 +                            input.backup(input.readLength() - initialReadLength);
 176.213 +                        } else {
 176.214 +                            return tokenFactory.createToken(PythonCommentTokenId.TEXT,
 176.215 +                                    input.readLength());
 176.216 +                        }
 176.217 +                    }
 176.218 +                }
 176.219 +                break;
 176.220 +                }
 176.221 +
 176.222 +                last = ch;
 176.223 +            }
 176.224 +
 176.225 +        }
 176.226 +        }
 176.227 +    }
 176.228 +
 176.229 +    @Override
 176.230 +    public void release() {
 176.231 +    }
 176.232 +}
   177.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   177.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/PythonCommentTokenId.java	Mon Sep 21 13:01:16 2015 +0200
   177.3 @@ -0,0 +1,120 @@
   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.spi.lexer.LanguageEmbedding;
  177.59 +import org.netbeans.spi.lexer.LanguageHierarchy;
  177.60 +import org.netbeans.spi.lexer.Lexer;
  177.61 +import org.netbeans.spi.lexer.LexerRestartInfo;
  177.62 +
  177.63 +/**
  177.64 + *
  177.65 + * @author Tor Norbye
  177.66 + */
  177.67 +public enum PythonCommentTokenId implements TokenId {
  177.68 +    TEXT("comment"),
  177.69 +    KEYWORD("comment"),
  177.70 +    SEPARATOR("comment"),
  177.71 +    TYPEKEY("comment"),
  177.72 +    VARNAME("comment"),
  177.73 +    TYPE("comment"),
  177.74 +    TODO("comment");
  177.75 +    private final String primaryCategory;
  177.76 +
  177.77 +    PythonCommentTokenId() {
  177.78 +        this(null);
  177.79 +    }
  177.80 +
  177.81 +    PythonCommentTokenId(String primaryCategory) {
  177.82 +        this.primaryCategory = primaryCategory;
  177.83 +    }
  177.84 +
  177.85 +    @Override
  177.86 +    public String primaryCategory() {
  177.87 +        return primaryCategory;
  177.88 +    }
  177.89 +    public static final Language<PythonCommentTokenId> language =
  177.90 +            new LanguageHierarchy<PythonCommentTokenId>() {
  177.91 +                @Override
  177.92 +                protected Collection<PythonCommentTokenId> createTokenIds() {
  177.93 +                    return EnumSet.allOf(PythonCommentTokenId.class);
  177.94 +                }
  177.95 +
  177.96 +                @Override
  177.97 +                protected Map<String, Collection<PythonCommentTokenId>> createTokenCategories() {
  177.98 +                    return null; // no extra categories
  177.99 +                }
 177.100 +
 177.101 +                @Override
 177.102 +                protected Lexer<PythonCommentTokenId> createLexer(
 177.103 +                        LexerRestartInfo<PythonCommentTokenId> info) {
 177.104 +                    return new PythonCommentLexer(info, true);
 177.105 +                }
 177.106 +
 177.107 +                @Override
 177.108 +                protected LanguageEmbedding<?> embedding(
 177.109 +                        Token<PythonCommentTokenId> token, LanguagePath languagePath,
 177.110 +                        InputAttributes inputAttributes) {
 177.111 +                    return null; // No embedding
 177.112 +                }
 177.113 +
 177.114 +                @Override
 177.115 +                public String mimeType() {
 177.116 +                    return "text/x-python-comment"; // NOI18N
 177.117 +                }
 177.118 +            }.language();
 177.119 +
 177.120 +    public static Language<PythonCommentTokenId> language() {
 177.121 +        return language;
 177.122 +    }
 177.123 +}
   178.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   178.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/PythonLexer.java	Mon Sep 21 13:01:16 2015 +0200
   178.3 @@ -0,0 +1,1158 @@
   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 org.netbeans.api.lexer.Token;
  178.50 +import org.netbeans.api.lexer.TokenUtilities;
  178.51 +import org.netbeans.spi.lexer.Lexer;
  178.52 +import org.netbeans.spi.lexer.LexerInput;
  178.53 +import org.netbeans.spi.lexer.LexerRestartInfo;
  178.54 +import org.netbeans.spi.lexer.TokenFactory;
  178.55 +
  178.56 +/**
  178.57 + * Lexer for Python.
  178.58 + *
  178.59 + * This is a hand written lexer for Python which recognizes the logical token types
  178.60 + * we care about within the IDE support.
  178.61 + *
  178.62 + * Initially, we were using Jython's lexer directly here. However, that had some
  178.63 + * problems:
  178.64 + *
  178.65 + * <ul>
  178.66 + *   <li>
  178.67 + *     In the IDE, we have to support incremental parsing. Not only is this a must
  178.68 + *     from a user performance perspective (typing a keystroke near the bottom of a
  178.69 + *     2,000 line file shouldn't cause complete re-lexing of the entire document), but
  178.70 + *     the NetBeans APIs require it; they restart the lexer on the nearest token
  178.71 + *     boundary.
  178.72 + *     ANTLR doesn't support incremental lexing. I looked into what it would take
  178.73 + *     to patch it to do so (as I have done for JRuby in the Ruby support), but
  178.74 + *     it (a) wasn't trivial, and (b) would require a LOT of data to be stored for
  178.75 + *     every token boundary.
  178.76 + *   </li>
  178.77 + *   <li>
  178.78 + *     Similarly, we need to put our lexer on top of a LexerInput, and it is not
  178.79 + *     particularly compatible with the way ANTLR handles input. We had an
  178.80 + *     adapter class for this which was jumping through various hoops to expose
  178.81 + *     the LexerInput as ANTLR input. However, it had some severe problems with
  178.82 + *     large inputs.
  178.83 + *   </li>
  178.84 + *   <li>
  178.85 + *     We need slightly different token divisions. For example, for matching bracket
  178.86 + *     purposes, we'd like to have strings split into string delimiters and the
  178.87 + *     string contents. Similarly, Jython did some things like coalesce all whitespace
  178.88 + *     around a newline into that newline token which causes some complications
  178.89 + *     for our token analysis.
  178.90 + *   </li>
  178.91 + *   <li>
  178.92 + *     For Ruby, I decided to use the JRuby lexer because JRuby lexing is very
  178.93 + *     difficult. They have a huge complicated class to do the lexing - and there's
  178.94 + *     no Ruby language spec.  Python on the other hand seems to have a very simple
  178.95 + *     lexing model, and a clear spec and grammar, so I don't feel worried that
  178.96 + *     our custom Python lexer is going to have a lot of corner case bugs.
  178.97 + *   </li>
  178.98 + * </ul>
  178.99 + *
 178.100 + * @author Tor Norbye
 178.101 + */
 178.102 +public final class PythonLexer implements Lexer<PythonTokenId> {
 178.103 +    public static final String COMMENT_CAT = "comment";
 178.104 +    public static final String KEYWORD_CAT = "keyword"; // NOI18N
 178.105 +    public static final String STRING_CAT = "string"; // NOI18N
 178.106 +    public static final String WHITESPACE_CAT = "whitespace"; // NOI18N
 178.107 +    public static final String OPERATOR_CAT = "operator"; // NOI18N
 178.108 +    public static final String SEPARATOR_CAT = "separator"; // NOI18N
 178.109 +    public static final String ERROR_CAT = "error"; // NOI18N
 178.110 +    public static final String NUMBER_CAT = "number"; // NOI18N
 178.111 +    public static final String IDENTIFIER_CAT = "identifier"; // NOI18N
 178.112 +    private static final int EOF = LexerInput.EOF;
 178.113 +    private final LexerInput input;
 178.114 +    private final TokenFactory<PythonTokenId> tokenFactory;
 178.115 +
 178.116 +    // Lexer state - preserved per token boundary
 178.117 +    private enum State {
 178.118 +        /** Normal state, same state as on entry into a Python file */
 178.119 +        INIT,
 178.120 +        /** We've processed the beginning string delimiter of a double-quoted short string */
 178.121 +        BEGIN_SHORTSTRING_DOUBLE,
 178.122 +        /** We've processed the beginning string delimiter of a single-quoted short string */
 178.123 +        BEGIN_SHORTSTRING_SINGLE,
 178.124 +        /** We've processed the beginning string delimiter of a double-quoted long string */
 178.125 +        BEGIN_LONGSTRING_DOUBLE,
 178.126 +        /** We've processed the beginning string delimiter of a singl-quoted long string */
 178.127 +        BEGIN_LONGSTRING_SINGLE,
 178.128 +        /** We've processed the string content in a double-quoted short string */
 178.129 +        END_SHORTSTRING_DOUBLE,
 178.130 +        /** We've processed the string content in a single-quoted short string */
 178.131 +        END_SHORTSTRING_SINGLE,
 178.132 +        /** We've processed the string content in a double-quoted long string */
 178.133 +        END_LONGSTRING_DOUBLE,
 178.134 +        /** We've processed the string content in a single-quoted long string */
 178.135 +        END_LONGSTRING_SINGLE,
 178.136 +    };
 178.137 +    private State state;
 178.138 +
 178.139 +    public PythonLexer(LexerRestartInfo<PythonTokenId> info) {
 178.140 +        this.input = info.input();
 178.141 +        this.tokenFactory = info.tokenFactory();
 178.142 +
 178.143 +        state = (State)info.state();
 178.144 +        if (state == null) {
 178.145 +            state = State.INIT;
 178.146 +        }
 178.147 +    }
 178.148 +
 178.149 +    @Override
 178.150 +    public Object state() {
 178.151 +        return state;
 178.152 +    }
 178.153 +
 178.154 +    private Token<PythonTokenId> createToken(PythonTokenId id, int tokenLength) {
 178.155 +        String fixedText = id.fixedText();
 178.156 +        return (fixedText != null) ? tokenFactory.getFlyweightToken(id, fixedText)
 178.157 +                : tokenFactory.createToken(id, tokenLength);
 178.158 +    }
 178.159 +
 178.160 +    @SuppressWarnings("fallthrough")
 178.161 +    @Override
 178.162 +    public Token<PythonTokenId> nextToken() {
 178.163 +        switch (state) {
 178.164 +        case INIT: {
 178.165 +            int ch = input.read();
 178.166 +            switch (ch) {
 178.167 +            case EOF:
 178.168 +                return null;
 178.169 +
 178.170 +            // Newline
 178.171 +            case '\n':
 178.172 +                assert input.readLength() == 1;
 178.173 +                return createToken(PythonTokenId.NEWLINE, 1);
 178.174 +
 178.175 +            // Whitespace
 178.176 +            case ' ':
 178.177 +            case '\t': {
 178.178 +                for (; ch != EOF; ch = input.read()) {
 178.179 +                    if (ch != ' ' && ch != '\t') {
 178.180 +                        break;
 178.181 +                    }
 178.182 +                }
 178.183 +                input.backup(1);
 178.184 +                return createToken(PythonTokenId.WHITESPACE, input.readLength());
 178.185 +            }
 178.186 +
 178.187 +            // Comment
 178.188 +            case '#': {
 178.189 +                ch = input.read();
 178.190 +                while (ch != EOF && ch != '\n') {
 178.191 +                    ch = input.read();
 178.192 +                }
 178.193 +                input.backup(1);
 178.194 +                return createToken(PythonTokenId.COMMENT, input.readLength());
 178.195 +            }
 178.196 +
 178.197 +            case '.': {
 178.198 +                assert input.readLength() == 1;
 178.199 +                int peek = input.read();
 178.200 +                input.backup(1);
 178.201 +                if (!Character.isDigit(peek)) {
 178.202 +                    return createToken(PythonTokenId.DOT, 1);
 178.203 +                } // else: Fallthrough to process the number!!
 178.204 +            } // FALLTHROUGH
 178.205 +            // FALLTHROUGH!!!!
 178.206 +
 178.207 +            // Number (integer, float, complex)
 178.208 +            case '0':
 178.209 +            case '1':
 178.210 +            case '2':
 178.211 +            case '3':
 178.212 +            case '4':
 178.213 +            case '5':
 178.214 +            case '6':
 178.215 +            case '7':
 178.216 +            case '8':
 178.217 +            case '9': {
 178.218 +                if (ch == '0') {
 178.219 +                    int peek = input.read();
 178.220 +                    if (peek == 'x' || peek == 'X') {
 178.221 +                        // Hex
 178.222 +                        ch = input.read();
 178.223 +                        while (ch != EOF) {
 178.224 +                            if (!(Character.isDigit(ch) ||
 178.225 +                                    (ch >= 'a' && ch <= 'f') ||
 178.226 +                                    (ch >= 'A' && ch <= 'F'))) {
 178.227 +                                break;
 178.228 +                            }
 178.229 +                            ch = input.read();
 178.230 +                        }
 178.231 +                        if (ch != 'l' && (ch != 'L')) {
 178.232 +                            input.backup(1);
 178.233 +                        }
 178.234 +                        return createToken(PythonTokenId.INT_LITERAL, input.readLength());
 178.235 +                    }
 178.236 +                    input.backup(1);
 178.237 +                }
 178.238 +                boolean isFloat = false;
 178.239 +                digitLoop:
 178.240 +                for (; ch != EOF; ch = input.read()) {
 178.241 +                    switch (ch) {
 178.242 +                    case '0':
 178.243 +                    case '1':
 178.244 +                    case '2':
 178.245 +                    case '3':
 178.246 +                    case '4':
 178.247 +                    case '5':
 178.248 +                    case '6':
 178.249 +                    case '7':
 178.250 +                    case '8':
 178.251 +                    case '9':
 178.252 +                        continue;
 178.253 +                    case '.':
 178.254 +                        isFloat = true;
 178.255 +                        continue;
 178.256 +                    case 'e': // Exponent
 178.257 +                    case 'E': {
 178.258 +                        int peek = input.read();
 178.259 +                        if (peek != '+' && peek != '-') {
 178.260 +                            input.backup(1);
 178.261 +                        }
 178.262 +                        ch = input.read();
 178.263 +                        while (ch != EOF) {
 178.264 +                            if (!Character.isDigit(ch)) {
 178.265 +                                break;
 178.266 +                            }
 178.267 +                            ch = input.read();
 178.268 +                        }
 178.269 +                        if (ch != 'j' && ch != 'J') {
 178.270 +                            input.backup(1);
 178.271 +                        }
 178.272 +                        return createToken(PythonTokenId.FLOAT_LITERAL, input.readLength());
 178.273 +                    }
 178.274 +                    case 'j': // Imaginary
 178.275 +                    case 'J':
 178.276 +                        isFloat = true;
 178.277 +                        break digitLoop;
 178.278 +                    case 'l': // Long
 178.279 +                    case 'L':
 178.280 +                        break digitLoop;
 178.281 +                    case EOF:
 178.282 +                    default:
 178.283 +                        input.backup(1);
 178.284 +                        break digitLoop;
 178.285 +
 178.286 +                    }
 178.287 +                }
 178.288 +
 178.289 +                return createToken(isFloat ? PythonTokenId.FLOAT_LITERAL : PythonTokenId.INT_LITERAL, input.readLength());
 178.290 +            }
 178.291 +
 178.292 +            // Operators and delimiters
 178.293 +            case '+': // +,+=
 178.294 +                if (input.read() != '=') {
 178.295 +                    input.backup(1);
 178.296 +                }
 178.297 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 178.298 +            case '-': // -,-=
 178.299 +                if (input.read() != '=') {
 178.300 +                    input.backup(1);
 178.301 +                }
 178.302 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 178.303 +            case '*': { // *,**,*=, **=
 178.304 +                int peek = input.read();
 178.305 +                if (peek == '=') {
 178.306 +                    // No need to back up, include it
 178.307 +                } else if (peek == '*') {
 178.308 +                    peek = input.read();
 178.309 +                    if (peek != '=') {
 178.310 +                        input.backup(1);
 178.311 +                    }
 178.312 +                } else {
 178.313 +                    input.backup(1);
 178.314 +                }
 178.315 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 178.316 +            }
 178.317 +            case '/': {
 178.318 +                // Look for /,//, /=, //=
 178.319 +                int peek = input.read();
 178.320 +                if (peek == '=') {
 178.321 +                    // No need to back up, include it
 178.322 +                } else if (peek == '/') {
 178.323 +                    peek = input.read();
 178.324 +                    if (peek != '=') {
 178.325 +                        input.backup(1);
 178.326 +                    }
 178.327 +                } else {
 178.328 +                    input.backup(1);
 178.329 +                }
 178.330 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 178.331 +            }
 178.332 +            case '%': { // Look for %,   %=
 178.333 +                if (input.read() != '=') {
 178.334 +                    input.backup(1);
 178.335 +                }
 178.336 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 178.337 +            }
 178.338 +            case '<': {
 178.339 +                // Look for <, <<, <=, <>, <<=
 178.340 +                int peek = input.read();
 178.341 +                if (peek == '=') {
 178.342 +                    // No need to back up, include it
 178.343 +                } else if (peek == '<') {
 178.344 +                    peek = input.read();
 178.345 +                    if (peek != '=') {
 178.346 +                        input.backup(1);
 178.347 +                    }
 178.348 +                } else if (peek != '>') {
 178.349 +                    input.backup(1);
 178.350 +                }
 178.351 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 178.352 +            }
 178.353 +            case '>': {
 178.354 +                // Look for >, >>, >=, >>=
 178.355 +                int peek = input.read();
 178.356 +                if (peek == '=') {
 178.357 +                    // No need to back up, include it
 178.358 +                } else if (peek == '>') {
 178.359 +                    peek = input.read();
 178.360 +                    if (peek != '=') {
 178.361 +                        input.backup(1);
 178.362 +                    }
 178.363 +                } else {
 178.364 +                    input.backup(1);
 178.365 +                }
 178.366 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 178.367 +            }
 178.368 +            case '&': { // Look for &,&=
 178.369 +                if (input.read() != '=') {
 178.370 +                    input.backup(1);
 178.371 +                }
 178.372 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 178.373 +            }
 178.374 +            case '|': { // Look for |, |=
 178.375 +                if (input.read() != '=') {
 178.376 +                    input.backup(1);
 178.377 +                }
 178.378 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 178.379 +            }
 178.380 +            case '^': { // ^,^=
 178.381 +                if (input.read() != '=') {
 178.382 +                    input.backup(1);
 178.383 +                }
 178.384 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 178.385 +            }
 178.386 +            case '=': {
 178.387 +                // Look for =,==
 178.388 +                if (input.read() != '=') {
 178.389 +                    input.backup(1);
 178.390 +                }
 178.391 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 178.392 +            }
 178.393 +            case '!': {
 178.394 +                // Look for !=
 178.395 +                if (input.read() != '=') {
 178.396 +                    input.backup(1);
 178.397 +                }
 178.398 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 178.399 +            }
 178.400 +            case '~':
 178.401 +            case '`':
 178.402 +            case ';':
 178.403 +                return createToken(PythonTokenId.ANY_OPERATOR, input.readLength());
 178.404 +
 178.405 +            case ':':
 178.406 +                assert input.readLength() == 1;
 178.407 +                return createToken(PythonTokenId.COLON, 1);
 178.408 +            case '(':
 178.409 +                assert input.readLength() == 1;
 178.410 +                return createToken(PythonTokenId.LPAREN, 1);
 178.411 +            case ')':
 178.412 +                assert input.readLength() == 1;
 178.413 +                return createToken(PythonTokenId.RPAREN, 1);
 178.414 +            case '[':
 178.415 +                assert input.readLength() == 1;
 178.416 +                return createToken(PythonTokenId.LBRACKET, 1);
 178.417 +            case ']':
 178.418 +                assert input.readLength() == 1;
 178.419 +                return createToken(PythonTokenId.RBRACKET, 1);
 178.420 +            case '{':
 178.421 +                assert input.readLength() == 1;
 178.422 +                return createToken(PythonTokenId.LBRACE, 1);
 178.423 +            case '}':
 178.424 +                assert input.readLength() == 1;
 178.425 +                return createToken(PythonTokenId.RBRACE, 1);
 178.426 +            case ',':
 178.427 +                assert input.readLength() == 1;
 178.428 +                return createToken(PythonTokenId.COMMA, 1);
 178.429 +            case '\\':
 178.430 +                assert input.readLength() == 1;
 178.431 +                return createToken(PythonTokenId.ESC, 1);
 178.432 +
 178.433 +            case '$':
 178.434 +            case '?':
 178.435 +                assert input.readLength() == 1;
 178.436 +                return createToken(PythonTokenId.ERROR, 1);
 178.437 +
 178.438 +            // String?
 178.439 +            case '\'':
 178.440 +            case '"': {
 178.441 +                int peek = input.read();
 178.442 +                if (peek != ch) {
 178.443 +                    input.backup(1);
 178.444 +                    assert input.readLength() == 1;
 178.445 +                    state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
 178.446 +                    return createToken(PythonTokenId.STRING_BEGIN, 1);
 178.447 +                }
 178.448 +                // We've seen two quotes... it's either an empty string,
 178.449 +                // or the beginning of a longstring
 178.450 +                int peek2 = input.read();
 178.451 +                if (peek2 == peek) {
 178.452 +                    // It's a longstring!
 178.453 +                    assert input.readLength() == 3;
 178.454 +                    state = (ch == '"') ? State.BEGIN_LONGSTRING_DOUBLE : State.BEGIN_LONGSTRING_SINGLE;
 178.455 +                    return createToken(PythonTokenId.STRING_BEGIN, 3);
 178.456 +                } else {
 178.457 +                    input.backup(2);
 178.458 +                    assert input.readLength() == 1;
 178.459 +                    state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
 178.460 +                    return createToken(PythonTokenId.STRING_BEGIN, 1);
 178.461 +                }
 178.462 +            }
 178.463 +            case '@': { // Decorator
 178.464 +                // Identifier or keyword?
 178.465 +                ch = input.read();
 178.466 +                if (Character.isJavaIdentifierStart(ch)) {
 178.467 +                    while (ch != EOF && Character.isJavaIdentifierPart(ch) && ch != '$') {
 178.468 +                        ch = input.read();
 178.469 +                    }
 178.470 +                    input.backup(1);
 178.471 +
 178.472 +                    return createToken(PythonTokenId.DECORATOR, input.readLength());
 178.473 +                }
 178.474 +                input.backup(1); // Remove the peeked char
 178.475 +
 178.476 +                assert input.readLength() == 1;
 178.477 +                return createToken(PythonTokenId.DECORATOR, 1);
 178.478 +            }
 178.479 +
 178.480 +            case 'r':
 178.481 +            case 'R':
 178.482 +            case 'u':
 178.483 +            case 'U': {
 178.484 +                // Digest the "u" and the "r" and position the input
 178.485 +                // before the following ' or "
 178.486 +                boolean isStringPrefix = false;
 178.487 +                int peek = input.read();
 178.488 +                if (ch == 'r' || ch == 'R') {
 178.489 +                    if (peek == '\'' || peek == '"') {
 178.490 +                        isStringPrefix = true;
 178.491 +                    }
 178.492 +                    input.backup(1);
 178.493 +                } else {
 178.494 +                    assert ch == 'u' || ch == 'U';
 178.495 +                    if (peek == 'r' || peek == 'R') {
 178.496 +                        int peek2 = input.read();
 178.497 +                        if (peek2 == '\'' || peek2 == '"') {
 178.498 +                            isStringPrefix = true;
 178.499 +                        }
 178.500 +                        input.backup(1);
 178.501 +                    } else if (peek == '\'' || peek == '"') {
 178.502 +                        isStringPrefix = true;
 178.503 +                        input.backup(1);
 178.504 +                    }
 178.505 +                    if (!isStringPrefix) {
 178.506 +                        input.backup(1);
 178.507 +                    }
 178.508 +                }
 178.509 +                if (isStringPrefix) {
 178.510 +                    ch = input.read();
 178.511 +                    assert ch == '\'' || ch == '"';
 178.512 +
 178.513 +                    peek = input.read();
 178.514 +                    if (peek != ch) {
 178.515 +                        input.backup(1);
 178.516 +                        state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
 178.517 +                        return createToken(PythonTokenId.STRING_BEGIN, input.readLength());
 178.518 +                    }
 178.519 +                    // We've seen two quotes... it's either an empty string,
 178.520 +                    // or the beginning of a longstring
 178.521 +                    int peek2 = input.read();
 178.522 +                    if (peek2 == peek) {
 178.523 +                        // It's a longstring!
 178.524 +                        state = (ch == '"') ? State.BEGIN_LONGSTRING_DOUBLE : State.BEGIN_LONGSTRING_SINGLE;
 178.525 +                        return createToken(PythonTokenId.STRING_BEGIN, input.readLength());
 178.526 +                    } else {
 178.527 +                        input.backup(2);
 178.528 +                        state = (ch == '"') ? State.BEGIN_SHORTSTRING_DOUBLE : State.BEGIN_SHORTSTRING_SINGLE;
 178.529 +                        return createToken(PythonTokenId.STRING_BEGIN, input.readLength());
 178.530 +                    }
 178.531 +                }// else: FALLTHROUGH!!! The "u" or "r" is probably an identifier prefix!!
 178.532 +            }
 178.533 +            // Fallthrough...
 178.534 +
 178.535 +            default: {
 178.536 +                // Identifier or keyword?
 178.537 +                if (Character.isJavaIdentifierStart(ch)) {
 178.538 +                    while (ch != EOF && Character.isJavaIdentifierPart(ch) && ch != '$') {
 178.539 +                        ch = input.read();
 178.540 +                    }
 178.541 +                    input.backup(1);
 178.542 +
 178.543 +                    // See if it's a keyword
 178.544 +                    PythonTokenId pid = getKeywordToken(input.readText());
 178.545 +                    if (pid != null) {
 178.546 +                        return createToken(pid, input.readLength());
 178.547 +                    } else {
 178.548 +                        return createToken(PythonTokenId.IDENTIFIER, input.readLength());
 178.549 +                    }
 178.550 +                }
 178.551 +
 178.552 +                assert input.readLength() == 1;
 178.553 +                return createToken(PythonTokenId.ANY_OPERATOR, 1);
 178.554 +            }
 178.555 +            }
 178.556 +        }
 178.557 +
 178.558 +        case BEGIN_LONGSTRING_SINGLE:
 178.559 +        case BEGIN_LONGSTRING_DOUBLE: {
 178.560 +            // In a long string. Look for the end.
 178.561 +            int ch = input.read();
 178.562 +            if (ch == EOF) {
 178.563 +                return null;
 178.564 +            }
 178.565 +            int term = (state == State.BEGIN_LONGSTRING_DOUBLE) ? '"' : '\'';
 178.566 +            while (ch != EOF) {
 178.567 +                if (ch == '\\') {
 178.568 +                    // It's an escape - read escaped char
 178.569 +                    input.read();
 178.570 +                } else if (ch == term) {
 178.571 +                    int peek = input.read();
 178.572 +                    if (peek == term) {
 178.573 +                        int peek2 = input.read();
 178.574 +                        if (peek2 == term) {
 178.575 +                            // Found the end
 178.576 +                            if (input.readLength() == 3) {
 178.577 +                                // Empty string - go straight to closed state
 178.578 +                                state = State.INIT;
 178.579 +                                return createToken(PythonTokenId.STRING_END, input.readLength());
 178.580 +                            }
 178.581 +                            input.backup(3);
 178.582 +                            if (state == State.BEGIN_LONGSTRING_DOUBLE) {
 178.583 +                                state = State.END_LONGSTRING_DOUBLE;
 178.584 +                            } else {
 178.585 +                                assert state == State.BEGIN_LONGSTRING_SINGLE;
 178.586 +                                state = State.END_LONGSTRING_SINGLE;
 178.587 +                            }
 178.588 +                            return createToken(PythonTokenId.STRING_LITERAL, input.readLength());
 178.589 +                        }
 178.590 +                        input.backup(1);
 178.591 +                    }
 178.592 +                    input.backup(1);
 178.593 +                }
 178.594 +                ch = input.read();
 178.595 +            }
 178.596 +            // Literal not terminated
 178.597 +            state = State.INIT;
 178.598 +            return createToken(PythonTokenId.ERROR, input.readLength());
 178.599 +        }
 178.600 +        case BEGIN_SHORTSTRING_SINGLE:
 178.601 +        case BEGIN_SHORTSTRING_DOUBLE: {
 178.602 +            // In a short string. Look for the end.
 178.603 +            int ch = input.read();
 178.604 +            if (ch == EOF) {
 178.605 +                return null;
 178.606 +            }
 178.607 +            int term = (state == State.BEGIN_SHORTSTRING_DOUBLE) ? '"' : '\'';
 178.608 +            while (ch != EOF) {
 178.609 +                if (ch == '\\') {
 178.610 +                    // It's an escape - read escaped char
 178.611 +                    input.read();
 178.612 +                } else if (ch == '\n') {
 178.613 +                    // Literal not terminated
 178.614 +                    state = State.INIT;
 178.615 +                    return createToken(PythonTokenId.ERROR, input.readLength());
 178.616 +                } else if (ch == term) {
 178.617 +                    if (input.readLength() == 1) {
 178.618 +                        // It's an empty string! Skip straight to the end state
 178.619 +                        state = State.INIT;
 178.620 +                        return createToken(PythonTokenId.STRING_END, input.readLength());
 178.621 +                    }
 178.622 +                    input.backup(1);
 178.623 +                    if (state == State.BEGIN_SHORTSTRING_DOUBLE) {
 178.624 +                        state = State.END_SHORTSTRING_DOUBLE;
 178.625 +                    } else {
 178.626 +                        assert state == State.BEGIN_SHORTSTRING_SINGLE;
 178.627 +                        state = State.END_SHORTSTRING_SINGLE;
 178.628 +                    }
 178.629 +                    return createToken(PythonTokenId.STRING_LITERAL, input.readLength());
 178.630 +                }
 178.631 +                ch = input.read();
 178.632 +            }
 178.633 +            // Literal not terminated
 178.634 +            state = State.INIT;
 178.635 +            return createToken(PythonTokenId.ERROR, input.readLength());
 178.636 +        }
 178.637 +
 178.638 +        case END_LONGSTRING_SINGLE:
 178.639 +        case END_LONGSTRING_DOUBLE: {
 178.640 +            // In a long string. Look for the end.
 178.641 +            int ch = input.read();
 178.642 +            if (ch == EOF) {
 178.643 +                return null;
 178.644 +            }
 178.645 +            int term = (state == State.END_LONGSTRING_DOUBLE) ? '"' : '\'';
 178.646 +            while (ch != EOF) {
 178.647 +                if (ch == term) {
 178.648 +                    int peek = input.read();
 178.649 +                    if (peek == term) {
 178.650 +                        int peek2 = input.read();
 178.651 +                        if (peek2 == term) {
 178.652 +                            // Found the end
 178.653 +                            state = State.INIT;
 178.654 +                            return createToken(PythonTokenId.STRING_END, input.readLength());
 178.655 +                        }
 178.656 +                        input.backup(1);
 178.657 +                    }
 178.658 +                    input.backup(1);
 178.659 +                }
 178.660 +                ch = input.read();
 178.661 +            }
 178.662 +            // Literal not terminated
 178.663 +            state = State.INIT;
 178.664 +            return createToken(PythonTokenId.ERROR, input.readLength());
 178.665 +        }
 178.666 +        case END_SHORTSTRING_SINGLE:
 178.667 +        case END_SHORTSTRING_DOUBLE: {
 178.668 +            // In a short string. Look for the end.
 178.669 +            int ch = input.read();
 178.670 +            if (ch == EOF) {
 178.671 +                return null;
 178.672 +            }
 178.673 +            int term = (state == State.END_SHORTSTRING_DOUBLE) ? '"' : '\'';
 178.674 +            if (ch == term) {
 178.675 +                state = State.INIT;
 178.676 +                return createToken(PythonTokenId.STRING_END, input.readLength());
 178.677 +            }
 178.678 +            state = State.INIT;
 178.679 +            return createToken(PythonTokenId.ERROR, input.readLength());
 178.680 +        }
 178.681 +
 178.682 +        default:
 178.683 +            assert false : state;
 178.684 +        }
 178.685 +
 178.686 +        return null;
 178.687 +    }
 178.688 +
 178.689 +    @Override
 178.690 +    public void release() {
 178.691 +    }
 178.692 +
 178.693 +    private static PythonTokenId getKeywordToken(CharSequence s) {
 178.694 +        int length = s.length();
 178.695 +        if (length < 2) {
 178.696 +            return null;
 178.697 +        }
 178.698 +
 178.699 +        if (BuiltinException.isBuiltInException(s)) {
 178.700 +            return PythonTokenId.ERROR;
 178.701 +        }
 178.702 +
 178.703 +        char c1 = s.charAt(0);
 178.704 +        char c2 = s.charAt(1);
 178.705 +
 178.706 +        switch (c1) {
 178.707 +        case 'a': // and, as, assert, async, await
 178.708 +            switch (c2) {
 178.709 +            case 'b': // abs
 178.710 +                if (length == 3 && TokenUtilities.textEquals(s, "abs")) { // NOI18N
 178.711 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.712 +                }
 178.713 +            case 'l': // all
 178.714 +                if (length == 3 && TokenUtilities.textEquals(s, "all")) {  // NOI18N
 178.715 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.716 +                }
 178.717 +            case 'n': // and, any
 178.718 +                if (length == 3 && TokenUtilities.textEquals(s, "and")) { // NOI18N
 178.719 +                    return PythonTokenId.ANY_KEYWORD;
 178.720 +                } else if (TokenUtilities.textEquals(s, "any")) {  // NOI18N
 178.721 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.722 +                }
 178.723 +                break;
 178.724 +            case 's':  // as, ascii, assert, async
 178.725 +                if (length == 2) { // as
 178.726 +                    return PythonTokenId.ANY_KEYWORD;
 178.727 +                }
 178.728 +                if (length == 5 && TokenUtilities.textEquals(s, "ascii")) {  // NOI18N
 178.729 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.730 +                }
 178.731 +                if (length == 6 && TokenUtilities.textEquals(s, "assert")) { // NOI18N
 178.732 +                    return PythonTokenId.ANY_KEYWORD;
 178.733 +                }
 178.734 +                if (length == 5 && TokenUtilities.textEquals(s, "async")) { // NOI18N
 178.735 +                    return PythonTokenId.ANY_KEYWORD;
 178.736 +                }
 178.737 +                break;
 178.738 +            case 'w': // await
 178.739 +                if (length == 5 && TokenUtilities.textEquals(s, "await")) { // NOI18N
 178.740 +                    return PythonTokenId.ANY_KEYWORD;
 178.741 +                }
 178.742 +            }
 178.743 +            break;
 178.744 +        case 'b': // basestring, bin, bool, break, bytearray, bytes
 178.745 +            if (length == 10 && TokenUtilities.textEquals(s, "basestring")) {  // NOI18N
 178.746 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.747 +            }
 178.748 +            if (length == 3 && TokenUtilities.textEquals(s, "bin")) {  // NOI18N
 178.749 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.750 +            }
 178.751 +            if (length == 4 && TokenUtilities.textEquals(s, "bool")) {  // NOI18N
 178.752 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.753 +            }
 178.754 +            if (length == 5 && TokenUtilities.textEquals(s, "break")) { // NOI18N
 178.755 +                return PythonTokenId.ANY_KEYWORD;
 178.756 +            }
 178.757 +            if (length == 9 && TokenUtilities.textEquals(s, "bytearray")) {  // NOI18N
 178.758 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.759 +            }
 178.760 +            if (length == 5 && TokenUtilities.textEquals(s, "bytes")) { // NOI18N
 178.761 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.762 +            }
 178.763 +            break;
 178.764 +        case 'c': // callable, chr, class, classmethod, continue
 178.765 +            switch (c2) {
 178.766 +            case 'a': // callable
 178.767 +                if (length == 8 && TokenUtilities.textEquals(s, "callable")) {  // NOI18N
 178.768 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.769 +                }
 178.770 +                break;
 178.771 +            case 'h': // chr
 178.772 +                if (length == 3 && TokenUtilities.textEquals(s, "chr")) {  // NOI18N
 178.773 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.774 +                }
 178.775 +                break;
 178.776 +            case 'l': // class, classmethod
 178.777 +                if (length == 5 && TokenUtilities.textEquals(s, "class")) { // NOI18N
 178.778 +                    return PythonTokenId.CLASS;
 178.779 +                }
 178.780 +                if (length == 11 && TokenUtilities.textEquals(s, "classmethod")) {  // NOI18N
 178.781 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.782 +                }
 178.783 +                break;
 178.784 +            case 'm': // cmp
 178.785 +                if (length == 3 && TokenUtilities.textEquals(s, "cmp")) {  // NOI18N
 178.786 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.787 +                }
 178.788 +                break;
 178.789 +            case 'o':  // compile, complex, continue
 178.790 +                if (length == 7 && TokenUtilities.textEquals(s, "compile")) {  // NOI18N
 178.791 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.792 +                }
 178.793 +                if (length == 7 && TokenUtilities.textEquals(s, "complex")) {  // NOI18N
 178.794 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.795 +                }
 178.796 +                if (length == 8 && TokenUtilities.textEquals(s, "continue")) { // NOI18N
 178.797 +                    return PythonTokenId.ANY_KEYWORD;
 178.798 +                }
 178.799 +                break;
 178.800 +            }
 178.801 +            break;
 178.802 +        case 'd': // def, del
 178.803 +            switch (c2) {
 178.804 +                case 'e': // def, del, delattr
 178.805 +                    if (length == 3 && TokenUtilities.textEquals(s, "def")) {  // NOI18N
 178.806 +                        return PythonTokenId.DEF;
 178.807 +                    }
 178.808 +                    if (length == 3 && TokenUtilities.textEquals(s, "del")) {  // NOI18N
 178.809 +                        return PythonTokenId.ANY_KEYWORD;
 178.810 +                    }
 178.811 +                    if (length == 7 && TokenUtilities.textEquals(s, "delattr")) {  // NOI18N
 178.812 +                        return PythonTokenId.BUILTIN_FUNCTION;
 178.813 +                    }
 178.814 +                    break;
 178.815 +                case 'i': // dict, dir, divmod
 178.816 +                    if (length == 4 && TokenUtilities.textEquals(s, "dict")) {  // NOI18N
 178.817 +                        return PythonTokenId.BUILTIN_FUNCTION;
 178.818 +                    }
 178.819 +                    if (length == 3 && TokenUtilities.textEquals(s, "dir")) {  // NOI18N
 178.820 +                        return PythonTokenId.BUILTIN_FUNCTION;
 178.821 +                    }
 178.822 +                    if (length == 6 && TokenUtilities.textEquals(s, "divmod")) {  // NOI18N
 178.823 +                        return PythonTokenId.BUILTIN_FUNCTION;
 178.824 +                    }
 178.825 +                    break;
 178.826 +            }
 178.827 +            break;
 178.828 +        case 'e': // elif, else, enumerate, eval, except, exec, execfile
 178.829 +            switch (c2) {
 178.830 +            case 'l': // elif, else
 178.831 +                if (length == 4) {
 178.832 +                    if (TokenUtilities.textEquals(s, "elif")) { // NOI18N
 178.833 +                        return PythonTokenId.ELIF;
 178.834 +                    }
 178.835 +                    if (TokenUtilities.textEquals(s, "else")) { // NOI18N
 178.836 +                        return PythonTokenId.ELSE;
 178.837 +                    }
 178.838 +                }
 178.839 +                break;
 178.840 +            case 'n': // enumerate
 178.841 +                if (length == 9 && TokenUtilities.textEquals(s, "enumerate")) { // NOI18N
 178.842 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.843 +                }
 178.844 +                break;
 178.845 +            case 'v': // eval
 178.846 +                if (length == 4 && TokenUtilities.textEquals(s, "eval")) {  // NOI18N
 178.847 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.848 +                }
 178.849 +                break;
 178.850 +            case 'x': // except, exec, execfile
 178.851 +                if (length == 4 && TokenUtilities.textEquals(s, "exec")) { // NOI18N
 178.852 +                    return PythonTokenId.ANY_KEYWORD;
 178.853 +                }
 178.854 +                if (length == 8 && TokenUtilities.textEquals(s, "execfile")) { // NOI18N
 178.855 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.856 +                }
 178.857 +                if (length == 6 && TokenUtilities.textEquals(s, "except")) { // NOI18N
 178.858 +                    return PythonTokenId.EXCEPT;
 178.859 +                }
 178.860 +                break;
 178.861 +            }
 178.862 +            break;
 178.863 +        case 'f': // file, filter, finally, for, from
 178.864 +            switch (c2) {
 178.865 +            case 'i': // file, filter, finally
 178.866 +                if (length == 4 && TokenUtilities.textEquals(s, "file")) {  // NOI18N
 178.867 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.868 +                }
 178.869 +                if (length == 6 && TokenUtilities.textEquals(s, "filter")) {  // NOI18N
 178.870 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.871 +                }
 178.872 +                if (length == 7 && TokenUtilities.textEquals(s, "finally")) { // NOI18N
 178.873 +                    return PythonTokenId.FINALLY;
 178.874 +                }
 178.875 +                break;
 178.876 +            case 'o': // for, format
 178.877 +                if (length == 3 && TokenUtilities.textEquals(s, "for")) { // NOI18N
 178.878 +                    return PythonTokenId.ANY_KEYWORD;
 178.879 +                }
 178.880 +                if (length == 6 && TokenUtilities.textEquals(s, "format")) {  // NOI18N
 178.881 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.882 +                }
 178.883 +                break;
 178.884 +            case 'r': // from, frozenset
 178.885 +                if (length == 4 && TokenUtilities.textEquals(s, "from")) { // NOI18N
 178.886 +                    return PythonTokenId.FROM;
 178.887 +                }
 178.888 +                if (length == 9 && TokenUtilities.textEquals(s, "frozenset")) {  // NOI18N
 178.889 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.890 +                }
 178.891 +                break;
 178.892 +            case 'l':
 178.893 +                if (length == 5 && TokenUtilities.textEquals(s, "float")) {
 178.894 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.895 +                }
 178.896 +                break;
 178.897 +            }
 178.898 +            break;
 178.899 +        case 'g': // getattr, global, globals
 178.900 +            if (length == 7 && TokenUtilities.textEquals(s, "getattr")) {  // NOI18N
 178.901 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.902 +            }
 178.903 +            if (length == 6 && TokenUtilities.textEquals(s, "global")) { // NOI18N
 178.904 +                return PythonTokenId.ANY_KEYWORD;
 178.905 +            }
 178.906 +            if (length == 7 && TokenUtilities.textEquals(s, "globals")) { // NOI18N
 178.907 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.908 +            }
 178.909 +            break;
 178.910 +        case 'h': // hasattr, hash, help, hex
 178.911 +            if (length == 7 && TokenUtilities.textEquals(s, "hasattr")) {  // NOI18N
 178.912 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.913 +            }
 178.914 +            if (length == 4 && TokenUtilities.textEquals(s, "hash")) {  // NOI18N
 178.915 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.916 +            }
 178.917 +            if (length == 4 && TokenUtilities.textEquals(s, "help")) {  // NOI18N
 178.918 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.919 +            }
 178.920 +            if (length == 3 && TokenUtilities.textEquals(s, "hex")) {  // NOI18N
 178.921 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.922 +            }
 178.923 +            break;
 178.924 +        case 'i': // id, if, import, in, input, int, is, issubclass, iter
 178.925 +            if (length == 2) {
 178.926 +                switch (c2) {
 178.927 +                case 'd': // id
 178.928 +                    return PythonTokenId.BUILTIN_FUNCTION;
 178.929 +                case 'f': // if
 178.930 +                    return PythonTokenId.IF;
 178.931 +                case 'n': // in
 178.932 +                    if (length == 2 && TokenUtilities.textEquals(s, "in")) { //NOI18N
 178.933 +                        return PythonTokenId.ANY_KEYWORD;
 178.934 +                    }
 178.935 +                case 's': // is
 178.936 +                    return PythonTokenId.ANY_KEYWORD;
 178.937 +                }
 178.938 +            } else if (c2 == 'm' && length == 6 && TokenUtilities.textEquals(s, "import")) { // NOI18N
 178.939 +                return PythonTokenId.IMPORT;
 178.940 +            } else if (length == 5 && TokenUtilities.textEquals(s, "input")) {  // NOI18N
 178.941 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.942 +            } else if (length == 3 && TokenUtilities.textEquals(s, "int")) { // NOI18N
 178.943 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.944 +            } else if (length == 10 && TokenUtilities.textEquals(s, "isinstance")) { // NOI18N
 178.945 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.946 +            } else if (length == 10 && TokenUtilities.textEquals(s, "issubclass")) { // NOI18N
 178.947 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.948 +            } else if (length == 4 && TokenUtilities.textEquals(s, "iter")) { // NOI18N
 178.949 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.950 +            }
 178.951 +            break;
 178.952 +        case 'l': // lambda, len, list, locals, long
 178.953 +            if (length == 6 && TokenUtilities.textEquals(s, "lambda")) { // NOI18N
 178.954 +                return PythonTokenId.ANY_KEYWORD;
 178.955 +            } else if (length == 3 && TokenUtilities.textEquals(s, "len")) { // NOI18N
 178.956 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.957 +            } else if (length == 4 && TokenUtilities.textEquals(s, "list")) { // NOI18N
 178.958 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.959 +            } else if (length == 6 && TokenUtilities.textEquals(s, "locals")) { // NOI18N
 178.960 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.961 +            } else if (length == 4 && TokenUtilities.textEquals(s, "long")) { // NOI18N
 178.962 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.963 +            }
 178.964 +            break;
 178.965 +        case 'm': // map, max, memoryview, min
 178.966 +            if (length == 3 && TokenUtilities.textEquals(s, "map")) { // NOI18N
 178.967 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.968 +            }
 178.969 +            if (length == 3 && TokenUtilities.textEquals(s, "max")) { // NOI18N
 178.970 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.971 +            }
 178.972 +            if (length == 10 && TokenUtilities.textEquals(s, "memoryview")) { // NOI18N
 178.973 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.974 +            }
 178.975 +            if (length == 3 && TokenUtilities.textEquals(s, "min")) { // NOI18N
 178.976 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.977 +            }
 178.978 +            break;
 178.979 +        case 'n': // next, nonlocal, not
 178.980 +            if (length == 4 && TokenUtilities.textEquals(s, "next")) { // NOI18N
 178.981 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.982 +            }
 178.983 +            if (length == 8 && TokenUtilities.textEquals(s, "nonlocal")) { // NOI18N
 178.984 +                return PythonTokenId.ANY_KEYWORD;
 178.985 +            }
 178.986 +            if (length == 3 && TokenUtilities.textEquals(s, "not")) { // NOI18N
 178.987 +                return PythonTokenId.ANY_KEYWORD;
 178.988 +            }
 178.989 +            break;
 178.990 +        case 'o': // or, object, oct, open, ord
 178.991 +            if (length == 2 && TokenUtilities.textEquals(s, "or")) { // NOI18N
 178.992 +                return PythonTokenId.ANY_KEYWORD;
 178.993 +            }
 178.994 +            if (length == 6 && TokenUtilities.textEquals(s, "object")) { // NOI18N
 178.995 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.996 +            }
 178.997 +            if (length == 3 && TokenUtilities.textEquals(s, "oct")) { // NOI18N
 178.998 +                return PythonTokenId.BUILTIN_FUNCTION;
 178.999 +            }
178.1000 +            if (length == 4 && TokenUtilities.textEquals(s, "open")) { // NOI18N
178.1001 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1002 +            }
178.1003 +            if (length == 3 && TokenUtilities.textEquals(s, "ord")) { // NOI18N
178.1004 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1005 +            }
178.1006 +            break;
178.1007 +        case 'p': // pass, pow, print, property
178.1008 +            if (c2 == 'a') { // pass
178.1009 +                if (length == 4 && TokenUtilities.textEquals(s, "pass")) { // NOI18N
178.1010 +                    return PythonTokenId.PASS;
178.1011 +                }
178.1012 +            }
178.1013 +            if (length == 3 && TokenUtilities.textEquals(s, "pow")) { // NOI18N
178.1014 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1015 +            }
178.1016 +            if (c2 == 'r') { // print, property
178.1017 +                if (length == 5 && TokenUtilities.textEquals(s, "print")) { // NOI18N
178.1018 +                    return PythonTokenId.ANY_KEYWORD;
178.1019 +                }
178.1020 +                if (length == 8 && TokenUtilities.textEquals(s, "property")) { // NOI18N
178.1021 +                    return PythonTokenId.BUILTIN_FUNCTION;
178.1022 +                }
178.1023 +            }
178.1024 +            break;
178.1025 +        case 'r': // raise, range, raise, raw_input, reduce, reload, repr, return, reversed, round
178.1026 +            if (c2 == 'a') { // raise, range
178.1027 +                if (length == 5 && TokenUtilities.textEquals(s, "range")) { // NOI18N
178.1028 +                    return PythonTokenId.BUILTIN_FUNCTION;
178.1029 +                }
178.1030 +                if (length == 5 && TokenUtilities.textEquals(s, "raise")) { // NOI18N
178.1031 +                    return PythonTokenId.RAISE;
178.1032 +                }
178.1033 +                if (length == 9 && TokenUtilities.textEquals(s, "raw_input")) { // NOI18N
178.1034 +                    return PythonTokenId.BUILTIN_FUNCTION;
178.1035 +                }
178.1036 +            } else if (c2 == 'e') { // reduce, reload, repr, return, reversed
178.1037 +                if (length == 6 && TokenUtilities.textEquals(s, "reduce")) { // NOI18N
178.1038 +                    return PythonTokenId.BUILTIN_FUNCTION;
178.1039 +                }
178.1040 +                if (length == 6 && TokenUtilities.textEquals(s, "reload")) {  // NOI18N
178.1041 +                    return PythonTokenId.BUILTIN_FUNCTION;
178.1042 +                }
178.1043 +                if (length == 4 && TokenUtilities.textEquals(s, "repr")) { // NOI18N
178.1044 +                    return PythonTokenId.BUILTIN_FUNCTION;
178.1045 +                }
178.1046 +                if (length == 6 && TokenUtilities.textEquals(s, "return")) { // NOI18N
178.1047 +                    return PythonTokenId.RETURN;
178.1048 +                }
178.1049 +                if (length == 8 && TokenUtilities.textEquals(s, "reversed")) { // NOI18N
178.1050 +                    return PythonTokenId.BUILTIN_FUNCTION;
178.1051 +                }
178.1052 +            } else if (length == 5 && TokenUtilities.textEquals(s, "round")) { // NOI18N
178.1053 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1054 +            }
178.1055 +            break;
178.1056 +        case 's': // self, set, setattr, slice, sorted, staticmethod, str, sum, super
178.1057 +            if (length == 4 && TokenUtilities.textEquals(s, "self")) { // NOI18N
178.1058 +                return PythonTokenId.ANY_KEYWORD;
178.1059 +            }
178.1060 +            if (length == 3 && TokenUtilities.textEquals(s, "set")) { // NOI18N
178.1061 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1062 +            }
178.1063 +            if (length == 7 && TokenUtilities.textEquals(s, "setattr")) { // NOI18N
178.1064 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1065 +            }
178.1066 +            if (length == 5 && TokenUtilities.textEquals(s, "slice")) { // NOI18N
178.1067 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1068 +            }
178.1069 +            if (length == 6 && TokenUtilities.textEquals(s, "sorted")) { // NOI18N
178.1070 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1071 +            }
178.1072 +            if (length == 12 && TokenUtilities.textEquals(s, "staticmethod")) { // NOI18N
178.1073 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1074 +            }
178.1075 +            if (length == 3 && TokenUtilities.textEquals(s, "str")) { // NOI18N
178.1076 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1077 +            }
178.1078 +            if (length == 3 && TokenUtilities.textEquals(s, "sum")) { // NOI18N
178.1079 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1080 +            }
178.1081 +            if (length == 5 && TokenUtilities.textEquals(s, "super")) { // NOI18N
178.1082 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1083 +            }
178.1084 +            break;
178.1085 +        case 't': // try, tuple, type
178.1086 +            if (length == 3 && TokenUtilities.textEquals(s, "try")) { // NOI18N
178.1087 +                return PythonTokenId.TRY;
178.1088 +            } else if (length == 5 && TokenUtilities.textEquals(s, "tuple")) { // NOI18N
178.1089 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1090 +            } else if (length == 4 && TokenUtilities.textEquals(s, "type")) { // NOI18N
178.1091 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1092 +            }
178.1093 +            break;
178.1094 +        case 'u': // unichr, unicode
178.1095 +            if (length == 6 && TokenUtilities.textEquals(s, "unichr")) { // NOI18N
178.1096 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1097 +            }
178.1098 +            if (length == 7 && TokenUtilities.textEquals(s, "unicode")) { // NOI18N
178.1099 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1100 +            }
178.1101 +            break;
178.1102 +        case 'v': // vars
178.1103 +            if (length == 4 && TokenUtilities.textEquals(s, "vars")) { // NOI18N
178.1104 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1105 +            }
178.1106 +            break;
178.1107 +        case 'w': // while,with
178.1108 +            if (c2 == 'h') { // while
178.1109 +                if (length == 5 && TokenUtilities.textEquals(s, "while")) { // NOI18N
178.1110 +                    return PythonTokenId.ANY_KEYWORD;
178.1111 +                }
178.1112 +            } else if (c2 == 'i') { // with
178.1113 +                if (length == 4 && TokenUtilities.textEquals(s, "with")) { // NOI18N
178.1114 +                    return PythonTokenId.ANY_KEYWORD;
178.1115 +                }
178.1116 +            }
178.1117 +            break;
178.1118 +        case 'x': // xrange
178.1119 +            if (length == 6 && TokenUtilities.textEquals(s, "xrange")) { // NOI18N
178.1120 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1121 +            }
178.1122 +            break;
178.1123 +        case 'y': // yield
178.1124 +            if (length == 5 && TokenUtilities.textEquals(s, "yield")) { // NOI18N
178.1125 +                return PythonTokenId.ANY_KEYWORD;
178.1126 +            }
178.1127 +            break;
178.1128 +        case 'z': // zip
178.1129 +            if (length == 3 && TokenUtilities.textEquals(s, "zip")) { // NOI18N
178.1130 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1131 +            }
178.1132 +            break;
178.1133 +        case 'F': // False
178.1134 +            if (length == 5 && TokenUtilities.textEquals(s, "False")) { // NOI18N
178.1135 +                return PythonTokenId.FALSE;
178.1136 +            }
178.1137 +            break;
178.1138 +        case 'N': // None
178.1139 +            if (length == 4 && TokenUtilities.textEquals(s, "None")) { // NOI18N
178.1140 +                return PythonTokenId.NONE;
178.1141 +            }
178.1142 +            break;
178.1143 +        case 'T': // True
178.1144 +            if (length == 4 && TokenUtilities.textEquals(s, "True")) { // NOI18N
178.1145 +                return PythonTokenId.TRUE;
178.1146 +            }
178.1147 +            break;
178.1148 +        case '_': // Special symbols of python
178.1149 +            if (length > 4 && TokenUtilities.startsWith(s, "__") && TokenUtilities.endsWith(s, "__")) { // NOI18N
178.1150 +                return PythonTokenId.BUILTIN_FUNCTION;
178.1151 +            }
178.1152 +            break;
178.1153 +        }
178.1154 +
178.1155 +        return null;
178.1156 +    }
178.1157 +
178.1158 +    public static boolean isKeywordOrBuiltin(CharSequence name) {
178.1159 +        return getKeywordToken(name) != null;
178.1160 +    }
178.1161 +}
   179.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   179.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/PythonLexerUtils.java	Mon Sep 21 13:01:16 2015 +0200
   179.3 @@ -0,0 +1,562 @@
   179.4 +/*
   179.5 + * To change this template, choose Tools | Templates
   179.6 + * and open the template in the editor.
   179.7 + */
   179.8 +package org.netbeans.modules.python.source.lexer;
   179.9 +
  179.10 +import java.util.Arrays;
  179.11 +import java.util.List;
  179.12 +import java.util.regex.Matcher;
  179.13 +import java.util.regex.Pattern;
  179.14 +import javax.swing.text.BadLocationException;
  179.15 +import javax.swing.text.Document;
  179.16 +import org.netbeans.api.lexer.Token;
  179.17 +import org.netbeans.api.lexer.TokenHierarchy;
  179.18 +import org.netbeans.api.lexer.TokenId;
  179.19 +import org.netbeans.api.lexer.TokenSequence;
  179.20 +import org.netbeans.editor.BaseDocument;
  179.21 +import org.netbeans.editor.Utilities;
  179.22 +import org.netbeans.modules.csl.api.OffsetRange;
  179.23 +import org.netbeans.modules.python.source.PythonParserResult;
  179.24 +import org.openide.filesystems.FileUtil;
  179.25 +import org.openide.loaders.DataObject;
  179.26 +import org.openide.util.Exceptions;
  179.27 +import org.python.antlr.PythonTree;
  179.28 +
  179.29 +/**
  179.30 + * Utility functions around the Python lexer
  179.31 + * 
  179.32 + * @author Tor Norbye
  179.33 + */
  179.34 +public class PythonLexerUtils {
  179.35 +    /**
  179.36 +     * Try to produce a more accurate location for the given name in the given import statement, located
  179.37 +     * at the lexRange provided
  179.38 +     */
  179.39 +    public static OffsetRange getImportNameOffset(BaseDocument doc, OffsetRange lexRange, PythonTree node, String name) {
  179.40 +        int docLength = doc.getLength();
  179.41 +        int start = Math.min(docLength, lexRange.getStart());
  179.42 +        int end = Math.min(docLength, lexRange.getEnd());
  179.43 +        try {
  179.44 +            String s = doc.getText(start, end - start);
  179.45 +
  179.46 +            Pattern p = Pattern.compile(".*import\\s+\\b(" + name + ")\\b.*");
  179.47 +            Matcher m = p.matcher(s);
  179.48 +            if (m.matches()) {
  179.49 +                int offset = start + m.start(1);
  179.50 +                return new OffsetRange(offset, offset + name.length());
  179.51 +            }
  179.52 +
  179.53 +            // Lame
  179.54 +            int searchIndex = s.indexOf("import ");
  179.55 +            if (searchIndex == -1) {
  179.56 +                searchIndex = 0;
  179.57 +            } else {
  179.58 +                searchIndex += 7;
  179.59 +            }
  179.60 +            int match = s.indexOf(name, searchIndex + 7);
  179.61 +            if (match != -1) {
  179.62 +                int offset = start + match;
  179.63 +                return new OffsetRange(offset, offset + name.length());
  179.64 +            }
  179.65 +
  179.66 +        // Give up - use the whole range
  179.67 +        } catch (BadLocationException ex) {
  179.68 +            Exceptions.printStackTrace(ex);
  179.69 +        }
  179.70 +
  179.71 +        return lexRange;
  179.72 +    }
  179.73 +
  179.74 +    /** For a possibly generated offset in an AST, return the corresponding lexing/true document offset */
  179.75 +    public static int getLexerOffset(PythonParserResult result, int astOffset) {
  179.76 +        return result.getSnapshot().getOriginalOffset(astOffset);
  179.77 +    }
  179.78 +
  179.79 +    public static OffsetRange getLexerOffsets(PythonParserResult result, OffsetRange astRange) {
  179.80 +        if (result != null) {
  179.81 +            int rangeStart = astRange.getStart();
  179.82 +            int start = result.getSnapshot().getOriginalOffset(rangeStart);
  179.83 +            if (start == rangeStart) {
  179.84 +                return astRange;
  179.85 +            } else if (start == -1) {
  179.86 +                return OffsetRange.NONE;
  179.87 +            } else {
  179.88 +                // Assumes the translated range maintains size
  179.89 +                return new OffsetRange(start, start + astRange.getLength());
  179.90 +            }
  179.91 +        }
  179.92 +
  179.93 +        return astRange;
  179.94 +    }
  179.95 +
  179.96 +    /**
  179.97 +     * Narrow a given lexical offset range to the closest AST-relevant offsets.
  179.98 +     * This means it will pass over things like comments and whitespace.
  179.99 +     * @param doc The document containing the range
 179.100 +     * @param range The start/end lexical range we want to narrow
 179.101 +     * @return An OffsetRange where the offsets begin and end at AST-relevant tokens
 179.102 +     */
 179.103 +    public static OffsetRange narrow(BaseDocument doc, OffsetRange range, boolean skipComments) {
 179.104 +        try {
 179.105 +            doc.readLock(); // For token hiearchy use
 179.106 +            // For token hiearchy use
 179.107 +            int start = range.getStart();
 179.108 +            TokenSequence<? extends PythonTokenId> ts = getPythonSequence(doc, start);
 179.109 +            if (ts != null) {
 179.110 +                int delta = ts.move(start);
 179.111 +                while (ts.moveNext()) {
 179.112 +                    Token<? extends PythonTokenId> token = ts.token();
 179.113 +                    PythonTokenId id = token.id();
 179.114 +                    if (id != PythonTokenId.NEWLINE && (!skipComments || id != PythonTokenId.COMMENT) && id != PythonTokenId.WHITESPACE) {
 179.115 +                        if (delta != 0) {
 179.116 +                            return OffsetRange.NONE;
 179.117 +                        }
 179.118 +                        start = ts.offset();
 179.119 +                        break;
 179.120 +                    } else {
 179.121 +                        delta = 0;
 179.122 +                    }
 179.123 +                }
 179.124 +            }
 179.125 +            int end = range.getEnd();
 179.126 +            ts = getPositionedSequence(doc, end);
 179.127 +            if (ts != null) {
 179.128 +                int delta = ts.move(end);
 179.129 +                while (delta > 0 ? ts.moveNext() : ts.movePrevious()) {
 179.130 +                    Token<? extends PythonTokenId> token = ts.token();
 179.131 +                    PythonTokenId id = token.id();
 179.132 +                    if (id != PythonTokenId.NEWLINE && (!skipComments || id != PythonTokenId.COMMENT) && id != PythonTokenId.WHITESPACE) {
 179.133 +                        if (delta != 0) {
 179.134 +                            return OffsetRange.NONE;
 179.135 +                        }
 179.136 +                        end = ts.offset() + token.length();
 179.137 +                        break;
 179.138 +                    } else {
 179.139 +                        delta = 0;
 179.140 +                    }
 179.141 +                }
 179.142 +            }
 179.143 +
 179.144 +            if (end < start) {
 179.145 +                return OffsetRange.NONE;
 179.146 +            }
 179.147 +
 179.148 +            return new OffsetRange(start, end);
 179.149 +        } finally {
 179.150 +            doc.readUnlock();
 179.151 +        }
 179.152 +    }
 179.153 +
 179.154 +    /** Find the ruby token sequence (in case it's embedded in something else at the top level */
 179.155 +    @SuppressWarnings("unchecked")
 179.156 +    public static TokenSequence<? extends PythonTokenId> getPythonSequence(BaseDocument doc, int offset) {
 179.157 +        TokenHierarchy<Document> th = TokenHierarchy.get((Document)doc);
 179.158 +        return getPythonSequence(th, offset);
 179.159 +    }
 179.160 +
 179.161 +    @SuppressWarnings("unchecked")
 179.162 +    public static TokenSequence<? extends PythonTokenId> getPythonSequence(TokenHierarchy<Document> th, int offset) {
 179.163 +        TokenSequence<? extends PythonTokenId> ts = th.tokenSequence(PythonTokenId.language());
 179.164 +
 179.165 +        if (ts == null) {
 179.166 +            // Possibly an embedding scenario such as an RHTML file
 179.167 +            // First try with backward bias true
 179.168 +            List<TokenSequence<?>> list = th.embeddedTokenSequences(offset, true);
 179.169 +
 179.170 +            for (TokenSequence t : list) {
 179.171 +                if (t.language() == PythonTokenId.language()) {
 179.172 +                    ts = t;
 179.173 +
 179.174 +                    break;
 179.175 +                }
 179.176 +            }
 179.177 +
 179.178 +            if (ts == null) {
 179.179 +                list = th.embeddedTokenSequences(offset, false);
 179.180 +
 179.181 +                for (TokenSequence t : list) {
 179.182 +                    if (t.language() == PythonTokenId.language()) {
 179.183 +                        ts = t;
 179.184 +
 179.185 +                        break;
 179.186 +                    }
 179.187 +                }
 179.188 +            }
 179.189 +        }
 179.190 +
 179.191 +        return ts;
 179.192 +    }
 179.193 +
 179.194 +    public static TokenSequence<? extends PythonTokenId> getPositionedSequence(BaseDocument doc, int offset) {
 179.195 +        return getPositionedSequence(doc, offset, true);
 179.196 +    }
 179.197 +
 179.198 +    public static TokenSequence<? extends PythonTokenId> getPositionedSequence(BaseDocument doc, int offset, boolean lookBack) {
 179.199 +        TokenSequence<? extends PythonTokenId> ts = getPythonSequence(doc, offset);
 179.200 +
 179.201 +        if (ts != null) {
 179.202 +            try {
 179.203 +                ts.move(offset);
 179.204 +            } catch (AssertionError e) {
 179.205 +                DataObject dobj = (DataObject)doc.getProperty(Document.StreamDescriptionProperty);
 179.206 +
 179.207 +                if (dobj != null) {
 179.208 +                    Exceptions.attachMessage(e, FileUtil.getFileDisplayName(dobj.getPrimaryFile()));
 179.209 +                }
 179.210 +
 179.211 +                throw e;
 179.212 +            }
 179.213 +
 179.214 +            if (!lookBack && !ts.moveNext()) {
 179.215 +                return null;
 179.216 +            } else if (lookBack && !ts.moveNext() && !ts.movePrevious()) {
 179.217 +                return null;
 179.218 +            }
 179.219 +
 179.220 +            /* TODO - allow Python inside strings
 179.221 +            if (ts.token().id() == PythonTokenId.STRING_LITERAL) {
 179.222 +            TokenSequence<? extends PythonStringTokenId> ets = ts.embedded(PythonStringTokenId.language());
 179.223 +            if (ets != null) {
 179.224 +            ets.move(offset);
 179.225 +            if ((!lookBack && ets.moveNext()) || (lookBack && ets.movePrevious())) {
 179.226 +            TokenSequence<?extends PythonTokenId> epts = ets.embedded(PythonTokenId.language());
 179.227 +            if (epts != null) {
 179.228 +            epts.move(offset);
 179.229 +            if (!lookBack && !epts.moveNext()) {
 179.230 +            return null;
 179.231 +            } else if (lookBack && !epts.moveNext() && !epts.movePrevious()) {
 179.232 +            return null;
 179.233 +            }
 179.234 +            return epts;
 179.235 +            }
 179.236 +            }
 179.237 +            }
 179.238 +            }
 179.239 +             */
 179.240 +
 179.241 +            return ts;
 179.242 +        }
 179.243 +
 179.244 +        return null;
 179.245 +    }
 179.246 +
 179.247 +    public static Token<? extends PythonTokenId> getToken(BaseDocument doc, int offset) {
 179.248 +        TokenSequence<? extends PythonTokenId> ts = getPositionedSequence(doc, offset);
 179.249 +
 179.250 +        if (ts != null) {
 179.251 +            return ts.token();
 179.252 +        }
 179.253 +
 179.254 +        return null;
 179.255 +    }
 179.256 +
 179.257 +    public static char getTokenChar(BaseDocument doc, int offset) {
 179.258 +        Token<? extends PythonTokenId> token = getToken(doc, offset);
 179.259 +
 179.260 +        if (token != null) {
 179.261 +            String text = token.text().toString();
 179.262 +
 179.263 +            if (text.length() > 0) { // Usually true, but I could have gotten EOF right?
 179.264 +
 179.265 +                return text.charAt(0);
 179.266 +            }
 179.267 +        }
 179.268 +
 179.269 +        return 0;
 179.270 +    }
 179.271 +
 179.272 +    public static Token<? extends PythonTokenId> findNextNonWsNonComment(TokenSequence<? extends PythonTokenId> ts) {
 179.273 +        return findNext(ts, Arrays.asList(PythonTokenId.WHITESPACE, PythonTokenId.NEWLINE, PythonTokenId.COMMENT));
 179.274 +    }
 179.275 +
 179.276 +    public static Token<? extends PythonTokenId> findPreviousNonWsNonComment(TokenSequence<? extends PythonTokenId> ts) {
 179.277 +        return findPrevious(ts, Arrays.asList(PythonTokenId.WHITESPACE, PythonTokenId.NEWLINE, PythonTokenId.COMMENT));
 179.278 +    }
 179.279 +
 179.280 +    public static Token<? extends PythonTokenId> findNext(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> ignores) {
 179.281 +        if (ignores.contains(ts.token().id())) {
 179.282 +            while (ts.moveNext() && ignores.contains(ts.token().id())) {
 179.283 +            }
 179.284 +        }
 179.285 +        return ts.token();
 179.286 +    }
 179.287 +
 179.288 +    public static Token<? extends PythonTokenId> findNextIncluding(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> includes) {
 179.289 +        while (ts.moveNext() && !includes.contains(ts.token().id())) {
 179.290 +        }
 179.291 +        return ts.token();
 179.292 +    }
 179.293 +
 179.294 +    public static Token<? extends PythonTokenId> findPreviousIncluding(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> includes) {
 179.295 +        while (ts.movePrevious() && !includes.contains(ts.token().id())) {
 179.296 +        }
 179.297 +        return ts.token();
 179.298 +    }
 179.299 +
 179.300 +    public static Token<? extends PythonTokenId> findPrevious(TokenSequence<? extends PythonTokenId> ts, List<PythonTokenId> ignores) {
 179.301 +        if (ignores.contains(ts.token().id())) {
 179.302 +            while (ts.movePrevious() && ignores.contains(ts.token().id())) {
 179.303 +            }
 179.304 +        }
 179.305 +        return ts.token();
 179.306 +    }
 179.307 +
 179.308 +    static boolean skipParenthesis(TokenSequence<? extends PythonTokenId> ts) {
 179.309 +        return skipParenthesis(ts, false);
 179.310 +    }
 179.311 +
 179.312 +    /**
 179.313 +     * Tries to skip parenthesis
 179.314 +     */
 179.315 +    public static boolean skipParenthesis(TokenSequence<? extends PythonTokenId> ts, boolean back) {
 179.316 +        int balance = 0;
 179.317 +
 179.318 +        Token<? extends PythonTokenId> token = ts.token();
 179.319 +        if (token == null) {
 179.320 +            return false;
 179.321 +        }
 179.322 +
 179.323 +        TokenId id = token.id();
 179.324 +
 179.325 +        if (id == PythonTokenId.WHITESPACE || id == PythonTokenId.NEWLINE) {
 179.326 +            while ((back ? ts.movePrevious() : ts.moveNext()) && (ts.token().id() == PythonTokenId.WHITESPACE || ts.token().id() == PythonTokenId.NEWLINE)) {
 179.327 +            }
 179.328 +        }
 179.329 +
 179.330 +        // if current token is not left parenthesis
 179.331 +        if (ts.token().id() != (back ? PythonTokenId.RPAREN : PythonTokenId.LPAREN)) {
 179.332 +            return false;
 179.333 +        }
 179.334 +
 179.335 +        do {
 179.336 +            token = ts.token();
 179.337 +            id = token.id();
 179.338 +
 179.339 +            if (id == (back ? PythonTokenId.RPAREN : PythonTokenId.LPAREN)) {
 179.340 +                balance++;
 179.341 +            } else if (id == (back ? PythonTokenId.LPAREN : PythonTokenId.RPAREN)) {
 179.342 +                if (balance == 0) {
 179.343 +                    return false;
 179.344 +                } else if (balance == 1) {
 179.345 +                    //int length = ts.offset() + token.length();
 179.346 +                    if (back) {
 179.347 +                        ts.movePrevious();
 179.348 +                    } else {
 179.349 +                        ts.moveNext();
 179.350 +                    }
 179.351 +                    return true;
 179.352 +                }
 179.353 +
 179.354 +                balance--;
 179.355 +            }
 179.356 +        } while (back ? ts.movePrevious() : ts.moveNext());
 179.357 +
 179.358 +        return false;
 179.359 +    }
 179.360 +
 179.361 +    /** Search forwards in the token sequence until a token of type <code>down</code> is found */
 179.362 +    public static OffsetRange findFwd(BaseDocument doc, TokenSequence<? extends PythonTokenId> ts, TokenId up,
 179.363 +            TokenId down) {
 179.364 +        int balance = 0;
 179.365 +
 179.366 +        while (ts.moveNext()) {
 179.367 +            Token<? extends PythonTokenId> token = ts.token();
 179.368 +            TokenId id = token.id();
 179.369 +
 179.370 +            if (id == up) {
 179.371 +                balance++;
 179.372 +            } else if (id == down) {
 179.373 +                if (balance == 0) {
 179.374 +                    return new OffsetRange(ts.offset(), ts.offset() + token.length());
 179.375 +                }
 179.376 +
 179.377 +                balance--;
 179.378 +            }
 179.379 +        }
 179.380 +
 179.381 +        return OffsetRange.NONE;
 179.382 +    }
 179.383 +
 179.384 +    /** Search backwards in the token sequence until a token of type <code>up</code> is found */
 179.385 +    public static OffsetRange findBwd(BaseDocument doc, TokenSequence<? extends PythonTokenId> ts, TokenId up,
 179.386 +            TokenId down) {
 179.387 +        int balance = 0;
 179.388 +
 179.389 +        while (ts.movePrevious()) {
 179.390 +            Token<? extends PythonTokenId> token = ts.token();
 179.391 +            TokenId id = token.id();
 179.392 +
 179.393 +            if (id == up) {
 179.394 +                if (balance == 0) {
 179.395 +                    return new OffsetRange(ts.offset(), ts.offset() + token.length());
 179.396 +                }
 179.397 +
 179.398 +                balance++;
 179.399 +            } else if (id == down) {
 179.400 +                balance--;
 179.401 +            }
 179.402 +        }
 179.403 +
 179.404 +        return OffsetRange.NONE;
 179.405 +    }
 179.406 +
 179.407 +    /** Compute the balance of begin/end tokens on the line */
 179.408 +    public static int getLineBalance(BaseDocument doc, int offset, TokenId up, TokenId down) {
 179.409 +        try {
 179.410 +            int begin = Utilities.getRowStart(doc, offset);
 179.411 +            int end = Utilities.getRowEnd(doc, offset);
 179.412 +
 179.413 +            TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(doc, begin);
 179.414 +            if (ts == null) {
 179.415 +                return 0;
 179.416 +            }
 179.417 +
 179.418 +            ts.move(begin);
 179.419 +
 179.420 +            if (!ts.moveNext()) {
 179.421 +                return 0;
 179.422 +            }
 179.423 +
 179.424 +            int balance = 0;
 179.425 +
 179.426 +            do {
 179.427 +                Token<? extends PythonTokenId> token = ts.token();
 179.428 +                TokenId id = token.id();
 179.429 +
 179.430 +                if (id == up) {
 179.431 +                    balance++;
 179.432 +                } else if (id == down) {
 179.433 +                    balance--;
 179.434 +                }
 179.435 +            } while (ts.moveNext() && (ts.offset() <= end));
 179.436 +
 179.437 +            return balance;
 179.438 +        } catch (BadLocationException ble) {
 179.439 +            Exceptions.printStackTrace(ble);
 179.440 +
 179.441 +            return 0;
 179.442 +        }
 179.443 +    }
 179.444 +
 179.445 +    /**
 179.446 +     * The same as braceBalance but generalized to any pair of matching
 179.447 +     * tokens.
 179.448 +     * @param open the token that increses the count
 179.449 +     * @param close the token that decreses the count
 179.450 +     */
 179.451 +    public static int getTokenBalance(BaseDocument doc, TokenId open, TokenId close, int offset)
 179.452 +            throws BadLocationException {
 179.453 +        TokenSequence<? extends PythonTokenId> ts = PythonLexerUtils.getPythonSequence(doc, 0);
 179.454 +        if (ts == null) {
 179.455 +            return 0;
 179.456 +        }
 179.457 +
 179.458 +        // XXX Why 0? Why not offset?
 179.459 +        ts.moveIndex(0);
 179.460 +
 179.461 +        if (!ts.moveNext()) {
 179.462 +            return 0;
 179.463 +        }
 179.464 +
 179.465 +        int balance = 0;
 179.466 +
 179.467 +        do {
 179.468 +            Token t = ts.token();
 179.469 +
 179.470 +            if (t.id() == open) {
 179.471 +                balance++;
 179.472 +            } else if (t.id() == close) {
 179.473 +                balance--;
 179.474 +            }
 179.475 +        } while (ts.moveNext());
 179.476 +
 179.477 +        return balance;
 179.478 +    }
 179.479 +
 179.480 +    /**
 179.481 +     * Return true iff the line for the given offset is a JavaScript comment line.
 179.482 +     * This will return false for lines that contain comments (even when the
 179.483 +     * offset is within the comment portion) but also contain code.
 179.484 +     */
 179.485 +    public static boolean isCommentOnlyLine(BaseDocument doc, int offset)
 179.486 +            throws BadLocationException {
 179.487 +        int begin = Utilities.getRowFirstNonWhite(doc, offset);
 179.488 +
 179.489 +        if (begin == -1) {
 179.490 +            return false; // whitespace only
 179.491 +        }
 179.492 +
 179.493 +        Token<? extends PythonTokenId> token = PythonLexerUtils.getToken(doc, begin);
 179.494 +        if (token != null) {
 179.495 +            return token.id() == PythonTokenId.COMMENT;
 179.496 +        }
 179.497 +
 179.498 +        return false;
 179.499 +    }
 179.500 +
 179.501 +    /**
 179.502 +     * Back up to the first space character prior to the given offset - as long as
 179.503 +     * it's on the same line!  If there's only leading whitespace on the line up
 179.504 +     * to the lex offset, return the offset itself
 179.505 +     * @todo Rewrite this now that I have a separate newline token, EOL, that I can
 179.506 +     *   break on - no need to call Utilities.getRowStart.
 179.507 +     */
 179.508 +    public static int findSpaceBegin(BaseDocument doc, int lexOffset) {
 179.509 +        TokenSequence ts = getPythonSequence(doc, lexOffset);
 179.510 +        if (ts == null) {
 179.511 +            return lexOffset;
 179.512 +        }
 179.513 +        boolean allowPrevLine = false;
 179.514 +        int lineStart;
 179.515 +        try {
 179.516 +            lineStart = Utilities.getRowStart(doc, Math.min(lexOffset, doc.getLength()));
 179.517 +            int prevLast = lineStart - 1;
 179.518 +            if (lineStart > 0) {
 179.519 +                prevLast = Utilities.getRowLastNonWhite(doc, lineStart - 1);
 179.520 +                if (prevLast != -1) {
 179.521 +                    char c = doc.getText(prevLast, 1).charAt(0);
 179.522 +                    if (c == ',') {
 179.523 +                        // Arglist continuation? // TODO : check lexing
 179.524 +                        allowPrevLine = true;
 179.525 +                    }
 179.526 +                }
 179.527 +            }
 179.528 +            if (!allowPrevLine) {
 179.529 +                int firstNonWhite = Utilities.getRowFirstNonWhite(doc, lineStart);
 179.530 +                if (lexOffset <= firstNonWhite || firstNonWhite == -1) {
 179.531 +                    return lexOffset;
 179.532 +                }
 179.533 +            } else {
 179.534 +                // Make lineStart so small that Math.max won't cause any problems
 179.535 +                int firstNonWhite = Utilities.getRowFirstNonWhite(doc, lineStart);
 179.536 +                if (prevLast >= 0 && (lexOffset <= firstNonWhite || firstNonWhite == -1)) {
 179.537 +                    return prevLast + 1;
 179.538 +                }
 179.539 +                lineStart = 0;
 179.540 +            }
 179.541 +        } catch (BadLocationException ble) {
 179.542 +            Exceptions.printStackTrace(ble);
 179.543 +            return lexOffset;
 179.544 +        }
 179.545 +        ts.move(lexOffset);
 179.546 +        if (ts.moveNext()) {
 179.547 +            if (lexOffset > ts.offset()) {
 179.548 +                // We're in the middle of a token
 179.549 +                return Math.max((ts.token().id() == PythonTokenId.WHITESPACE) ? ts.offset() : lexOffset, lineStart);
 179.550 +            }
 179.551 +            while (ts.movePrevious()) {
 179.552 +                Token token = ts.token();
 179.553 +                if (token.id() != PythonTokenId.WHITESPACE) {
 179.554 +                    return Math.max(ts.offset() + token.length(), lineStart);
 179.555 +                }
 179.556 +            }
 179.557 +        }
 179.558 +
 179.559 +        return lexOffset;
 179.560 +    }
 179.561 +
 179.562 +     public static boolean isKeywordOrBuiltin(CharSequence name) {
 179.563 +        return PythonLexer.isKeywordOrBuiltin(name);
 179.564 +    }
 179.565 +}
   180.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   180.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/PythonStringLexer.java	Mon Sep 21 13:01:16 2015 +0200
   180.3 @@ -0,0 +1,292 @@
   180.4 +/*
   180.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   180.6 + *
   180.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   180.8 + *
   180.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  180.10 + * Other names may be trademarks of their respective owners.
  180.11 + *
  180.12 + * The contents of this file are subject to the terms of either the GNU
  180.13 + * General Public License Version 2 only ("GPL") or the Common
  180.14 + * Development and Distribution License("CDDL") (collectively, the
  180.15 + * "License"). You may not use this file except in compliance with the
  180.16 + * License. You can obtain a copy of the License at
  180.17 + * http://www.netbeans.org/cddl-gplv2.html
  180.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  180.19 + * specific language governing permissions and limitations under the
  180.20 + * License.  When distributing the software, include this License Header
  180.21 + * Notice in each file and include the License file at
  180.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  180.23 + * particular file as subject to the "Classpath" exception as provided
  180.24 + * by Oracle in the GPL Version 2 section of the License file that
  180.25 + * accompanied this code. If applicable, add the following below the
  180.26 + * License Header, with the fields enclosed by brackets [] replaced by
  180.27 + * your own identifying information:
  180.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  180.29 + *
  180.30 + * Contributor(s):
  180.31 + *
  180.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  180.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  180.34 + * Microsystems, Inc. All Rights Reserved.
  180.35 + *
  180.36 + * If you wish your version of this file to be governed by only the CDDL
  180.37 + * or only the GPL Version 2, indicate your decision by adding
  180.38 + * "[Contributor] elects to include this software in this distribution
  180.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  180.40 + * single choice of license, a recipient has the option to distribute
  180.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  180.42 + * to extend the choice of license to its licensees as provided above.
  180.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  180.44 + * Version 2 license, then the option applies only if the new code is
  180.45 + * made subject to such option by the copyright holder.
  180.46 + */
  180.47 +package org.netbeans.modules.python.source.lexer;
  180.48 +
  180.49 +import org.netbeans.api.lexer.Token;
  180.50 +import org.netbeans.spi.lexer.Lexer;
  180.51 +import org.netbeans.spi.lexer.LexerInput;
  180.52 +import org.netbeans.spi.lexer.LexerRestartInfo;
  180.53 +import org.netbeans.spi.lexer.TokenFactory;
  180.54 +
  180.55 +/**
  180.56 + * A lexer for python strings. Highlights escape sequences, and recognizes
  180.57 + * doctest sections and highlights these as well.
  180.58 + *   http://docs.python.org/lib/module-doctest.html
  180.59 + *
  180.60 + * @todo Track whether strings are raw or not, and don't do escape sequence
  180.61 + *  highlighting in raw strings
  180.62 + *
  180.63 + * @author Tor Norbye
  180.64 + */
  180.65 +public class PythonStringLexer implements Lexer<PythonStringTokenId> {
  180.66 +    private static final int EOF = LexerInput.EOF;
  180.67 +    private final LexerInput input;
  180.68 +    private final TokenFactory<PythonStringTokenId> tokenFactory;
  180.69 +    private final boolean substituting;
  180.70 +
  180.71 +    /**
  180.72 +     * A Lexer for Python strings
  180.73 +     * @param substituting If true, handle substitution rules for double quoted strings, otherwise
  180.74 +     *    single quoted strings.
  180.75 +     */
  180.76 +    public PythonStringLexer(LexerRestartInfo<PythonStringTokenId> info, boolean substituting) {
  180.77 +        this.input = info.input();
  180.78 +        this.tokenFactory = info.tokenFactory();
  180.79 +        this.substituting = substituting;
  180.80 +        assert (info.state() == null); // passed argument always null
  180.81 +    }
  180.82 +
  180.83 +    @Override
  180.84 +    public Object state() {
  180.85 +        return null;
  180.86 +    }
  180.87 +
  180.88 +    @Override
  180.89 +    public Token<PythonStringTokenId> nextToken() {
  180.90 +        boolean inWord = false;
  180.91 +        while (true) {
  180.92 +            int ch = input.read();
  180.93 +
  180.94 +            switch (ch) {
  180.95 +            case EOF:
  180.96 +
  180.97 +                if (input.readLength() > 0) {
  180.98 +                    return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
  180.99 +                            input.readLength());
 180.100 +                } else {
 180.101 +                    return null;
 180.102 +                }
 180.103 +
 180.104 +            case '>':
 180.105 +                // Look for doctest:  \n, whitespace, >>>{embedded python}\n
 180.106 +                int initialReadLength = input.readLength();
 180.107 +                input.read();
 180.108 +                if (ch == '>') {
 180.109 +                    ch = input.read();
 180.110 +                    if (ch == '>') {
 180.111 +                        if (input.readLength() > 3) {
 180.112 +                            input.backup(3);
 180.113 +                            // Finish this token such that we can do a dedicated token for the ">>>" line.
 180.114 +                            return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
 180.115 +                                    input.readLength());
 180.116 +                        }
 180.117 +                        // Find end...
 180.118 +                        boolean nonempty = false;
 180.119 +                        while (true) {
 180.120 +                            ch = input.read();
 180.121 +                            if (ch == EOF) {
 180.122 +                                break;
 180.123 +                            } else if (ch == '\n') {
 180.124 +                                if (nonempty) {
 180.125 +                                    input.backup(1); // Don't include the \n
 180.126 +                                    return tokenFactory.createToken(PythonStringTokenId.EMBEDDED_PYTHON,
 180.127 +                                            input.readLength());
 180.128 +
 180.129 +                                }
 180.130 +                                break;
 180.131 +                            } else if (!Character.isWhitespace(ch)) {
 180.132 +                                nonempty = true;
 180.133 +                            }
 180.134 +                        }
 180.135 +                    }
 180.136 +                }
 180.137 +                if (input.readLength() > initialReadLength) {
 180.138 +                    input.backup(input.readLength() - initialReadLength);
 180.139 +                } else {
 180.140 +                    return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
 180.141 +                            input.readLength());
 180.142 +                }
 180.143 +                break;
 180.144 +
 180.145 +            case '\\':
 180.146 +
 180.147 +                if (input.readLength() > 1) { // already read some text
 180.148 +                    input.backup(1);
 180.149 +
 180.150 +                    return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
 180.151 +                            input.readLength());
 180.152 +                }
 180.153 +
 180.154 +                ch = input.read();
 180.155 +                if (ch == EOF) {
 180.156 +                    return tokenFactory.createToken(PythonStringTokenId.STRING_INVALID,
 180.157 +                            input.readLength());
 180.158 +                } else {
 180.159 +                    return tokenFactory.createToken(PythonStringTokenId.STRING_ESCAPE,
 180.160 +                            input.readLength());
 180.161 +                }
 180.162 +
 180.163 +            case 'f': // ftp:
 180.164 +            case 'm': // mailto:
 180.165 +            case 'w': // www.
 180.166 +            case 'h': { // http links. TODO: link:, ftp:, mailto:, and www.
 180.167 +
 180.168 +                if (inWord) {
 180.169 +                    break;
 180.170 +                }
 180.171 +
 180.172 +                int originalLength = input.readLength();
 180.173 +                boolean foundLinkBegin = false;
 180.174 +
 180.175 +                if (ch == 'h') { // http:
 180.176 +
 180.177 +                    if (input.read() == 't') {
 180.178 +                        if (input.read() == 't') {
 180.179 +                            if (input.read() == 'p') {
 180.180 +                                int r = input.read();
 180.181 +                                if (r == ':') {
 180.182 +                                    foundLinkBegin = true;
 180.183 +                                } else if (r == 's') {
 180.184 +                                    if (input.read() == ':') {
 180.185 +                                        foundLinkBegin = true;
 180.186 +                                    } else {
 180.187 +                                        input.backup(5);
 180.188 +                                    }
 180.189 +                                } else {
 180.190 +                                    input.backup(4);
 180.191 +                                }
 180.192 +                            } else {
 180.193 +                                input.backup(3);
 180.194 +                            }
 180.195 +                        } else {
 180.196 +                            input.backup(2);
 180.197 +                        }
 180.198 +                    } else {
 180.199 +                        input.backup(1);
 180.200 +                    }
 180.201 +                } else if (ch == 'f') { // ftp:
 180.202 +
 180.203 +                    if (input.read() == 't') {
 180.204 +                        if (input.read() == 'p') {
 180.205 +                            if (input.read() == ':') {
 180.206 +                                foundLinkBegin = true;
 180.207 +                            } else {
 180.208 +                                input.backup(3);
 180.209 +                            }
 180.210 +                        } else {
 180.211 +                            input.backup(2);
 180.212 +                        }
 180.213 +                    } else {
 180.214 +                        input.backup(1);
 180.215 +                    }
 180.216 +                } else if (ch == 'm') { // mailto:
 180.217 +
 180.218 +                    if (input.read() == 'a') {
 180.219 +                        if (input.read() == 'i') {
 180.220 +                            if (input.read() == 'l') {
 180.221 +                                if (input.read() == 't') {
 180.222 +                                    if (input.read() == 'o') {
 180.223 +                                        if (input.read() == ':') {
 180.224 +                                            foundLinkBegin = true;
 180.225 +                                        } else {
 180.226 +                                            input.backup(6);
 180.227 +                                        }
 180.228 +                                    } else {
 180.229 +                                        input.backup(5);
 180.230 +                                    }
 180.231 +                                } else {
 180.232 +                                    input.backup(4);
 180.233 +                                }
 180.234 +                            } else {
 180.235 +                                input.backup(3);
 180.236 +                            }
 180.237 +                        } else {
 180.238 +                            input.backup(2);
 180.239 +                        }
 180.240 +                    } else {
 180.241 +                        input.backup(1);
 180.242 +                    }
 180.243 +                } else if (ch == 'w') { // www.
 180.244 +
 180.245 +                    if (input.read() == 'w') {
 180.246 +                        if (input.read() == 'w') {
 180.247 +                            if (input.read() == '.') {
 180.248 +                                foundLinkBegin = true;
 180.249 +                            } else {
 180.250 +                                input.backup(3);
 180.251 +                            }
 180.252 +                        } else {
 180.253 +                            input.backup(2);
 180.254 +                        }
 180.255 +                    } else {
 180.256 +                        input.backup(1);
 180.257 +                    }
 180.258 +                }
 180.259 +
 180.260 +                if (foundLinkBegin) {
 180.261 +                    while (ch != EOF) {
 180.262 +                        ch = input.read();
 180.263 +
 180.264 +                        if ((ch == ']') || (ch == ')') || Character.isWhitespace(ch) ||
 180.265 +                                (ch == '\'') || (ch == '"')) {
 180.266 +                            input.backup(1);
 180.267 +
 180.268 +                            break;
 180.269 +                        }
 180.270 +                    }
 180.271 +
 180.272 +                    if (originalLength > 1) {
 180.273 +                        input.backup(input.readLengthEOF() - originalLength + 1);
 180.274 +
 180.275 +                        return tokenFactory.createToken(PythonStringTokenId.STRING_TEXT,
 180.276 +                                input.readLength());
 180.277 +                    }
 180.278 +
 180.279 +                    if (input.readLength() > 2) {
 180.280 +                        return tokenFactory.createToken(PythonStringTokenId.URL,
 180.281 +                                input.readLength());
 180.282 +                    }
 180.283 +                }
 180.284 +                break;
 180.285 +            }
 180.286 +            }
 180.287 +
 180.288 +            inWord = Character.isJavaIdentifierPart(ch);
 180.289 +        }
 180.290 +    }
 180.291 +
 180.292 +    @Override
 180.293 +    public void release() {
 180.294 +    }
 180.295 +}
   181.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   181.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/PythonStringTokenId.java	Mon Sep 21 13:01:16 2015 +0200
   181.3 @@ -0,0 +1,125 @@
   181.4 +/*
   181.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   181.6 + *
   181.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   181.8 + *
   181.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  181.10 + * Other names may be trademarks of their respective owners.
  181.11 + *
  181.12 + * The contents of this file are subject to the terms of either the GNU
  181.13 + * General Public License Version 2 only ("GPL") or the Common
  181.14 + * Development and Distribution License("CDDL") (collectively, the
  181.15 + * "License"). You may not use this file except in compliance with the
  181.16 + * License. You can obtain a copy of the License at
  181.17 + * http://www.netbeans.org/cddl-gplv2.html
  181.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  181.19 + * specific language governing permissions and limitations under the
  181.20 + * License.  When distributing the software, include this License Header
  181.21 + * Notice in each file and include the License file at
  181.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  181.23 + * particular file as subject to the "Classpath" exception as provided
  181.24 + * by Oracle in the GPL Version 2 section of the License file that
  181.25 + * accompanied this code. If applicable, add the following below the
  181.26 + * License Header, with the fields enclosed by brackets [] replaced by
  181.27 + * your own identifying information:
  181.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  181.29 + *
  181.30 + * Contributor(s):
  181.31 + *
  181.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  181.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  181.34 + * Microsystems, Inc. All Rights Reserved.
  181.35 + *
  181.36 + * If you wish your version of this file to be governed by only the CDDL
  181.37 + * or only the GPL Version 2, indicate your decision by adding
  181.38 + * "[Contributor] elects to include this software in this distribution
  181.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  181.40 + * single choice of license, a recipient has the option to distribute
  181.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  181.42 + * to extend the choice of license to its licensees as provided above.
  181.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  181.44 + * Version 2 license, then the option applies only if the new code is
  181.45 + * made subject to such option by the copyright holder.
  181.46 + */
  181.47 +package org.netbeans.modules.python.source.lexer;
  181.48 +
  181.49 +import java.util.Collection;
  181.50 +import java.util.EnumSet;
  181.51 +import java.util.Map;
  181.52 +
  181.53 +import org.netbeans.api.lexer.InputAttributes;
  181.54 +import org.netbeans.api.lexer.Language;
  181.55 +import org.netbeans.api.lexer.LanguagePath;
  181.56 +import org.netbeans.api.lexer.Token;
  181.57 +import org.netbeans.api.lexer.TokenId;
  181.58 +import org.netbeans.api.lexer.TokenUtilities;
  181.59 +import org.netbeans.spi.lexer.LanguageEmbedding;
  181.60 +import org.netbeans.spi.lexer.LanguageHierarchy;
  181.61 +import org.netbeans.spi.lexer.Lexer;
  181.62 +import org.netbeans.spi.lexer.LexerRestartInfo;
  181.63 +
  181.64 +/**
  181.65 + *
  181.66 + * @author Tor Norbye
  181.67 + */
  181.68 +public enum PythonStringTokenId implements TokenId {
  181.69 +    STRING_TEXT("string"),
  181.70 +    STRING_ESCAPE("string-escape"),
  181.71 +    STRING_INVALID("string-escape-invalid"),
  181.72 +    URL("url"),
  181.73 +    EMBEDDED_PYTHON("string");
  181.74 +    private final String primaryCategory;
  181.75 +
  181.76 +    PythonStringTokenId() {
  181.77 +        this(null);
  181.78 +    }
  181.79 +
  181.80 +    PythonStringTokenId(String primaryCategory) {
  181.81 +        this.primaryCategory = primaryCategory;
  181.82 +    }
  181.83 +
  181.84 +    @Override
  181.85 +    public String primaryCategory() {
  181.86 +        return primaryCategory;
  181.87 +    }
  181.88 +    public static final Language<PythonStringTokenId> language =
  181.89 +            new LanguageHierarchy<PythonStringTokenId>() {
  181.90 +                @Override
  181.91 +                protected Collection<PythonStringTokenId> createTokenIds() {
  181.92 +                    return EnumSet.allOf(PythonStringTokenId.class);
  181.93 +                }
  181.94 +
  181.95 +                @Override
  181.96 +                protected Map<String, Collection<PythonStringTokenId>> createTokenCategories() {
  181.97 +                    return null; // no extra categories
  181.98 +                }
  181.99 +
 181.100 +                @Override
 181.101 +                protected Lexer<PythonStringTokenId> createLexer(
 181.102 +                        LexerRestartInfo<PythonStringTokenId> info) {
 181.103 +                    return new PythonStringLexer(info, true);
 181.104 +                }
 181.105 +
 181.106 +                @Override
 181.107 +                protected LanguageEmbedding<?> embedding(
 181.108 +                        Token<PythonStringTokenId> token, LanguagePath languagePath,
 181.109 +                        InputAttributes inputAttributes) {
 181.110 +                    PythonStringTokenId id = token.id();
 181.111 +
 181.112 +                    if (id == EMBEDDED_PYTHON && token.text() != null) {
 181.113 +                        return LanguageEmbedding.create(PythonTokenId.language(), 3, 0); // 3: Exlude ">>>" prefix
 181.114 +                    }
 181.115 +
 181.116 +                    return null; // No embedding
 181.117 +                }
 181.118 +
 181.119 +                @Override
 181.120 +                public String mimeType() {
 181.121 +                    return "text/x-python-string"; // NOI18N
 181.122 +                }
 181.123 +            }.language();
 181.124 +
 181.125 +    public static Language<PythonStringTokenId> language() {
 181.126 +        return language;
 181.127 +    }
 181.128 +}
   182.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   182.2 +++ b/python.source/src/org/netbeans/modules/python/source/lexer/PythonTokenId.java	Mon Sep 21 13:01:16 2015 +0200
   182.3 @@ -0,0 +1,206 @@
   182.4 +/*
   182.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   182.6 + *
   182.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   182.8 + *
   182.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  182.10 + * Other names may be trademarks of their respective owners.
  182.11 + *
  182.12 + * The contents of this file are subject to the terms of either the GNU
  182.13 + * General Public License Version 2 only ("GPL") or the Common
  182.14 + * Development and Distribution License("CDDL") (collectively, the
  182.15 + * "License"). You may not use this file except in compliance with the
  182.16 + * License. You can obtain a copy of the License at
  182.17 + * http://www.netbeans.org/cddl-gplv2.html
  182.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  182.19 + * specific language governing permissions and limitations under the
  182.20 + * License.  When distributing the software, include this License Header
  182.21 + * Notice in each file and include the License file at
  182.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  182.23 + * particular file as subject to the "Classpath" exception as provided
  182.24 + * by Oracle in the GPL Version 2 section of the License file that
  182.25 + * accompanied this code. If applicable, add the following below the
  182.26 + * License Header, with the fields enclosed by brackets [] replaced by
  182.27 + * your own identifying information:
  182.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  182.29 + *
  182.30 + * Contributor(s):
  182.31 + *
  182.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  182.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  182.34 + * Microsystems, Inc. All Rights Reserved.
  182.35 + *
  182.36 + * If you wish your version of this file to be governed by only the CDDL
  182.37 + * or only the GPL Version 2, indicate your decision by adding
  182.38 + * "[Contributor] elects to include this software in this distribution
  182.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  182.40 + * single choice of license, a recipient has the option to distribute
  182.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  182.42 + * to extend the choice of license to its licensees as provided above.
  182.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  182.44 + * Version 2 license, then the option applies only if the new code is
  182.45 + * made subject to such option by the copyright holder.
  182.46 + */
  182.47 +package org.netbeans.modules.python.source.lexer;
  182.48 +
  182.49 +import java.util.Collection;
  182.50 +import java.util.EnumSet;
  182.51 +import java.util.HashMap;
  182.52 +import java.util.Map;
  182.53 +import org.netbeans.api.lexer.InputAttributes;
  182.54 +import org.netbeans.api.lexer.Language;
  182.55 +import org.netbeans.api.lexer.LanguagePath;
  182.56 +import org.netbeans.api.lexer.Token;
  182.57 +import org.netbeans.api.lexer.TokenId;
  182.58 +import org.netbeans.modules.python.api.PythonMIMEResolver;
  182.59 +import org.netbeans.modules.python.source.PythonUtils;
  182.60 +import org.netbeans.spi.lexer.LanguageEmbedding;
  182.61 +import org.netbeans.spi.lexer.LanguageHierarchy;
  182.62 +import org.netbeans.spi.lexer.Lexer;
  182.63 +import org.netbeans.spi.lexer.LexerInput;
  182.64 +import org.netbeans.spi.lexer.LexerRestartInfo;
  182.65 +
  182.66 +import org.netbeans.spi.lexer.TokenFactory;
  182.67 +import org.openide.filesystems.FileObject;
  182.68 +import static org.netbeans.modules.python.source.lexer.PythonLexer.*;
  182.69 +
  182.70 +/**
  182.71 + * @todo add the rest of the tokens
  182.72 + *
  182.73 + * @author Martin Adamek
  182.74 + * @author alley
  182.75 + */
  182.76 +public enum PythonTokenId implements TokenId {
  182.77 +    ERROR(null, ERROR_CAT),
  182.78 +    IDENTIFIER(null, IDENTIFIER_CAT),
  182.79 +    INT_LITERAL(null, NUMBER_CAT),
  182.80 +    FLOAT_LITERAL(null, NUMBER_CAT),
  182.81 +    STRING_LITERAL(null, STRING_CAT),
  182.82 +    WHITESPACE(null, WHITESPACE_CAT),
  182.83 +    NEWLINE(null, WHITESPACE_CAT),
  182.84 +    DECORATOR(null, OPERATOR_CAT), // NOI18N
  182.85 +    //    CONTINUED_LINE(null, WHITESPACE_CAT), // NOI18N
  182.86 +    COMMENT(null, COMMENT_CAT),
  182.87 +    BUILTIN_FUNCTION(null, KEYWORD_CAT), // NOI18N
  182.88 +    LPAREN("(", SEPARATOR_CAT), // NOI18N
  182.89 +    RPAREN(")", SEPARATOR_CAT), // NOI18N
  182.90 +    LBRACE("{", SEPARATOR_CAT), // NOI18N
  182.91 +    RBRACE("}", SEPARATOR_CAT), // NOI18N
  182.92 +    LBRACKET("[", SEPARATOR_CAT), // NOI18N
  182.93 +    RBRACKET("]", SEPARATOR_CAT), // NOI18N
  182.94 +    STRING_BEGIN(null, STRING_CAT),
  182.95 +    STRING_END(null, STRING_CAT),
  182.96 +    // Cheating: out of laziness just map all keywords returning from Jython
  182.97 +    // into a single KEYWORD token; eventually we will have separate tokens
  182.98 +    // for each here such that the various helper methods for formatting,
  182.99 +    // smart indent, brace matching etc. can refer to specific keywords
 182.100 +    ANY_KEYWORD(null, KEYWORD_CAT),
 182.101 +    ANY_OPERATOR(null, OPERATOR_CAT),
 182.102 +    DEF("def", KEYWORD_CAT), // NOI18N
 182.103 +    CLASS("class", KEYWORD_CAT), // NOI18N
 182.104 +    IF("if", KEYWORD_CAT), // NOI18N
 182.105 +    ELSE("else", KEYWORD_CAT), // NOI18N
 182.106 +    ELIF("elif", KEYWORD_CAT), // NOI18N
 182.107 +    RAISE("raise", KEYWORD_CAT), // NOI18N
 182.108 +    PASS("pass", KEYWORD_CAT), // NOI18N
 182.109 +    RETURN("return", KEYWORD_CAT), // NOI18N
 182.110 +    EXCEPT("except", KEYWORD_CAT), // NOI18N
 182.111 +    FINALLY("finally", KEYWORD_CAT), // NOI18N
 182.112 +    IMPORT("import", KEYWORD_CAT), // NOI18N
 182.113 +    FROM("from", KEYWORD_CAT), // NOI18N
 182.114 +    TRUE("True", KEYWORD_CAT), // NOI18N
 182.115 +    FALSE("False", KEYWORD_CAT), // NOI18N
 182.116 +    NONE("None", KEYWORD_CAT), // NOI18N
 182.117 +    TRY("try", KEYWORD_CAT), // NOI18N
 182.118 +    DOT(".", OPERATOR_CAT), // NOI18N
 182.119 +    COMMA(",", OPERATOR_CAT), // NOI18N
 182.120 +    COLON(":", OPERATOR_CAT), // NOI18N
 182.121 +    ESC("\\", OPERATOR_CAT), // NOI18N
 182.122 +
 182.123 +    // Non-unary operators which indicate a line continuation if used at the end of a line
 182.124 +    NONUNARY_OP(null, OPERATOR_CAT);
 182.125 +    private final String fixedText;
 182.126 +    private final String primaryCategory;
 182.127 +
 182.128 +    PythonTokenId(String fixedText, String primaryCategory) {
 182.129 +        this.fixedText = fixedText;
 182.130 +        this.primaryCategory = primaryCategory;
 182.131 +    }
 182.132 +
 182.133 +    @Override
 182.134 +    public String primaryCategory() {
 182.135 +        return primaryCategory;
 182.136 +    }
 182.137 +
 182.138 +    public String fixedText() {
 182.139 +        return fixedText;
 182.140 +    }
 182.141 +    private static final Language<PythonTokenId> language =
 182.142 +            new LanguageHierarchy<PythonTokenId>() {
 182.143 +                @Override
 182.144 +                protected String mimeType() {
 182.145 +                    return PythonMIMEResolver.PYTHON_MIME_TYPE;
 182.146 +                }
 182.147 +
 182.148 +                @Override
 182.149 +                protected Collection<PythonTokenId> createTokenIds() {
 182.150 +                    return EnumSet.allOf(PythonTokenId.class);
 182.151 +                }
 182.152 +
 182.153 +                @Override
 182.154 +                protected Map<String, Collection<PythonTokenId>> createTokenCategories() {
 182.155 +                    Map<String, Collection<PythonTokenId>> cats =
 182.156 +                            new HashMap<>();
 182.157 +                    return cats;
 182.158 +                }
 182.159 +
 182.160 +                @Override
 182.161 +                protected Lexer<PythonTokenId> createLexer(LexerRestartInfo<PythonTokenId> info) {
 182.162 +                    FileObject fileObject = (FileObject)info.getAttributeValue(FileObject.class);
 182.163 +                    final TokenFactory<PythonTokenId> tokenFactory = info.tokenFactory();
 182.164 +                    final LexerInput input = info.input();
 182.165 +                    // Lex .rst files just as literal strings
 182.166 +                    if (fileObject != null && PythonUtils.isRstFile(fileObject)) {
 182.167 +                        return new Lexer<PythonTokenId>() {
 182.168 +                            @Override
 182.169 +                            public Token<PythonTokenId> nextToken() {
 182.170 +                                if (input.read() == LexerInput.EOF) {
 182.171 +                                    return null;
 182.172 +                                }
 182.173 +                                while (input.read() != LexerInput.EOF) {
 182.174 +                                    ;
 182.175 +                                }
 182.176 +                                return tokenFactory.createToken(PythonTokenId.STRING_LITERAL, input.readLength());
 182.177 +                            }
 182.178 +
 182.179 +                            @Override
 182.180 +                            public Object state() {
 182.181 +                                return null;
 182.182 +                            }
 182.183 +
 182.184 +                            @Override
 182.185 +                            public void release() {
 182.186 +                            }
 182.187 +                        };
 182.188 +                    }
 182.189 +                    return new PythonLexer(info);
 182.190 +                }
 182.191 +
 182.192 +                @Override
 182.193 +                protected LanguageEmbedding<?> embedding(Token<PythonTokenId> token,
 182.194 +                        LanguagePath languagePath, InputAttributes inputAttributes) {
 182.195 +                    PythonTokenId id = token.id();
 182.196 +                    if (id == STRING_LITERAL) {
 182.197 +                        return LanguageEmbedding.create(PythonStringTokenId.language, 0, 0);
 182.198 +                    } else if (id == COMMENT) {
 182.199 +                        return LanguageEmbedding.create(PythonCommentTokenId.language(), 1, 0);
 182.200 +                    }
 182.201 +
 182.202 +                    return null; // No embedding
 182.203 +                }
 182.204 +            }.language();
 182.205 +
 182.206 +    public static Language<PythonTokenId> language() {
 182.207 +        return language;
 182.208 +    }
 182.209 +}
   183.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   183.2 +++ b/python.source/src/org/netbeans/modules/python/source/queries/DeprecationQuery.java	Mon Sep 21 13:01:16 2015 +0200
   183.3 @@ -0,0 +1,169 @@
   183.4 +/*
   183.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   183.6 + *
   183.7 + * Copyright 2015 Oracle and/or its affiliates. All rights reserved.
   183.8 + *
   183.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  183.10 + * Other names may be trademarks of their respective owners.
  183.11 + *
  183.12 + * The contents of this file are subject to the terms of either the GNU
  183.13 + * General Public License Version 2 only ("GPL") or the Common
  183.14 + * Development and Distribution License("CDDL") (collectively, the
  183.15 + * "License"). You may not use this file except in compliance with the
  183.16 + * License. You can obtain a copy of the License at
  183.17 + * http://www.netbeans.org/cddl-gplv2.html
  183.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  183.19 + * specific language governing permissions and limitations under the
  183.20 + * License.  When distributing the software, include this License Header
  183.21 + * Notice in each file and include the License file at
  183.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  183.23 + * particular file as subject to the "Classpath" exception as provided
  183.24 + * by Oracle in the GPL Version 2 section of the License file that
  183.25 + * accompanied this code. If applicable, add the following below the
  183.26 + * License Header, with the fields enclosed by brackets [] replaced by
  183.27 + * your own identifying information:
  183.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  183.29 + *
  183.30 + * If you wish your version of this file to be governed by only the CDDL
  183.31 + * or only the GPL Version 2, indicate your decision by adding
  183.32 + * "[Contributor] elects to include this software in this distribution
  183.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  183.34 + * single choice of license, a recipient has the option to distribute
  183.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  183.36 + * to extend the choice of license to its licensees as provided above.
  183.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  183.38 + * Version 2 license, then the option applies only if the new code is
  183.39 + * made subject to such option by the copyright holder.
  183.40 + *
  183.41 + * Contributor(s):
  183.42 + *
  183.43 + * Portions Copyrighted 2015 Sun Microsystems, Inc.
  183.44 + */
  183.45 +package org.netbeans.modules.python.source.queries;
  183.46 +
  183.47 +import java.util.HashMap;
  183.48 +import java.util.Map;
  183.49 +
  183.50 +/**
  183.51 + *
  183.52 + * @author Ralph Ruijs
  183.53 + */
  183.54 +public final class DeprecationQuery {
  183.55 +    private static final Map<String, String> DEPRECATED = new HashMap<>();
  183.56 +
  183.57 +
  183.58 +    static {
  183.59 +        for (String module : new String[]{"cl", "sv", "timing"}) {
  183.60 +            DEPRECATED.put(module, "Listed as obsolete in the library documentation");
  183.61 +        }
  183.62 +
  183.63 +        for (String module : new String[]{
  183.64 +                    "addpack", "cmp", "cmpcache", "codehack", "dircmp", "dump", "find", "fmt",
  183.65 +                    "grep", "lockfile", "newdir", "ni", "packmail", "Para", "poly",
  183.66 +                    "rand", "reconvert", "regex", "regsub", "statcache", "tb", "tzparse",
  183.67 +                    "util", "whatsound", "whrandom", "zmod"}) {
  183.68 +            DEPRECATED.put(module, "Obsolete module, removed in Python 2.5");
  183.69 +
  183.70 +        }
  183.71 +
  183.72 +        for (String module : new String[]{"gopherlib", "rgbimg", "macfs"}) {
  183.73 +            DEPRECATED.put(module, "Obsolete module, removed in Python 2.6");
  183.74 +        }
  183.75 +
  183.76 +        /*
  183.77 +        al.rst:    The :mod:`al` module has been deprecated for removal in Python 3.0.
  183.78 +        al.rst:   The :mod:`AL` module has been deprecated for removal in Python 3.0.
  183.79 +        bsddb.rst:    The :mod:`bsddb` module has been deprecated for removal in Python 3.0.
  183.80 +        cd.rst:    The :mod:`cd` module has been deprecated for removal in Python 3.0.
  183.81 +        dbhash.rst:    The :mod:`dbhash` module has been deprecated for removal in Python 3.0.
  183.82 +        fl.rst:    The :mod:`fl` module has been deprecated for removal in Python 3.0.
  183.83 +        fl.rst:    The :mod:`FL` module has been deprecated for removal in Python 3.0.
  183.84 +        fl.rst:    The :mod:`flp` module has been deprecated for removal in Python 3.0.
  183.85 +        fm.rst:   The :mod:`fm` module has been deprecated for removal in Python 3.0.
  183.86 +        gl.rst:    The :mod:`gl` module has been deprecated for removal in Python 3.0.
  183.87 +        gl.rst:    The :mod:`DEVICE` module has been deprecated for removal in Python 3.0.
  183.88 +        gl.rst:    The :mod:`GL` module has been deprecated for removal in Python 3.0.
  183.89 +        imgfile.rst:   The :mod:`imgfile` module has been deprecated for removal in Python 3.0.
  183.90 +        jpeg.rst:   The :mod:`jpeg` module has been deprecated for removal in Python 3.0.
  183.91 +        statvfs.rst:   The :mod:`statvfs` module has been deprecated for removal in Python 3.0.
  183.92 +        sunaudio.rst:   The :mod:`sunaudiodev` module has been deprecated for removal in Python 3.0.
  183.93 +        sunaudio.rst:   The :mod:`SUNAUDIODEV` module has been deprecated for removal in Python 3.0.
  183.94 +        tarfile.rst:      The :class:`TarFileCompat` class has been deprecated for removal in Python 3.0.
  183.95 +         */
  183.96 +
  183.97 +        DEPRECATED.put("posixfile",
  183.98 +                "Locking is better done by fcntl.lockf().");
  183.99 +
 183.100 +        DEPRECATED.put("gopherlib",
 183.101 +                "The gopher protocol is not in active use anymore.");
 183.102 +
 183.103 +        DEPRECATED.put("rgbimgmodule",
 183.104 +                "");
 183.105 +
 183.106 +        DEPRECATED.put("pre",
 183.107 +                "The underlying PCRE engine doesn't support Unicode, and has been unmaintained since Python 1.5.2.");
 183.108 +
 183.109 +        DEPRECATED.put("whrandom",
 183.110 +                "The module's default seed computation was inherently insecure; the random module should be used instead.");
 183.111 +
 183.112 +        DEPRECATED.put("rfc822",
 183.113 +                "Supplanted by Python 2.2's email package.");
 183.114 +
 183.115 +        DEPRECATED.put("mimetools",
 183.116 +                "Supplanted by Python 2.2's email package.");
 183.117 +
 183.118 +        DEPRECATED.put("MimeWriter",
 183.119 +                "Supplanted by Python 2.2's email package.");
 183.120 +
 183.121 +        DEPRECATED.put("mimify",
 183.122 +                "Supplanted by Python 2.2's email package.");
 183.123 +
 183.124 +        DEPRECATED.put("rotor",
 183.125 +                "Uses insecure algorithm.");
 183.126 +
 183.127 +        DEPRECATED.put("TERMIOS.py",
 183.128 +                "The constants in this file are now in the 'termios' module.");
 183.129 +
 183.130 +        DEPRECATED.put("statcache",
 183.131 +                "Using the cache can be fragile and error-prone; applications should just use os.stat() directly.");
 183.132 +
 183.133 +        DEPRECATED.put("mpz",
 183.134 +                "Third-party packages provide similiar features and wrap more of GMP's API.");
 183.135 +
 183.136 +
 183.137 +        DEPRECATED.put("xreadlines",
 183.138 +                "Using 'for line in file', introduced in 2.3, is preferable.");
 183.139 +
 183.140 +        DEPRECATED.put("multifile",
 183.141 +                "Supplanted by the email package.");
 183.142 +
 183.143 +        DEPRECATED.put("sets",
 183.144 +                "The built-in set/frozenset types, introduced in Python 2.4, supplant the module.");
 183.145 +
 183.146 +        DEPRECATED.put("buildtools",
 183.147 +                "");
 183.148 +
 183.149 +        DEPRECATED.put("cfmfile",
 183.150 +                "");
 183.151 +
 183.152 +        DEPRECATED.put("macfs",
 183.153 +                "");
 183.154 +
 183.155 +        DEPRECATED.put("md5",
 183.156 +                "Replaced by the 'hashlib' module.");
 183.157 +
 183.158 +        DEPRECATED.put("sha",
 183.159 +                "Replaced by the 'hashlib' module.");
 183.160 +    }
 183.161 +
 183.162 +    public static boolean isDeprecatedModule(String module) {
 183.163 +        return DEPRECATED.containsKey(module);
 183.164 +    }
 183.165 +    
 183.166 +    public static String getDeprecatedModuleDescription(String module) {
 183.167 +        return DEPRECATED.get(module);
 183.168 +    }
 183.169 +
 183.170 +    private DeprecationQuery() {
 183.171 +    }
 183.172 +}
   184.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   184.2 +++ b/python.source/src/org/netbeans/modules/python/source/scopes/ArgListCompiler.java	Mon Sep 21 13:01:16 2015 +0200
   184.3 @@ -0,0 +1,121 @@
   184.4 +// Copyright (c) Corporation for National Research Initiatives
   184.5 +package org.netbeans.modules.python.source.scopes;
   184.6 +
   184.7 +import java.util.ArrayList;
   184.8 +
   184.9 +import java.util.List;
  184.10 +import org.python.antlr.PythonTree;
  184.11 +import org.python.antlr.Visitor;
  184.12 +import org.python.antlr.ast.Assign;
  184.13 +import org.python.antlr.ast.Name;
  184.14 +import org.python.antlr.ast.Suite;
  184.15 +import org.python.antlr.ast.Tuple;
  184.16 +import org.python.antlr.ast.arguments;
  184.17 +import org.python.antlr.ast.expr_contextType;
  184.18 +import org.python.antlr.base.expr;
  184.19 +import org.python.antlr.base.stmt;
  184.20 +
  184.21 +/** Based on org.python.compiler.ArgListCompiler */
  184.22 +public class ArgListCompiler extends Visitor {
  184.23 +    public boolean arglist, keywordlist;
  184.24 +    public List<expr> defaults;
  184.25 +    public List<String> names;
  184.26 +    public ArrayList<PythonTree> nodes;
  184.27 +    public List<String> fpnames;
  184.28 +    public List<stmt> init_code;
  184.29 +    private SymbolTable symbolTable;
  184.30 +
  184.31 +    public ArgListCompiler(SymbolTable symbolTable) {
  184.32 +        this.symbolTable = symbolTable;
  184.33 +        arglist = keywordlist = false;
  184.34 +        defaults = null;
  184.35 +        names = new ArrayList<>();
  184.36 +        nodes = new ArrayList<>();
  184.37 +        fpnames = new ArrayList<>();
  184.38 +        init_code = new ArrayList<>();
  184.39 +    }
  184.40 +
  184.41 +    public void reset() {
  184.42 +        arglist = keywordlist = false;
  184.43 +        defaults = null;
  184.44 +        names.clear();
  184.45 +        nodes.clear();
  184.46 +        init_code.clear();
  184.47 +    }
  184.48 +
  184.49 +    public void appendInitCode(Suite node) {
  184.50 +        node.getInternalBody().addAll(0, init_code);
  184.51 +    }
  184.52 +
  184.53 +    public List<expr> getDefaults() {
  184.54 +        return defaults;
  184.55 +    }
  184.56 +
  184.57 +    public void visitArgs(arguments args) throws Exception {
  184.58 +        for (int i = 0; i < args.getInternalArgs().size(); i++) {
  184.59 +            expr node = args.getInternalArgs().get(i);
  184.60 +            String name = (String)visit(node);
  184.61 +            names.add(name);
  184.62 +            nodes.add(node);
  184.63 +            if (node instanceof Tuple) {
  184.64 +                List<expr> targets = new ArrayList<>();
  184.65 +                targets.add(node);
  184.66 +                Assign ass = new Assign(node,
  184.67 +                        targets,
  184.68 +                        new Name(node, name, expr_contextType.Load));
  184.69 +                init_code.add(ass);
  184.70 +            }
  184.71 +        }
  184.72 +        if (args.getInternalVararg() != null) {
  184.73 +            arglist = true;
  184.74 +            names.add(args.getInternalVararg());
  184.75 +            //nodes.add(null); // no corresponding node?
  184.76 +            nodes.add(args); // just use the corresponding args node instead
  184.77 +        }
  184.78 +        if (args.getInternalKwarg() != null) {
  184.79 +            keywordlist = true;
  184.80 +            names.add(args.getInternalKwarg());
  184.81 +            //nodes.add(null); // no corresponding node?
  184.82 +            nodes.add(args); // just use the corresponding args node instead
  184.83 +        }
  184.84 +
  184.85 +        defaults = args.getInternalDefaults();
  184.86 +        for (int i = 0; i < defaults.size(); i++) {
  184.87 +            if (defaults.get(i) == null) {
  184.88 +                symbolTable.error("non-default argument follows default argument", true,
  184.89 +                        args.getInternalArgs().get(args.getInternalArgs().size() - defaults.size() + i));
  184.90 +            }
  184.91 +        }
  184.92 +    }
  184.93 +
  184.94 +    @Override
  184.95 +    public Object visitName(Name node) throws Exception {
  184.96 +        //FIXME: do we need Store and Param, or just Param?
  184.97 +        if (node.getInternalCtx() != expr_contextType.Store && node.getInternalCtx() != expr_contextType.Param) {
  184.98 +            return null;
  184.99 +        }
 184.100 +
 184.101 +        if (fpnames.contains(node.getInternalId())) {
 184.102 +            symbolTable.error("duplicate argument name found: " +
 184.103 +                    node.getInternalId(), true, node);
 184.104 +        }
 184.105 +        fpnames.add(node.getInternalId());
 184.106 +        return node.getInternalId();
 184.107 +    }
 184.108 +
 184.109 +    @Override
 184.110 +    public Object visitTuple(Tuple node) throws Exception {
 184.111 +        StringBuffer name = new StringBuffer("(");
 184.112 +        List<expr> elts = node.getInternalElts();
 184.113 +        if (elts != null) {
 184.114 +            int n = elts.size();
 184.115 +            for (int i = 0; i < n - 1; i++) {
 184.116 +                name.append(visit(elts.get(i)));
 184.117 +                name.append(", ");
 184.118 +            }
 184.119 +            name.append(visit(elts.get(n - 1)));
 184.120 +        }
 184.121 +        name.append(")");
 184.122 +        return name.toString();
 184.123 +    }
 184.124 +}
   185.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   185.2 +++ b/python.source/src/org/netbeans/modules/python/source/scopes/ScopeConstants.java	Mon Sep 21 13:01:16 2015 +0200
   185.3 @@ -0,0 +1,28 @@
   185.4 +package org.netbeans.modules.python.source.scopes;
   185.5 +
   185.6 +/** Based on org.python.compiler.ScopeConstants in Jython */
   185.7 +public interface ScopeConstants {
   185.8 +    public final static int BOUND = 1 << 0;
   185.9 +    public final static int NGLOBAL = 1 << 1; // func scope expl global
  185.10 +    public final static int PARAM = 1 << 2;
  185.11 +    public final static int FROM_PARAM = 1 << 3;
  185.12 +    public final static int CELL = 1 << 4;
  185.13 +    public final static int FREE = 1 << 5;
  185.14 +    public final static int CLASS_GLOBAL = 1 << 6; // class scope expl global
  185.15 +    public final static int READ = 1 << 7;
  185.16 +    public final static int CALLED = 1 << 8;
  185.17 +    public final static int DEF = 1 << 9;
  185.18 +    public final static int IMPORTED = 1 << 10;
  185.19 +    public final static int CLASS = 1 << 11;
  185.20 +    public final static int FUNCTION = 1 << 12;
  185.21 +    public final static int MEMBER = 1 << 13;
  185.22 +    public final static int GENERATOR = 1 << 13; // it's a generator expression
  185.23 +    public final static int PRIVATE = 1 << 14;
  185.24 +    public final static int ALIAS = 1 << 15;
  185.25 +    public final static int PROTECTED = 1 << 16;
  185.26 +    public final static int BOUND_IN_CONSTRUCTOR = 1 << 17;
  185.27 +    public final static int GLOBAL = NGLOBAL | CLASS_GLOBAL; // all global
  185.28 +    public final static int TOPSCOPE = 0;
  185.29 +    public final static int FUNCSCOPE = 1;
  185.30 +    public final static int CLASSSCOPE = 2;
  185.31 +}
   186.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   186.2 +++ b/python.source/src/org/netbeans/modules/python/source/scopes/ScopeInfo.java	Mon Sep 21 13:01:16 2015 +0200
   186.3 @@ -0,0 +1,576 @@
   186.4 +// (C) Copyright 2001 Samuele Pedroni
   186.5 +package org.netbeans.modules.python.source.scopes;
   186.6 +
   186.7 +import java.util.ArrayList;
   186.8 +import java.util.Collections;
   186.9 +import java.util.HashMap;
  186.10 +import java.util.LinkedHashMap;
  186.11 +import java.util.Map;
  186.12 +import java.util.List;
  186.13 +
  186.14 +import org.netbeans.modules.python.source.AstPath;
  186.15 +import org.netbeans.modules.python.source.PythonAstUtils;
  186.16 +import org.python.antlr.ParseException;
  186.17 +import org.python.antlr.PythonTree;
  186.18 +import org.python.antlr.ast.Assign;
  186.19 +import org.python.antlr.ast.Attribute;
  186.20 +import org.python.antlr.ast.ClassDef;
  186.21 +import org.python.antlr.ast.Name;
  186.22 +import org.python.antlr.ast.Return;
  186.23 +import org.python.antlr.ast.Tuple;
  186.24 +import org.python.antlr.base.expr;
  186.25 +import static org.netbeans.modules.python.source.scopes.ScopeConstants.*;
  186.26 +import org.netbeans.modules.python.source.NameStyle;
  186.27 +
  186.28 +/** 
  186.29 + * Based on org.python.compiler.ScopeInfo in Jython
  186.30 + *
  186.31 + * See {@link ScopesCompiler} for details on my modifications
  186.32 + */
  186.33 +@SuppressWarnings("unchecked")
  186.34 +public class ScopeInfo extends Object {
  186.35 +    public PythonTree scope_node;
  186.36 +    public String scope_name;
  186.37 +    public int level;
  186.38 +    public int func_level;
  186.39 +    public boolean hidden;
  186.40 +
  186.41 +    public String dump() {
  186.42 +        StringBuilder sb = new StringBuilder();
  186.43 +
  186.44 +        for (int i = 0; i < level; i++) {
  186.45 +            sb.append("    ");
  186.46 +        }
  186.47 +        sb.append("=============================================\n");
  186.48 +        for (int i = 0; i < level; i++) {
  186.49 +            sb.append("    ");
  186.50 +        }
  186.51 +        sb.append(((kind != CLASSSCOPE) ? scope_name : "class " +
  186.52 +                scope_name) + ": " + scope_node + " : " + PythonAstUtils.getRange(scope_node) + "\n");
  186.53 +        //for(int i=0; i<level; i++) sb.append("    ");
  186.54 +        //sb.append("UP=" + up);
  186.55 +        //sb.append("   NESTED=" + nested);
  186.56 +        //sb.append("\n");
  186.57 +
  186.58 +
  186.59 +        // Sort to make test output stable
  186.60 +        List<String> keys = new ArrayList<>(tbl.keySet());
  186.61 +        Collections.sort(keys);
  186.62 +        for (String name : keys) {
  186.63 +            SymInfo info = tbl.get(name);
  186.64 +            for (int i = 0; i < level; i++) {
  186.65 +                sb.append("    ");
  186.66 +            }
  186.67 +            sb.append(name);
  186.68 +            sb.append(" ");
  186.69 +            sb.append(info.dumpFlags(this));
  186.70 +            sb.append("\n");
  186.71 +        }
  186.72 +
  186.73 +        if (inner_free.size() > 0 || cellvars.size() > 0 || jy_paramcells.size() > 0 ||
  186.74 +                jy_npurecell != 0 /*|| cell != 0 || distance != 0 || up != null*/) {
  186.75 +            for (int i = 0; i < level; i++) {
  186.76 +                sb.append("    ");
  186.77 +            }
  186.78 +            sb.append("---------------------------------------------\n");
  186.79 +        }
  186.80 +
  186.81 +        if (inner_free.size() > 0) {
  186.82 +            List<String> sorted = new ArrayList<>();
  186.83 +            for (String s : inner_free.keySet()) {
  186.84 +                sorted.add(s + "=" + inner_free.get(s));
  186.85 +            }
  186.86 +            Collections.sort(sorted);
  186.87 +
  186.88 +            for (int i = 0; i < level; i++) {
  186.89 +                sb.append("    ");
  186.90 +            }
  186.91 +            sb.append("inner_free: {"); // NOI18N
  186.92 +            boolean first = true;
  186.93 +            for (String s : sorted) {
  186.94 +                if (first) {
  186.95 +                    first = false;
  186.96 +                } else {
  186.97 +                    sb.append(", "); // NOI18N
  186.98 +                }
  186.99 +                sb.append(s);
 186.100 +            }
 186.101 +            sb.append("}\n"); // NOI18N
 186.102 +        }
 186.103 +        if (cellvars.size() > 0) {
 186.104 +            Collections.sort(cellvars);
 186.105 +            for (int i = 0; i < level; i++) {
 186.106 +                sb.append("    ");
 186.107 +            }
 186.108 +            sb.append("cellvars: " + cellvars.toString() + "\n"); // TODO - sort
 186.109 +        }
 186.110 +        if (jy_paramcells.size() > 0) {
 186.111 +            Collections.sort(jy_paramcells);
 186.112 +            for (int i = 0; i < level; i++) {
 186.113 +                sb.append("    ");
 186.114 +            }
 186.115 +            sb.append("jy_paramcells: " + jy_paramcells.toString() + "\n"); // TODO - sort
 186.116 +        }
 186.117 +        if (jy_npurecell != 0) {
 186.118 +            for (int i = 0; i < level; i++) {
 186.119 +                sb.append("    ");
 186.120 +            }
 186.121 +            sb.append("jy_npurecell: " + jy_npurecell + "\n"); // TODO - sort
 186.122 +        }
 186.123 +        //if (cell != 0) {
 186.124 +        //    for(int i=0; i<level; i++) sb.append("    ");
 186.125 +        //    sb.append("cell: " + cell + "\n"); // TODO - sort
 186.126 +        //}
 186.127 +        //if (distance != 0) {
 186.128 +        //    for(int i=0; i<level; i++) sb.append("    ");
 186.129 +        //    sb.append("distance: " + distance + "\n"); // TODO - sort
 186.130 +        //}
 186.131 +        //if (up != null) {
 186.132 +        //    for(int i=0; i<level; i++) sb.append("    ");
 186.133 +        //    sb.append("up: " + up.scope_node);
 186.134 +        //}
 186.135 +
 186.136 +        if (attributes.size() > 0) {
 186.137 +            for (int i = 0; i < level; i++) {
 186.138 +                sb.append("    ");
 186.139 +            }
 186.140 +            sb.append("------ Attributes ---------------------------------------\n"); // NOI18N
 186.141 +            // Sort
 186.142 +            List<String> attributeNames = new ArrayList<>(attributes.keySet());
 186.143 +            Collections.sort(attributeNames);
 186.144 +            for (String attributeName : attributeNames) {
 186.145 +                for (int i = 0; i < level; i++) {
 186.146 +                    sb.append("    ");
 186.147 +                }
 186.148 +                sb.append(attributeName);
 186.149 +                sb.append(" : "); // NOI18N
 186.150 +                sb.append(attributes.get(attributeName));
 186.151 +                sb.append("\n"); // NOI18N
 186.152 +            }
 186.153 +        }
 186.154 +
 186.155 +        return sb.toString();
 186.156 +    }
 186.157 +
 186.158 +    public ScopeInfo(String name, PythonTree node, int level, int kind,
 186.159 +            int func_level, ArgListCompiler ac) {
 186.160 +        scope_name = name;
 186.161 +        scope_node = node;
 186.162 +        this.level = level;
 186.163 +        this.kind = kind;
 186.164 +        this.func_level = func_level;
 186.165 +        this.ac = ac;
 186.166 +    }
 186.167 +    public int kind;
 186.168 +    public boolean unqual_exec;
 186.169 +    public boolean exec;
 186.170 +    public boolean from_import_star;
 186.171 +    public boolean contains_ns_free_vars;
 186.172 +    public boolean generator;
 186.173 +    private boolean hasReturnWithValue;
 186.174 +    public int yield_count;
 186.175 +    public int max_with_count;
 186.176 +    public ArgListCompiler ac;
 186.177 +    public Map<String, SymInfo> tbl = new LinkedHashMap<>();
 186.178 +
 186.179 +    // define a separate dictionary for dynamic bounded variables
 186.180 +    public Map<String, SymInfo> attributes = new HashMap<>();
 186.181 +    public List<String> names = new ArrayList<>();
 186.182 +
 186.183 +    private void addAttributeEntry(String name, PythonTree node, int flags) {
 186.184 +        SymInfo info = attributes.get(name);
 186.185 +        if (info == null) {
 186.186 +            SymInfo entry = new SymInfo(flags);
 186.187 +            if (NameStyle.isPrivateName(name)) {
 186.188 +                entry.flags |= PRIVATE;
 186.189 +            } else if (NameStyle.isProtectedName(name)) {
 186.190 +                entry.flags |= PROTECTED;
 186.191 +            }
 186.192 +            entry.node = node;
 186.193 +            attributes.put(name, entry);
 186.194 +        }
 186.195 +    }
 186.196 +
 186.197 +    private void addToClassScope(String name, PythonTree node, boolean inConstructor) {
 186.198 +        int flags = CLASSSCOPE | BOUND | MEMBER;
 186.199 +        if (inConstructor) {
 186.200 +            flags |= BOUND_IN_CONSTRUCTOR;
 186.201 +        }
 186.202 +        addAttributeEntry(name, node, flags);
 186.203 +    }
 186.204 +
 186.205 +    public ScopeInfo getClassScope() {
 186.206 +        ScopeInfo cur = this;
 186.207 +        while ((cur != null) &&
 186.208 +                (!(cur.scope_node instanceof ClassDef))) {
 186.209 +            cur = cur.nested;
 186.210 +        }
 186.211 +        return cur;
 186.212 +    }
 186.213 +
 186.214 +    private boolean belongsToExprList(List<expr> types, expr cur) {
 186.215 +        return types != null && types.contains(cur);
 186.216 +    }
 186.217 +
 186.218 +    boolean isAttributeAssigment(AstPath path, Attribute attr) {
 186.219 +        PythonTree leaf = path.leaf();
 186.220 +        Assign assign = null;
 186.221 +        expr target = attr; // default to single
 186.222 +        if (leaf instanceof Assign) {
 186.223 +            assign = (Assign)leaf;
 186.224 +        } else if (leaf instanceof Tuple) {
 186.225 +            // check for tuple assignment
 186.226 +            Tuple tuple = (Tuple)leaf;
 186.227 +            PythonTree tupleParent = path.leafParent();
 186.228 +            if (belongsToExprList(tuple.getInternalElts(), attr)) {
 186.229 +                if (tupleParent instanceof Assign) {
 186.230 +                    assign = (Assign)tupleParent;
 186.231 +                    target = tuple; // tuple assignment target
 186.232 +                }
 186.233 +            }
 186.234 +        }
 186.235 +        // check if we got assignment
 186.236 +        if (assign == null) {
 186.237 +            return false;
 186.238 +        }
 186.239 +        if (belongsToExprList(assign.getInternalTargets(), target)) {
 186.240 +            return true;
 186.241 +        }
 186.242 +        return false;
 186.243 +    }
 186.244 +
 186.245 +    public void addAttribute(AstPath path, String name, PythonTree node) {
 186.246 +        // deeply check assignment context for attribute.
 186.247 +        Attribute curAttr = (Attribute)node;
 186.248 +
 186.249 +        if (curAttr.getInternalValue() instanceof Attribute) {
 186.250 +            // recursice attributes( x.y.z.w ) to be handled later
 186.251 +        } else if (curAttr.getInternalValue() instanceof Name) {
 186.252 +
 186.253 +            Name parentName = (Name)curAttr.getInternalValue();
 186.254 +
 186.255 +            ScopeInfo classScope = getClassScope();
 186.256 +            boolean inConstructor = false;
 186.257 +            String parName = parentName.getInternalId();
 186.258 +
 186.259 +            // for simplicity handle only at classScope in current source
 186.260 +            if (classScope != null) {
 186.261 +                // check for self or inherited parent name prefix
 186.262 +                if ((parName.equals("self")) ||
 186.263 +                        (PythonAstUtils.getParentClassFromNode(path, classScope.scope_node, parName) != null)) {
 186.264 +                    if (!(parName.equals("self"))) {
 186.265 +                        // check classname not overridden by local scope variable
 186.266 +                        if (tbl.get(parName) != null) {
 186.267 +                            return;
 186.268 +                        }
 186.269 +                    }
 186.270 +                    if (scope_name.equals("__init__") || scope_name.equals("__new__")) {
 186.271 +                        inConstructor = true; // set in constructor
 186.272 +                    }
 186.273 +                    //
 186.274 +                    // put in class scope
 186.275 +                    if (isAttributeAssigment(path, curAttr)) {
 186.276 +                        classScope.addToClassScope(name, node, inConstructor);
 186.277 +                    } else {
 186.278 +                        // store at current scope if parName is not overriding
 186.279 +                        // classname at current scope
 186.280 +                        int flags = CLASSSCOPE | READ;
 186.281 +                        addAttributeEntry(name, node, flags);
 186.282 +                    }
 186.283 +                }
 186.284 +            }
 186.285 +        }
 186.286 +    }
 186.287 +
 186.288 +    public int addGlobal(String name, PythonTree node) {
 186.289 +        // global kind = func vs. class
 186.290 +        int global = kind == CLASSSCOPE ? CLASS_GLOBAL : NGLOBAL;
 186.291 +        SymInfo info = tbl.get(name);
 186.292 +        if (info == null) {
 186.293 +            SymInfo entry = new SymInfo(global | BOUND);
 186.294 +            if (NameStyle.isPrivateName(name)) {
 186.295 +                entry.flags |= PRIVATE;
 186.296 +            } else if (NameStyle.isProtectedName(name)) {
 186.297 +                entry.flags |= PROTECTED;
 186.298 +            }
 186.299 +            entry.node = node;
 186.300 +            tbl.put(name, entry);
 186.301 +            return -1;
 186.302 +        }
 186.303 +        int prev = info.flags;
 186.304 +        info.flags |= global | BOUND;
 186.305 +        return prev;
 186.306 +    }
 186.307 +    public int local = 0;
 186.308 +
 186.309 +    public void addParam(String name, PythonTree node) {
 186.310 +        SymInfo entry = new SymInfo(PARAM | BOUND, local++);
 186.311 +        entry.node = node;
 186.312 +        tbl.put(name, entry);
 186.313 +        names.add(name);
 186.314 +    }
 186.315 +
 186.316 +    // <netbeans>
 186.317 +    public boolean isUnused(String name) {
 186.318 +        SymInfo info = tbl.get(name);
 186.319 +        if (info != null) {
 186.320 +            return info.isUnused(this);
 186.321 +        }
 186.322 +        return false;
 186.323 +    }
 186.324 +
 186.325 +    public boolean isParameter(String name) {
 186.326 +        SymInfo info = tbl.get(name);
 186.327 +        if (info != null) {
 186.328 +            return info.isParameter();
 186.329 +        }
 186.330 +        return false;
 186.331 +    }
 186.332 +    // </netbeans>
 186.333 +
 186.334 +    public void markFromParam() {
 186.335 +        for (SymInfo info : tbl.values()) {
 186.336 +            info.flags |= FROM_PARAM;
 186.337 +        }
 186.338 +    }
 186.339 +
 186.340 +    public SymInfo addBound(String name, PythonTree node) {
 186.341 +        SymInfo info = tbl.get(name);
 186.342 +        if (info == null) {
 186.343 +            info = new SymInfo(BOUND);
 186.344 +            if (NameStyle.isPrivateName(name)) {
 186.345 +                info.flags |= PRIVATE;
 186.346 +            } else if (NameStyle.isProtectedName(name)) {
 186.347 +                info.flags |= PROTECTED;
 186.348 +            }
 186.349 +            tbl.put(name, info);
 186.350 +            info.node = node;
 186.351 +            return info;
 186.352 +        }
 186.353 +        info.flags |= BOUND;
 186.354 +
 186.355 +        return info;
 186.356 +    }
 186.357 +
 186.358 +    public SymInfo addUsed(String name, PythonTree node) {
 186.359 +        SymInfo info = tbl.get(name);
 186.360 +        if (info == null) {
 186.361 +            // <netbeans>
 186.362 +            info = new SymInfo(0);
 186.363 +            tbl.put(name, info);
 186.364 +            info.node = node;
 186.365 +        }
 186.366 +        info.flags |= READ;
 186.367 +
 186.368 +        return info;
 186.369 +        // </netbeans>
 186.370 +    }
 186.371 +
 186.372 +
 186.373 +    // <netbeans>
 186.374 +    void markCall(String name) {
 186.375 +        SymInfo entry = tbl.get(name);
 186.376 +        if (entry != null) {
 186.377 +            entry.flags |= CALLED;
 186.378 +        }
 186.379 +    }
 186.380 +    // </netbeans>
 186.381 +    private final static String PRESENT = new String("PRESENT");
 186.382 +    public HashMap<String, String> inner_free = new HashMap<>();
 186.383 +    public List<String> cellvars = new ArrayList<>();
 186.384 +    public List<String> jy_paramcells = new ArrayList<>();
 186.385 +    public int jy_npurecell;
 186.386 +    public int cell, distance;
 186.387 +    public ScopeInfo up;
 186.388 +    public ScopeInfo nested;
 186.389 +
 186.390 +    //Resolve the names used in the given scope, and mark any freevars used in the up scope
 186.391 +    public void cook(ScopeInfo up, int distance, SymbolTable ctxt) throws Exception {
 186.392 +        if (up == null) {
 186.393 +            return; // top level => nop
 186.394 +        }
 186.395 +        this.up = up;
 186.396 +        this.distance = distance;
 186.397 +        boolean func = kind == FUNCSCOPE;
 186.398 +        List<String> purecells = new ArrayList<>();
 186.399 +        cell = 0;
 186.400 +        boolean some_inner_free = inner_free.size() > 0;
 186.401 +
 186.402 +        for (String name : inner_free.keySet()) {
 186.403 +
 186.404 +            SymInfo info = tbl.get(name);
 186.405 +            if (info == null) {
 186.406 +                tbl.put(name, new SymInfo(FREE));
 186.407 +                continue;
 186.408 +            }
 186.409 +            int flags = info.flags;
 186.410 +            if (func) {
 186.411 +                // not func global and bound ?
 186.412 +                if ((flags & NGLOBAL) == 0 && (flags & BOUND) != 0) {
 186.413 +                    info.flags |= CELL;
 186.414 +                    if ((info.flags & PARAM) != 0) {
 186.415 +                        jy_paramcells.add(name);
 186.416 +                    }
 186.417 +                    cellvars.add(name);
 186.418 +                    info.env_index = cell++;
 186.419 +                    if ((flags & PARAM) == 0) {
 186.420 +                        purecells.add(name);
 186.421 +                    }
 186.422 +                    continue;
 186.423 +                }
 186.424 +            } else {
 186.425 +                info.flags |= FREE;
 186.426 +            }
 186.427 +        }
 186.428 +        boolean some_free = false;
 186.429 +
 186.430 +        boolean nested = up.kind != TOPSCOPE;
 186.431 +        for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
 186.432 +            String name = entry.getKey();
 186.433 +            SymInfo info = entry.getValue();
 186.434 +            int flags = info.flags;
 186.435 +            if (nested && (flags & FREE) != 0) {
 186.436 +                up.inner_free.put(name, PRESENT);
 186.437 +            }
 186.438 +            if ((flags & (GLOBAL | PARAM | CELL)) == 0) {
 186.439 +                if ((flags & BOUND) != 0) { // ?? only func
 186.440 +                    // System.err.println("local: "+name);
 186.441 +                    names.add(name);
 186.442 +                    info.locals_index = local++;
 186.443 +                    continue;
 186.444 +                }
 186.445 +                info.flags |= FREE;
 186.446 +                some_free = true;
 186.447 +                if (nested) {
 186.448 +                    up.inner_free.put(name, PRESENT);
 186.449 +                }
 186.450 +            }
 186.451 +
 186.452 +            // <netbeans>
 186.453 +            if ((info.flags & FREE) != 0) {
 186.454 +                // Mark definition symbol as read as well
 186.455 +                ScopeInfo curr = up;
 186.456 +                while (curr != null) {
 186.457 +                    SymInfo s = curr.tbl.get(name);
 186.458 +                    if (s != null && ((s.flags & BOUND) != 0)) {
 186.459 +                        s.flags |= READ;
 186.460 +                        s.flags |= (info.flags & (CALLED));
 186.461 +                        break;
 186.462 +                    }
 186.463 +                    curr = curr.up;
 186.464 +                    while (curr != null && curr.kind == CLASSSCOPE) {
 186.465 +                        curr = curr.up;
 186.466 +                    }
 186.467 +                }
 186.468 +            }
 186.469 +
 186.470 +            // </netbeans>
 186.471 +        }
 186.472 +        if ((jy_npurecell = purecells.size()) > 0) {
 186.473 +            int sz = purecells.size();
 186.474 +            for (int i = 0; i < sz; i++) {
 186.475 +                names.add(purecells.get(i));
 186.476 +            }
 186.477 +        }
 186.478 +
 186.479 +        if (some_free && nested) {
 186.480 +            up.contains_ns_free_vars = true;
 186.481 +        }
 186.482 +        // XXX - this doesn't catch all cases - may depend subtly
 186.483 +        // on how visiting NOW works with antlr compared to javacc
 186.484 +        if ((unqual_exec || from_import_star)) {
 186.485 +            if (some_inner_free) {
 186.486 +                dynastuff_trouble(true, ctxt);
 186.487 +            } else if (func_level > 1 && some_free) {
 186.488 +                dynastuff_trouble(false, ctxt);
 186.489 +            }
 186.490 +        }
 186.491 +
 186.492 +    }
 186.493 +
 186.494 +    private void dynastuff_trouble(boolean inner_free,
 186.495 +            SymbolTable ctxt) throws Exception {
 186.496 +        String illegal;
 186.497 +        if (unqual_exec && from_import_star) {
 186.498 +            illegal = "function '" + scope_name +
 186.499 +                    "' uses import * and bare exec, which are illegal";
 186.500 +        } else if (unqual_exec) {
 186.501 +            illegal = "unqualified exec is not allowed in function '" +
 186.502 +                    scope_name + "'";
 186.503 +        } else {
 186.504 +            illegal = "import * is not allowed in function '" + scope_name + "'";
 186.505 +        }
 186.506 +        String why;
 186.507 +        if (inner_free) {
 186.508 +            why = " because it contains a function with free variables";
 186.509 +        } else {
 186.510 +            why = " because it contains free variables";
 186.511 +        }
 186.512 +        ctxt.error(illegal + why, true, scope_node);
 186.513 +    }
 186.514 +    public List<String> freevars = new ArrayList<>();
 186.515 +
 186.516 +    /**
 186.517 +     * setup the closure on this scope using the scope passed into cook as up as
 186.518 +     * the containing scope
 186.519 +     */
 186.520 +    public void setup_closure() {
 186.521 +        setup_closure(up);
 186.522 +    }
 186.523 +
 186.524 +    /**
 186.525 +     * setup the closure on this scope using the passed in scope. This is used
 186.526 +     * by jythonc to setup its closures.
 186.527 +     */
 186.528 +    public void setup_closure(ScopeInfo up) {
 186.529 +        int free = cell; // env = cell...,free...
 186.530 +        Map<String, SymInfo> up_tbl = up.tbl;
 186.531 +        boolean nested = up.kind != TOPSCOPE;
 186.532 +        for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
 186.533 +            String name = entry.getKey();
 186.534 +            SymInfo info = entry.getValue();
 186.535 +            int flags = info.flags;
 186.536 +            if ((flags & FREE) != 0) {
 186.537 +                SymInfo up_info = up_tbl.get(name);
 186.538 +                // ?? differs from CPython -- what is the intended behaviour?
 186.539 +                if (up_info != null) {
 186.540 +                    int up_flags = up_info.flags;
 186.541 +                    if ((up_flags & (CELL | FREE)) != 0) {
 186.542 +                        info.env_index = free++;
 186.543 +                        freevars.add(name);
 186.544 +                        continue;
 186.545 +                    }
 186.546 +                    // ! func global affect nested scopes
 186.547 +                    if (nested && (up_flags & NGLOBAL) != 0) {
 186.548 +                        info.flags = NGLOBAL | BOUND;
 186.549 +                        continue;
 186.550 +                    }
 186.551 +                }
 186.552 +                info.flags &= ~FREE;
 186.553 +            }
 186.554 +        }
 186.555 +
 186.556 +    }
 186.557 +
 186.558 +    @Override
 186.559 +    public String toString() {
 186.560 +        return "ScopeInfo[" + scope_name + " " + kind + "]@" +
 186.561 +                System.identityHashCode(this);
 186.562 +    }
 186.563 +
 186.564 +    public void defineAsGenerator(expr node) {
 186.565 +        generator = true;
 186.566 +        if (hasReturnWithValue) {
 186.567 +            throw new ParseException("'return' with argument " +
 186.568 +                    "inside generator", node);
 186.569 +        }
 186.570 +    }
 186.571 +
 186.572 +    public void noteReturnValue(Return node) {
 186.573 +        if (generator) {
 186.574 +            throw new ParseException("'return' with argument " +
 186.575 +                    "inside generator", node);
 186.576 +        }
 186.577 +        hasReturnWithValue = true;
 186.578 +    }
 186.579 +}
   187.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   187.2 +++ b/python.source/src/org/netbeans/modules/python/source/scopes/ScopesCompiler.java	Mon Sep 21 13:01:16 2015 +0200
   187.3 @@ -0,0 +1,641 @@
   187.4 +// (C) Copyright 2001 Samuele Pedroni
   187.5 +package org.netbeans.modules.python.source.scopes;
   187.6 +
   187.7 +import java.util.ArrayList;
   187.8 +import java.util.List;
   187.9 +import java.util.Map;
  187.10 +import java.util.Set;
  187.11 +import java.util.Stack;
  187.12 +import org.netbeans.modules.python.source.AstPath;
  187.13 +import org.openide.util.Exceptions;
  187.14 +import org.python.antlr.PythonTree;
  187.15 +import org.python.antlr.Visitor;
  187.16 +import org.python.antlr.ast.Assign;
  187.17 +import org.python.antlr.ast.Attribute;
  187.18 +import org.python.antlr.ast.Call;
  187.19 +import org.python.antlr.ast.ClassDef;
  187.20 +import org.python.antlr.ast.Delete;
  187.21 +import org.python.antlr.ast.Exec;
  187.22 +import org.python.antlr.ast.Expression;
  187.23 +import org.python.antlr.ast.FunctionDef;
  187.24 +import org.python.antlr.ast.GeneratorExp;
  187.25 +import org.python.antlr.ast.Global;
  187.26 +import org.python.antlr.ast.Import;
  187.27 +import org.python.antlr.ast.ImportFrom;
  187.28 +import org.python.antlr.ast.Interactive;
  187.29 +import org.python.antlr.ast.Lambda;
  187.30 +import org.python.antlr.ast.ListComp;
  187.31 +import org.python.antlr.ast.Name;
  187.32 +import org.python.antlr.ast.Return;
  187.33 +import org.python.antlr.ast.Str;
  187.34 +import org.python.antlr.ast.With;
  187.35 +import org.python.antlr.ast.Yield;
  187.36 +import org.python.antlr.ast.alias;
  187.37 +import org.python.antlr.ast.arguments;
  187.38 +import org.python.antlr.base.expr;
  187.39 +import org.python.antlr.ast.expr_contextType;
  187.40 +import org.python.antlr.base.stmt;
  187.41 +
  187.42 +/** 
  187.43 + * Based on org.python.compiler.ScopesCompiler in Jython
  187.44 + *
  187.45 + * Modifications I've made:
  187.46 + * - Methods for finding all the free variables
  187.47 + * - Methods for identifying unused bound variables
  187.48 + * - Track whether symbols are referenced as calls or not
  187.49 + *   (so I can determine whether to look in the index for
  187.50 + *    functions or data etc. when trying to resolve imports)
  187.51 + * - Track variable reads/writes
  187.52 + * - Track imports etc.
  187.53 + * - Add nodes to each SymInfo
  187.54 + * - Replace old style Java (Hashtable, Vector, implements ScopeConstants) with
  187.55 + *   modern Java (HashMap, ArrayList, import static)
  187.56 + * 
  187.57 + */
  187.58 +@SuppressWarnings("unchecked")
  187.59 +public class ScopesCompiler extends Visitor implements ScopeConstants {
  187.60 +    private SymbolTable symbolTable;
  187.61 +    private Stack scopes;
  187.62 +    private ScopeInfo cur = null;
  187.63 +    private Map<PythonTree, ScopeInfo> nodeScopes;
  187.64 +    private int level = 0;
  187.65 +    private int func_level = 0;
  187.66 +    private List<Import> imports;
  187.67 +    private List<PythonTree> mainImports;
  187.68 +    private List<ImportFrom> importsFrom;
  187.69 +    private Set<PythonTree> topLevelImports;
  187.70 +    private PythonTree root;
  187.71 +    private PythonTree parent;
  187.72 +    private AstPath path = new AstPath();
  187.73 +    /** List of symbols registered via __all__ = [ "foo", "bar" ] or __all__.extend() or __all__.append() */
  187.74 +    private List<Str> publicSymbols;
  187.75 +    /** Set to true if we encountered manipulation on __all__ that I don't understand */
  187.76 +    private boolean invalidPublicSymbols;
  187.77 +
  187.78 +    public ScopesCompiler(SymbolTable symbolTable, Map<PythonTree, ScopeInfo> nodeScopes, PythonTree root,
  187.79 +            List<Import> imports, List<ImportFrom> importsFrom, List<PythonTree> mainImports, Set<PythonTree> topLevelImports) {
  187.80 +        this.symbolTable = symbolTable;
  187.81 +        this.nodeScopes = nodeScopes;
  187.82 +        scopes = new Stack();
  187.83 +        this.root = root;
  187.84 +
  187.85 +        this.imports = imports;
  187.86 +        this.importsFrom = importsFrom;
  187.87 +        this.mainImports = mainImports;
  187.88 +        this.topLevelImports = topLevelImports;
  187.89 +    }
  187.90 +
  187.91 +    @Override
  187.92 +    public void traverse(PythonTree node) throws Exception {
  187.93 +        // Jython's parser often doesn't set the parent references correctly
  187.94 +        // so try to fix that here
  187.95 +        node.setParent(parent);
  187.96 +
  187.97 +        PythonTree oldParent = parent;
  187.98 +        parent = node;
  187.99 +
 187.100 +        path.descend(node);
 187.101 +        super.traverse(node);
 187.102 +        parent = oldParent;
 187.103 +        path.ascend();
 187.104 +    }
 187.105 +
 187.106 +    public void beginScope(String name, int kind, PythonTree node,
 187.107 +            ArgListCompiler ac) {
 187.108 +        if (cur != null) {
 187.109 +            scopes.push(cur);
 187.110 +        }
 187.111 +        if (kind == FUNCSCOPE) {
 187.112 +            func_level++;
 187.113 +        }
 187.114 +        cur = new ScopeInfo(name, node, level++, kind, func_level, ac);
 187.115 +        nodeScopes.put(node, cur);
 187.116 +    }
 187.117 +
 187.118 +    public void endScope() throws Exception {
 187.119 +        if (cur.kind == FUNCSCOPE) {
 187.120 +            func_level--;
 187.121 +        }
 187.122 +        level--;
 187.123 +        ScopeInfo up = null;
 187.124 +        if (!scopes.empty()) {
 187.125 +            up = (ScopeInfo)scopes.pop();
 187.126 +        }
 187.127 +        //Go into the stack to find a non class containing scope to use making the closure
 187.128 +        //See PEP 227
 187.129 +        int dist = 1;
 187.130 +        ScopeInfo referenceable = up;
 187.131 +        for (int i = scopes.size() - 1; i >= 0 && referenceable.kind == CLASSSCOPE; i--, dist++) {
 187.132 +            referenceable = ((ScopeInfo)scopes.get(i));
 187.133 +        }
 187.134 +        cur.cook(referenceable, dist, symbolTable);
 187.135 +//        cur.dump(); // debug
 187.136 +        cur = up;
 187.137 +    }
 187.138 +
 187.139 +    public void parse() {
 187.140 +        try {
 187.141 +            visit(root);
 187.142 +        } catch (Throwable t) {
 187.143 +            Exceptions.printStackTrace(t);
 187.144 +            //throw org.python.core.ParserFacade.fixParseError(null, t,
 187.145 +            //        code_compiler.getFilename());
 187.146 +        }
 187.147 +    }
 187.148 +
 187.149 +    @Override
 187.150 +    public Object visitInteractive(Interactive node) throws Exception {
 187.151 +        beginScope("<single-top>", TOPSCOPE, node, null);
 187.152 +        PythonTree oldParent = parent;
 187.153 +        parent = node;
 187.154 +        suite(node.getInternalBody());
 187.155 +        parent = oldParent;
 187.156 +        endScope();
 187.157 +        return null;
 187.158 +    }
 187.159 +
 187.160 +    @Override
 187.161 +    public Object visitModule(org.python.antlr.ast.Module node)
 187.162 +            throws Exception {
 187.163 +        List<stmt> body = node.getInternalBody();
 187.164 +        if (body != null && body.size() > 0) {
 187.165 +            boolean foundFirst = false;
 187.166 +            for (stmt stmt : body) {
 187.167 +                if (stmt != null) {
 187.168 +                    if (stmt instanceof Import || stmt instanceof ImportFrom) {
 187.169 +                        if (!foundFirst) {
 187.170 +                            foundFirst = true;
 187.171 +                        }
 187.172 +                        mainImports.add(stmt);
 187.173 +                    } else if (foundFirst) {
 187.174 +                        break;
 187.175 +                    }
 187.176 +                }
 187.177 +            }
 187.178 +        }
 187.179 +
 187.180 +        beginScope("<file-top>", TOPSCOPE, node, null);
 187.181 +
 187.182 +        PythonTree oldParent = parent;
 187.183 +        parent = node;
 187.184 +        suite(node.getInternalBody());
 187.185 +        parent = oldParent;
 187.186 +
 187.187 +        endScope();
 187.188 +        return null;
 187.189 +    }
 187.190 +
 187.191 +    @Override
 187.192 +    public Object visitExpression(Expression node) throws Exception {
 187.193 +        beginScope("<eval-top>", TOPSCOPE, node, null);
 187.194 +        visit(new Return(node, node.getInternalBody()));
 187.195 +        endScope();
 187.196 +        return null;
 187.197 +    }
 187.198 +
 187.199 +    private void def(String name, int extraFlags, PythonTree node) {
 187.200 +        SymInfo info = cur.addBound(name, node);
 187.201 +        // <netbeans>
 187.202 +        info.flags |= (DEF | extraFlags);
 187.203 +        info.node = node;
 187.204 +        // </netbeans>
 187.205 +    }
 187.206 +
 187.207 +    @Override
 187.208 +    public Object visitAssign(Assign node) throws Exception {
 187.209 +        List<expr> targets = node.getInternalTargets();
 187.210 +        if (targets != null && targets.size() == 1 && targets.get(0) instanceof Name) {
 187.211 +            Name lhs = (Name)targets.get(0);
 187.212 +            if ("__all__".equals(lhs.getInternalId())) { // NOI18N
 187.213 +                expr nodeValue = node.getInternalValue();
 187.214 +                if (!invalidPublicSymbols && nodeValue instanceof org.python.antlr.ast.List) {
 187.215 +                    org.python.antlr.ast.List allList = (org.python.antlr.ast.List)nodeValue;
 187.216 +                    if (allList != null) {
 187.217 +                        for (expr expr : allList.getInternalElts()) {
 187.218 +                            if (expr instanceof Str) {
 187.219 +                                Str str = (Str)expr;
 187.220 +                                if (publicSymbols == null) {
 187.221 +                                    publicSymbols = new ArrayList<>();
 187.222 +                                }
 187.223 +                                publicSymbols.add(str);
 187.224 +                            } else {
 187.225 +                                invalidPublicSymbols = true;
 187.226 +                            }
 187.227 +                        }
 187.228 +                    }
 187.229 +                } else {
 187.230 +                    invalidPublicSymbols = true;
 187.231 +                }
 187.232 +            }
 187.233 +        }
 187.234 +
 187.235 +        if (targets.size() > 0) {
 187.236 +            List<Name> names = new ArrayList<>(targets.size());
 187.237 +            boolean valid = true;
 187.238 +            for (expr et : targets) {
 187.239 +                if (et instanceof Name) {
 187.240 +                    Name name = (Name)et;
 187.241 +                    names.add(name);
 187.242 +                } else {
 187.243 +                    valid = false;
 187.244 +                }
 187.245 +            }
 187.246 +            if (valid) {
 187.247 +                expr nodeValue = node.getInternalValue();
 187.248 +                if (nodeValue instanceof Name) {
 187.249 +                    Name value = (Name)nodeValue;
 187.250 +
 187.251 +                    SymInfo rhsSym = cur.tbl.get(value.getInternalId());
 187.252 +                    if (rhsSym != null && rhsSym.isDef()) {
 187.253 +                        for (Name name : names) {
 187.254 +                            visitName(name);
 187.255 +                            SymInfo sym = cur.tbl.get(name.getInternalId());
 187.256 +                            if (sym != null) {
 187.257 +                                sym.flags |= ALIAS;
 187.258 +                                sym.flags |= (rhsSym.flags & (CLASS | FUNCTION));
 187.259 +                                sym.node = rhsSym.node;
 187.260 +                            }
 187.261 +                        }
 187.262 +                    }
 187.263 +                }
 187.264 +            }
 187.265 +        }
 187.266 +
 187.267 +        return super.visitAssign(node);
 187.268 +    }
 187.269 +
 187.270 +    @Override
 187.271 +    public Object visitFunctionDef(FunctionDef node) throws Exception {
 187.272 +        def(node.getInternalName(), FUNCTION, node);
 187.273 +        ArgListCompiler ac = new ArgListCompiler(symbolTable);
 187.274 +        ac.visitArgs(node.getInternalArgs());
 187.275 +
 187.276 +        List<expr> defaults = ac.getDefaults();
 187.277 +        for (int i = 0; i < defaults.size(); i++) {
 187.278 +            visit(defaults.get(i));
 187.279 +        }
 187.280 +
 187.281 +        List<expr> decs = node.getInternalDecorator_list();
 187.282 +        for (int i = decs.size() - 1; i >= 0; i--) {
 187.283 +            visit(decs.get(i));
 187.284 +        }
 187.285 +
 187.286 +        ScopeInfo parentScope = cur;
 187.287 +        beginScope(node.getInternalName(), FUNCSCOPE, node, ac);
 187.288 +        cur.nested = parentScope;
 187.289 +
 187.290 +        int n = ac.names.size();
 187.291 +        for (int i = 0; i < n; i++) {
 187.292 +            cur.addParam(ac.names.get(i), ac.nodes.get(i));
 187.293 +        }
 187.294 +        for (int i = 0; i < ac.init_code.size(); i++) {
 187.295 +            visit(ac.init_code.get(i));
 187.296 +        }
 187.297 +        cur.markFromParam();
 187.298 +
 187.299 +        PythonTree oldParent = parent;
 187.300 +        parent = node;
 187.301 +        suite(node.getInternalBody());
 187.302 +        parent = oldParent;
 187.303 +
 187.304 +        endScope();
 187.305 +        return null;
 187.306 +    }
 187.307 +
 187.308 +    @Override
 187.309 +    public Object visitLambda(Lambda node) throws Exception {
 187.310 +        ArgListCompiler ac = new ArgListCompiler(symbolTable);
 187.311 +        ac.visitArgs(node.getInternalArgs());
 187.312 +
 187.313 +        List<expr> defaults = ac.getDefaults();
 187.314 +        for (expr expr : defaults) {
 187.315 +            visit(expr);
 187.316 +        }
 187.317 +
 187.318 +        beginScope("<lambda>", FUNCSCOPE, node, ac);
 187.319 +        assert ac.names.size() == ac.nodes.size();
 187.320 +        for (int i = 0; i < ac.names.size(); i++) {
 187.321 +            cur.addParam(ac.names.get(i), ac.nodes.get(i));
 187.322 +        }
 187.323 +        for (Object o : ac.init_code) {
 187.324 +            visit((stmt)o);
 187.325 +        }
 187.326 +        cur.markFromParam();
 187.327 +        visit(node.getInternalBody());
 187.328 +        endScope();
 187.329 +        return null;
 187.330 +    }
 187.331 +
 187.332 +    public void suite(List<stmt> stmts) throws Exception {
 187.333 +        if (stmts != null) {
 187.334 +            for (int i = 0; i < stmts.size(); i++) {
 187.335 +                stmt s = stmts.get(i);
 187.336 +                path.descend(s);
 187.337 +                visit(s);
 187.338 +                path.ascend();
 187.339 +            }
 187.340 +        }
 187.341 +    }
 187.342 +
 187.343 +    @Override
 187.344 +    public Object visitImport(Import node) throws Exception {
 187.345 +        if (parent == root) {
 187.346 +            topLevelImports.add(node);
 187.347 +        }
 187.348 +        imports.add(node);
 187.349 +
 187.350 +        List<alias> names = node.getInternalNames();
 187.351 +        if (names != null) {
 187.352 +            for (alias alias : names) {
 187.353 +                String asname = alias.getInternalAsname();
 187.354 +                if (asname != null) {
 187.355 +                    SymInfo entry = cur.addBound(asname, node);
 187.356 +                    entry.flags |= IMPORTED;
 187.357 +                } else {
 187.358 +                    String name = alias.getInternalName();
 187.359 +                    if (name.indexOf('.') > 0) {
 187.360 +                        name = name.substring(0, name.indexOf('.'));
 187.361 +                    }
 187.362 +                    SymInfo entry = cur.addBound(name, node);
 187.363 +                    entry.flags |= IMPORTED;
 187.364 +                }
 187.365 +            }
 187.366 +        }
 187.367 +        return null;
 187.368 +    }
 187.369 +
 187.370 +    @Override
 187.371 +    public Object visitImportFrom(ImportFrom node) throws Exception {
 187.372 +        if (parent == root) {
 187.373 +            topLevelImports.add(node);
 187.374 +        }
 187.375 +        importsFrom.add(node);
 187.376 +
 187.377 +        //Future.checkFromFuture(node); // future stmt support
 187.378 +        List<alias> names = node.getInternalNames();
 187.379 +        if (names == null || names.size() == 0) {
 187.380 +            cur.from_import_star = true;
 187.381 +            return null;
 187.382 +        }
 187.383 +        for (alias alias : names) {
 187.384 +            String asname = alias.getInternalAsname();
 187.385 +            if (asname != null) {
 187.386 +                SymInfo entry = cur.addBound(asname, node);
 187.387 +                entry.flags |= IMPORTED;
 187.388 +            } else {
 187.389 +                SymInfo entry = cur.addBound(alias.getInternalName(), node);
 187.390 +                entry.flags |= IMPORTED;
 187.391 +            }
 187.392 +        }
 187.393 +        return null;
 187.394 +    }
 187.395 +
 187.396 +    @Override
 187.397 +    public Object visitGlobal(Global node) throws Exception {
 187.398 +        List<String> names = node.getInternalNames();
 187.399 +        for (String name : names) {
 187.400 +            int prev = cur.addGlobal(name, node);
 187.401 +            if (prev >= 0) {
 187.402 +                if ((prev & FROM_PARAM) != 0) {
 187.403 +                    symbolTable.error("name '" + name + "' is local and global", true, node);
 187.404 +                }
 187.405 +                if ((prev & GLOBAL) != 0) {
 187.406 +                    continue;
 187.407 +                }
 187.408 +                String what;
 187.409 +                if ((prev & BOUND) != 0) {
 187.410 +                    what = "assignment";
 187.411 +                } else {
 187.412 +                    what = "use";
 187.413 +                }
 187.414 +                symbolTable.error("name '" + name + "' declared global after " + what, false, node);
 187.415 +            }
 187.416 +        }
 187.417 +        return null;
 187.418 +    }
 187.419 +
 187.420 +    @Override
 187.421 +    public Object visitExec(Exec node) throws Exception {
 187.422 +        cur.exec = true;
 187.423 +        if (node.getInternalGlobals() == null && node.getInternalLocals() == null) {
 187.424 +            cur.unqual_exec = true;
 187.425 +        }
 187.426 +        traverse(node);
 187.427 +        return null;
 187.428 +    }
 187.429 +
 187.430 +    @Override
 187.431 +    public Object visitClassDef(ClassDef node) throws Exception {
 187.432 +        String name = node.getInternalName();
 187.433 +        def(name, CLASS, node);
 187.434 +        List<expr> bases = node.getInternalBases();
 187.435 +        if (bases != null) {
 187.436 +            for (expr expr : bases) {
 187.437 +                visit(expr);
 187.438 +            }
 187.439 +        }
 187.440 +        ScopeInfo parentScope = cur;
 187.441 +        beginScope(name, CLASSSCOPE, node, null);
 187.442 +        cur.nested = parentScope;
 187.443 +        PythonTree oldParent = parent;
 187.444 +        parent = node;
 187.445 +        suite(node.getInternalBody());
 187.446 +        parent = oldParent;
 187.447 +        endScope();
 187.448 +        return null;
 187.449 +    }
 187.450 +
 187.451 +    @Override
 187.452 +    public Object visitName(Name node) throws Exception {
 187.453 +        // Jython's parser doesn't always initialize the parent references correctly;
 187.454 +        // try to correct that here.
 187.455 +        node.setParent(parent);
 187.456 +
 187.457 +        String name = node.getInternalId();
 187.458 +        if (node.getInternalCtx() != expr_contextType.Load) {
 187.459 +            if (name.equals("__debug__")) {
 187.460 +                symbolTable.error("can not assign to __debug__", true, node);
 187.461 +            }
 187.462 +            cur.addBound(name, node);
 187.463 +        } else {
 187.464 +            cur.addUsed(name, node);
 187.465 +        }
 187.466 +        return null;
 187.467 +    }
 187.468 +
 187.469 +    // <netbeans>
 187.470 +    @Override
 187.471 +    public Object visitCall(Call node) throws Exception {
 187.472 +        Object ret = super.visitCall(node);
 187.473 +
 187.474 +        expr func = node.getInternalFunc();
 187.475 +        if (func instanceof Name) {
 187.476 +            Name name = (Name)func;
 187.477 +            cur.markCall(name.getInternalId());
 187.478 +        } else if (func instanceof Attribute) {
 187.479 +            Attribute attr = (Attribute)func;
 187.480 +            if (cur.attributes != null) {
 187.481 +                SymInfo funcSymbol = cur.attributes.get(attr.getInternalAttr());
 187.482 +                if (funcSymbol != null) {
 187.483 +                    funcSymbol.flags |= FUNCTION | CALLED; // mark as func/method call
 187.484 +                }
 187.485 +            }
 187.486 +
 187.487 +        }
 187.488 +
 187.489 +        return ret;
 187.490 +    }
 187.491 +
 187.492 +    @Override
 187.493 +    public Object visitDelete(Delete node) throws Exception {
 187.494 +        for (expr et : node.getInternalTargets()) {
 187.495 +            if (et instanceof Name) {
 187.496 +                String name = ((Name)et).getInternalId();
 187.497 +                cur.addUsed(name, node);
 187.498 +            }
 187.499 +        }
 187.500 +
 187.501 +        return super.visitDelete(node);
 187.502 +    }
 187.503 +
 187.504 +    @Override
 187.505 +    public Object visitAttribute(Attribute node) throws Exception {
 187.506 +        if (parent instanceof Call && node.getInternalValue() instanceof Name &&
 187.507 +                ("__all__".equals(((Name)node.getInternalValue()).getInternalId()))) {
 187.508 +            // If you for example call
 187.509 +            //    __all__.extend("foo")
 187.510 +            // or
 187.511 +            //    __all__.append("bar")
 187.512 +            // then I don't want to try to analyze __all__
 187.513 +            String nodeAttr = node.getInternalAttr();
 187.514 +            if ("extend".equals(nodeAttr) || "append".equals(nodeAttr)) { // NOI18N
 187.515 +                Call call = (Call)parent;
 187.516 +                List<expr> callArgs = call.getInternalArgs();
 187.517 +                if (callArgs != null) {
 187.518 +                    for (expr expr : callArgs) {
 187.519 +                        if (expr instanceof Str) {
 187.520 +                            if (publicSymbols == null) {
 187.521 +                                publicSymbols = new ArrayList<>();
 187.522 +                            }
 187.523 +                            publicSymbols.add((Str)expr);
 187.524 +                        } else if (expr instanceof org.python.antlr.ast.List) {
 187.525 +                            org.python.antlr.ast.List list = (org.python.antlr.ast.List)expr;
 187.526 +                            if (list != null) {
 187.527 +                                List<expr> elts = list.getInternalElts();
 187.528 +                                if (elts != null) {
 187.529 +                                    for (expr ex : elts) {
 187.530 +                                        if (ex instanceof Str) {
 187.531 +                                            Str str = (Str)ex;
 187.532 +                                            if (publicSymbols == null) {
 187.533 +                                                publicSymbols = new ArrayList<>();
 187.534 +                                            }
 187.535 +                                            publicSymbols.add(str);
 187.536 +                                        } else {
 187.537 +                                            invalidPublicSymbols = true;
 187.538 +                                        }
 187.539 +                                    }
 187.540 +                                }
 187.541 +                            }
 187.542 +                        } else {
 187.543 +                            invalidPublicSymbols = true;
 187.544 +                            break;
 187.545 +                        }
 187.546 +                    }
 187.547 +                }
 187.548 +            } else {
 187.549 +                invalidPublicSymbols = true;
 187.550 +            }
 187.551 +        } else {
 187.552 +            String nodeAttr = node.getInternalAttr();
 187.553 +            if (nodeAttr != null) {
 187.554 +                cur.addAttribute(path, nodeAttr, node);
 187.555 +            }
 187.556 +        }
 187.557 +        return super.visitAttribute(node);
 187.558 +    }
 187.559 +    // </netbeans>
 187.560 +
 187.561 +    @Override
 187.562 +    public Object visitListComp(ListComp node) throws Exception {
 187.563 +        String tmp = "_[" + node.getLine() + "_" + node.getCharPositionInLine() + "]";
 187.564 +        cur.addBound(tmp, node);
 187.565 +        traverse(node);
 187.566 +        return null;
 187.567 +    }
 187.568 +
 187.569 +    @Override
 187.570 +    public Object visitYield(Yield node) throws Exception {
 187.571 +        cur.defineAsGenerator(node);
 187.572 +        cur.yield_count++;
 187.573 +        traverse(node);
 187.574 +        return null;
 187.575 +    }
 187.576 +
 187.577 +    @Override
 187.578 +    public Object visitReturn(Return node) throws Exception {
 187.579 +        if (node.getInternalValue() != null) {
 187.580 +            cur.noteReturnValue(node);
 187.581 +        }
 187.582 +        traverse(node);
 187.583 +        return null;
 187.584 +    }
 187.585 +
 187.586 +    @Override
 187.587 +    public Object visitGeneratorExp(GeneratorExp node) throws Exception {
 187.588 +        // The first iterator is evaluated in the outer scope
 187.589 +        if (node.getInternalGenerators() != null && node.getInternalGenerators().size() > 0) {
 187.590 +            visit(node.getInternalGenerators().get(0).getInternalIter());
 187.591 +        }
 187.592 +        String bound_exp = "_(x)";
 187.593 +        String tmp = "_(" + node.getLine() + "_" + node.getCharPositionInLine() + ")";
 187.594 +        def(tmp, GENERATOR, node);
 187.595 +        ArgListCompiler ac = new ArgListCompiler(symbolTable);
 187.596 +        List<expr> args = new ArrayList<>();
 187.597 +        Name argsName = new Name(node.getToken(), bound_exp, expr_contextType.Param);
 187.598 +        args.add(argsName);
 187.599 +        ac.visitArgs(new arguments(node, args, null, null, new ArrayList<expr>()));
 187.600 +        beginScope(tmp, FUNCSCOPE, node, ac);
 187.601 +        cur.addParam(bound_exp, argsName);
 187.602 +        cur.markFromParam();
 187.603 +
 187.604 +        cur.defineAsGenerator(node);
 187.605 +        cur.yield_count++;
 187.606 +        // The reset of the iterators are evaluated in the inner scope
 187.607 +        if (node.getInternalElt() != null) {
 187.608 +            visit(node.getInternalElt());
 187.609 +        }
 187.610 +        if (node.getInternalGenerators() != null) {
 187.611 +            for (int i = 0; i < node.getInternalGenerators().size(); i++) {
 187.612 +                if (node.getInternalGenerators().get(i) != null) {
 187.613 +                    if (i == 0) {
 187.614 +                        visit(node.getInternalGenerators().get(i).getInternalTarget());
 187.615 +                        if (node.getInternalGenerators().get(i).getInternalIfs() != null) {
 187.616 +                            for (expr cond : node.getInternalGenerators().get(i).getInternalIfs()) {
 187.617 +                                if (cond != null) {
 187.618 +                                    visit(cond);
 187.619 +                                }
 187.620 +                            }
 187.621 +                        }
 187.622 +                    } else {
 187.623 +                        visit(node.getInternalGenerators().get(i));
 187.624 +                    }
 187.625 +                }
 187.626 +            }
 187.627 +        }
 187.628 +
 187.629 +        endScope();
 187.630 +        return null;
 187.631 +    }
 187.632 +
 187.633 +    @Override
 187.634 +    public Object visitWith(With node) throws Exception {
 187.635 +        cur.max_with_count++;
 187.636 +        traverse(node);
 187.637 +
 187.638 +        return null;
 187.639 +    }
 187.640 +
 187.641 +    public List<Str> getPublicSymbols() {
 187.642 +        return invalidPublicSymbols ? null : publicSymbols;
 187.643 +    }
 187.644 +}
   188.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   188.2 +++ b/python.source/src/org/netbeans/modules/python/source/scopes/SymInfo.java	Mon Sep 21 13:01:16 2015 +0200
   188.3 @@ -0,0 +1,184 @@
   188.4 +package org.netbeans.modules.python.source.scopes;
   188.5 +
   188.6 +import org.python.antlr.PythonTree;
   188.7 +import static org.netbeans.modules.python.source.scopes.ScopeConstants.*;
   188.8 +
   188.9 +public class SymInfo extends Object {
  188.10 +    public SymInfo(int flags) {
  188.11 +        this.flags = flags;
  188.12 +    }
  188.13 +
  188.14 +    public SymInfo(int flags, int locals_index) {
  188.15 +        this.flags = flags;
  188.16 +        this.locals_index = locals_index;
  188.17 +    }
  188.18 +    public int flags;
  188.19 +    public int locals_index;
  188.20 +    public int env_index;
  188.21 +    public PythonTree node;
  188.22 +
  188.23 +    @Override
  188.24 +    public String toString() {
  188.25 +        return "SymInfo[" + flags + " " + locals_index + " " +
  188.26 +                env_index + "]" + dumpFlags(null);
  188.27 +    }
  188.28 +
  188.29 +    public String dumpFlags(ScopeInfo info) {
  188.30 +        StringBuilder sb = new StringBuilder();
  188.31 +        if ((flags & BOUND) != 0) {
  188.32 +            sb.append("[bound]");
  188.33 +        }
  188.34 +        // func scope global (affect nested scopes)
  188.35 +        // vs. class scope global
  188.36 +        if ((flags & NGLOBAL) != 0) {
  188.37 +            sb.append("[func-global]");
  188.38 +        } else if ((flags & CLASS_GLOBAL) != 0) {
  188.39 +            sb.append("[class-global]");
  188.40 +        }
  188.41 +        if ((flags & PARAM) != 0) {
  188.42 +            sb.append("[param]");
  188.43 +        } else if ((flags & FROM_PARAM) != 0) {
  188.44 +            sb.append("[from-param]");
  188.45 +        }
  188.46 +        if ((flags & CELL) != 0) {
  188.47 +            sb.append("[cell]");
  188.48 +        }
  188.49 +        if ((flags & FREE) != 0) {
  188.50 +            sb.append("[free]");
  188.51 +        }
  188.52 +        if (isImported()) {
  188.53 +            sb.append("[imported]");
  188.54 +        }
  188.55 +        if (isPrivate()) {
  188.56 +            sb.append("[private]");
  188.57 +        }
  188.58 +        if (isClass()) {
  188.59 +            sb.append("[class]");
  188.60 +        }
  188.61 +        if (isFunction()) {
  188.62 +            sb.append("[function]");
  188.63 +        }
  188.64 +        if (isData()) {
  188.65 +            sb.append("[data]");
  188.66 +        }
  188.67 +        if (isMember()) {
  188.68 +            sb.append("[member]");
  188.69 +        }
  188.70 +        if (isDef()) {
  188.71 +            sb.append("[def]");
  188.72 +        }
  188.73 +        if (isRead()) {
  188.74 +            sb.append("[read]");
  188.75 +        }
  188.76 +        if (isAlias()) {
  188.77 +            sb.append("[alias]");
  188.78 +        }
  188.79 +        if (isGeneratorExp()) {
  188.80 +            sb.append("[generator]");
  188.81 +        }
  188.82 +        if (isCalled()) {
  188.83 +            sb.append("[called]");
  188.84 +        }
  188.85 +        if (isProtected()) {
  188.86 +            sb.append("[protected]");
  188.87 +        }
  188.88 +        if (isBoundInConstructor()) {
  188.89 +            sb.append("[bound-in-constructor]");
  188.90 +        }
  188.91 +        if (isUnused(info)) {
  188.92 +            sb.append("[unused]");
  188.93 +        }
  188.94 +        if (isUnresolved()) {
  188.95 +            sb.append("[UNRESOLVED]");
  188.96 +        }
  188.97 +        sb.append("[node=");
  188.98 +        if (node != null) {
  188.99 +            sb.append(node.getClass().getSimpleName());
 188.100 +        } else {
 188.101 +            sb.append("null");
 188.102 +        }
 188.103 +        sb.append("]");
 188.104 +
 188.105 +        return sb.toString();
 188.106 +    }
 188.107 +
 188.108 +    public boolean isUnused(ScopeInfo info) {
 188.109 +        // Cannot correctly detect usage of variables in CLASSSCOPE
 188.110 +        return (info == null || info.kind == FUNCSCOPE || info.kind == TOPSCOPE) &&
 188.111 +                (flags & (READ | BOUND | DEF)) == BOUND;
 188.112 +    }
 188.113 +
 188.114 +    public boolean isParameter() {
 188.115 +        return (flags & (PARAM | FROM_PARAM)) != 0;
 188.116 +    }
 188.117 +
 188.118 +    public boolean isUnresolved() {
 188.119 +        return (flags & (BOUND | FREE)) == 0;
 188.120 +    }
 188.121 +
 188.122 +    public boolean isImported() {
 188.123 +        return (flags & IMPORTED) != 0;
 188.124 +    }
 188.125 +
 188.126 +    public boolean isData() {
 188.127 +        return (flags & (BOUND | DEF | CLASS | FUNCTION)) == (BOUND);
 188.128 +    }
 188.129 +
 188.130 +    public boolean isClass() {
 188.131 +        return (flags & CLASS) != 0;
 188.132 +    }
 188.133 +
 188.134 +    public boolean isDef() {
 188.135 +        return (flags & DEF) != 0;
 188.136 +    }
 188.137 +
 188.138 +    public boolean isFunction() {
 188.139 +        return (flags & FUNCTION) != 0;
 188.140 +    }
 188.141 +
 188.142 +    public boolean isBound() {
 188.143 +        return (flags & BOUND) != 0;
 188.144 +    }
 188.145 +
 188.146 +    public boolean isMember() {
 188.147 +        return (flags & MEMBER) != 0;
 188.148 +    }
 188.149 +
 188.150 +    public boolean isCalled() {
 188.151 +        return (flags & CALLED) != 0;
 188.152 +    }
 188.153 +
 188.154 +    public boolean isRead() {
 188.155 +        return (flags & READ) != 0;
 188.156 +    }
 188.157 +
 188.158 +    public boolean isGeneratorExp() {
 188.159 +        return (flags & GENERATOR) != 0;
 188.160 +    }
 188.161 +
 188.162 +    public boolean isFree() {
 188.163 +        return (flags & FREE) != 0;
 188.164 +    }
 188.165 +
 188.166 +    public boolean isPrivate() {
 188.167 +        return (flags & PRIVATE) != 0;
 188.168 +    }
 188.169 +
 188.170 +    public boolean isProtected() {
 188.171 +        return (flags & PROTECTED) != 0;
 188.172 +    }
 188.173 +
 188.174 +    public boolean isBoundInConstructor() {
 188.175 +        return (flags & BOUND_IN_CONSTRUCTOR) != 0;
 188.176 +    }
 188.177 +
 188.178 +    public boolean isAlias() {
 188.179 +        return (flags & ALIAS) != 0;
 188.180 +    }
 188.181 +
 188.182 +    public boolean isVariable(boolean mustBeBound) {
 188.183 +        int mask = mustBeBound ? BOUND : 0;
 188.184 +        return (flags & (BOUND | CALLED | DEF | IMPORTED | CLASS | FUNCTION | MEMBER | GENERATOR)) == mask;
 188.185 +    }
 188.186 +
 188.187 +}
   189.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   189.2 +++ b/python.source/src/org/netbeans/modules/python/source/scopes/SymbolTable.java	Mon Sep 21 13:01:16 2015 +0200
   189.3 @@ -0,0 +1,1247 @@
   189.4 +/*
   189.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   189.6 + *
   189.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   189.8 + *
   189.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  189.10 + * Other names may be trademarks of their respective owners.
  189.11 + *
  189.12 + * The contents of this file are subject to the terms of either the GNU
  189.13 + * General Public License Version 2 only ("GPL") or the Common
  189.14 + * Development and Distribution License("CDDL") (collectively, the
  189.15 + * "License"). You may not use this file except in compliance with the
  189.16 + * License. You can obtain a copy of the License at
  189.17 + * http://www.netbeans.org/cddl-gplv2.html
  189.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  189.19 + * specific language governing permissions and limitations under the
  189.20 + * License.  When distributing the software, include this License Header
  189.21 + * Notice in each file and include the License file at
  189.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  189.23 + * particular file as subject to the "Classpath" exception as provided
  189.24 + * by Oracle in the GPL Version 2 section of the License file that
  189.25 + * accompanied this code. If applicable, add the following below the
  189.26 + * License Header, with the fields enclosed by brackets [] replaced by
  189.27 + * your own identifying information:
  189.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  189.29 + *
  189.30 + * If you wish your version of this file to be governed by only the CDDL
  189.31 + * or only the GPL Version 2, indicate your decision by adding
  189.32 + * "[Contributor] elects to include this software in this distribution
  189.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  189.34 + * single choice of license, a recipient has the option to distribute
  189.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  189.36 + * to extend the choice of license to its licensees as provided above.
  189.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  189.38 + * Version 2 license, then the option applies only if the new code is
  189.39 + * made subject to such option by the copyright holder.
  189.40 + *
  189.41 + * Contributor(s):
  189.42 + *
  189.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  189.44 + */
  189.45 +package org.netbeans.modules.python.source.scopes;
  189.46 +
  189.47 +import java.util.ArrayList;
  189.48 +import java.util.Collections;
  189.49 +import java.util.HashMap;
  189.50 +import java.util.HashSet;
  189.51 +import java.util.List;
  189.52 +import java.util.Map;
  189.53 +import java.util.Set;
  189.54 +import org.netbeans.modules.csl.api.ElementKind;
  189.55 +import org.netbeans.modules.csl.api.OffsetRange;
  189.56 +import org.netbeans.modules.csl.api.Severity;
  189.57 +import org.netbeans.modules.csl.api.Error;
  189.58 +import org.netbeans.modules.csl.spi.DefaultError;
  189.59 +import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
  189.60 +import org.netbeans.modules.python.source.PythonAstUtils;
  189.61 +import org.netbeans.modules.python.source.PythonIndex;
  189.62 +import org.netbeans.modules.python.source.PythonIndexer;
  189.63 +import org.netbeans.modules.python.source.PythonParserResult;
  189.64 +import org.netbeans.modules.python.source.PythonUtils;
  189.65 +import org.netbeans.modules.python.source.elements.AstElement;
  189.66 +import org.netbeans.modules.python.source.elements.Element;
  189.67 +import org.netbeans.modules.python.source.elements.IndexedElement;
  189.68 +import org.netbeans.modules.python.source.ImportEntry;
  189.69 +import org.netbeans.modules.python.source.ImportManager;
  189.70 +import org.openide.filesystems.FileObject;
  189.71 +import org.openide.filesystems.FileUtil;
  189.72 +import org.openide.util.Exceptions;
  189.73 +import org.python.antlr.PythonTree;
  189.74 +import org.python.antlr.Visitor;
  189.75 +import org.python.antlr.ast.Attribute;
  189.76 +import org.python.antlr.ast.ClassDef;
  189.77 +import org.python.antlr.ast.Expression;
  189.78 +import org.python.antlr.ast.FunctionDef;
  189.79 +import org.python.antlr.ast.GeneratorExp;
  189.80 +import org.python.antlr.ast.Import;
  189.81 +import org.python.antlr.ast.ImportFrom;
  189.82 +import org.python.antlr.ast.Interactive;
  189.83 +import org.python.antlr.ast.Lambda;
  189.84 +import org.python.antlr.ast.Name;
  189.85 +import org.python.antlr.ast.Str;
  189.86 +import org.python.antlr.ast.alias;
  189.87 +import org.python.antlr.base.expr;
  189.88 +import static org.netbeans.modules.python.source.scopes.ScopeConstants.*;
  189.89 +
  189.90 +/**
  189.91 + * A symbol table tracks a bunch of scopes and can answer questions about defined
  189.92 + * symbols.
  189.93 + *
  189.94 + * Based on Jython's ScopeManager.
  189.95 + *
  189.96 + * @author Tor Norbye
  189.97 + */
  189.98 +public class SymbolTable {
  189.99 +    private final static int YES = 1;
 189.100 +    private final static int NO = 0;
 189.101 +    private final static int CIRCULAR = -1;
 189.102 +    private Map<PythonTree, ScopeInfo> scopes = new HashMap<>();
 189.103 +    private PythonTree root;
 189.104 +    private FileObject fileObject;
 189.105 +    private List<Import> imports = new ArrayList<>();
 189.106 +    private List<ImportFrom> importsFrom = new ArrayList<>();
 189.107 +    private List<PythonTree> mainImports = new ArrayList<>();
 189.108 +    private Set<PythonTree> topLevelImports = new HashSet<>();
 189.109 +    private List<Error> errors;
 189.110 +    /** List of symbols registered via __all__ = [ "foo", "bar" ] or __all__.extend() or __all__.append() */
 189.111 +    private List<Str> publicSymbols;
 189.112 +    private final static HashMap<String, String> classAttributes = new HashMap<String, String>() {
 189.113 +        {
 189.114 +            put("__class__", "__class__");
 189.115 +            put("__bases__", "__bases__");
 189.116 +            put("__dict__", "__dict__");
 189.117 +            put("__doc__", "__doc__");
 189.118 +            put("__name__", "__bases");
 189.119 +        }
 189.120 +    };
 189.121 +    private HashMap<String, ClassDef> classes = new HashMap<>();
 189.122 +    // TODO - use WeakHashMap?
 189.123 +    static Map<String, Set<IndexedElement>> importedElements = new HashMap<>();
 189.124 +
 189.125 +    private HashMap<String, ClassDef> buildLocalClasses() {
 189.126 +        HashMap<String, ClassDef> localClasses = new HashMap<>();
 189.127 +        for (PythonTree cur : scopes.keySet()) {
 189.128 +            if (cur instanceof ClassDef) {
 189.129 +                ClassDef curClass = (ClassDef)cur;
 189.130 +                localClasses.put(curClass.getInternalName(), curClass);
 189.131 +            }
 189.132 +        }
 189.133 +        return localClasses;
 189.134 +    }
 189.135 +
 189.136 +    public SymbolTable(PythonTree root, FileObject fileObject) {
 189.137 +        this.root = root;
 189.138 +        this.fileObject = fileObject;
 189.139 +
 189.140 +        if (root != null) {
 189.141 +            try {
 189.142 +                ScopesCompiler compiler = new ScopesCompiler(this, scopes, root, imports, importsFrom, mainImports, topLevelImports);
 189.143 +                compiler.parse();
 189.144 +                publicSymbols = compiler.getPublicSymbols();
 189.145 +                classes = buildLocalClasses();
 189.146 +                if (publicSymbols != null) {
 189.147 +                    // Mark all other symbols private!
 189.148 +                    Set<String> names = new HashSet<>(publicSymbols.size() + 1);
 189.149 +                    names.add("__all__"); // __all__ itself is exported!
 189.150 +                    for (Str str : publicSymbols) {
 189.151 +                        String name = PythonAstUtils.getStrContent(str);
 189.152 +                        if (name != null) {
 189.153 +                            names.add(name);
 189.154 +                        }
 189.155 +                    }
 189.156 +
 189.157 +                    ScopeInfo topScope = scopes.get(root);
 189.158 +                    if (topScope != null) {
 189.159 +                        for (Map.Entry<String, SymInfo> entry : topScope.tbl.entrySet()) {
 189.160 +                            String name = entry.getKey();
 189.161 +                            if (!names.contains(name)) {
 189.162 +                                SymInfo sym = entry.getValue();
 189.163 +                                sym.flags |= PRIVATE;
 189.164 +                                if (sym.isDef() && sym.node != null) {
 189.165 +                                    ScopeInfo scope = scopes.get(sym.node);
 189.166 +                                    scope.hidden = true;
 189.167 +                                }
 189.168 +                            }
 189.169 +                        }
 189.170 +                    }
 189.171 +
 189.172 +                    for (Map.Entry<PythonTree, ScopeInfo> entry : scopes.entrySet()) {
 189.173 +                        ScopeInfo scope = entry.getValue();
 189.174 +                        boolean isHidden = false;
 189.175 +                        ScopeInfo curr = scope;
 189.176 +                        while (curr != null) {
 189.177 +                            if (curr.hidden) {
 189.178 +                                isHidden = true;
 189.179 +                                break;
 189.180 +                            }
 189.181 +                            if (curr.nested != null) {
 189.182 +                                curr = curr.nested;
 189.183 +                            } else {
 189.184 +                                curr = curr.up;
 189.185 +                            }
 189.186 +
 189.187 +                        }
 189.188 +                        if (isHidden) {
 189.189 +                            scope.hidden = true;
 189.190 +                        }
 189.191 +                    }
 189.192 +
 189.193 +                    // Mark all symbols private, unless the scope is a direct descendant
 189.194 +                    // of a public symbol
 189.195 +                    for (ScopeInfo scope : scopes.values()) {
 189.196 +                        if (scope.hidden) {
 189.197 +                            for (SymInfo sym : scope.tbl.values()) {
 189.198 +                                sym.flags |= PRIVATE;
 189.199 +                            }
 189.200 +                        }
 189.201 +                    }
 189.202 +                }
 189.203 +            } catch (Exception ex) {
 189.204 +                Exceptions.printStackTrace(ex);
 189.205 +            }
 189.206 +        }
 189.207 +    }
 189.208 +
 189.209 +    public boolean isPrivate(PythonTree node, String name) {
 189.210 +        ScopeInfo scope = scopes.get(node);
 189.211 +        if (scope == null) {
 189.212 +            scope = scopes.get(root);
 189.213 +        }
 189.214 +        if (scope != null) {
 189.215 +            if (scope.up != null) {
 189.216 +                if (scope.hidden) {
 189.217 +                    return true;
 189.218 +                }
 189.219 +                // Look in parent's scope table
 189.220 +                if (scope.nested != null) {
 189.221 +                    scope = scope.nested;
 189.222 +                } else {
 189.223 +                    scope = scope.up;
 189.224 +                }
 189.225 +                if (scope != null) {
 189.226 +                    SymInfo sym = scope.tbl.get(name);
 189.227 +                    if (sym != null) {
 189.228 +                        return sym.isPrivate();
 189.229 +                    }
 189.230 +                }
 189.231 +            } else {
 189.232 +                SymInfo sym = scope.tbl.get(name);
 189.233 +                if (sym != null) {
 189.234 +                    return sym.isPrivate();
 189.235 +                }
 189.236 +            }
 189.237 +        }
 189.238 +
 189.239 +        return false;
 189.240 +    }
 189.241 +
 189.242 +    public SymInfo findDeclaration(PythonTree scope, String name, boolean allowFree) {
 189.243 +        ScopeInfo scopeInfo = getScopeInfo(scope);
 189.244 +        if (scopeInfo != null) {
 189.245 +            SymInfo sym = scopeInfo.tbl.get(name);
 189.246 +            SymInfo orig = sym;
 189.247 +            while (sym != null && sym.isFree()) {
 189.248 +                scopeInfo = scopeInfo.up;
 189.249 +                while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 189.250 +                    scopeInfo = scopeInfo.up;
 189.251 +                }
 189.252 +                sym = scopeInfo.tbl.get(name);
 189.253 +            }
 189.254 +
 189.255 +            if (allowFree && sym == null && orig != null) {
 189.256 +                // Free variable -- might have to resolve it
 189.257 +                return orig;
 189.258 +            }
 189.259 +
 189.260 +            // Look for attributes too
 189.261 +            if (sym == null) {
 189.262 +                sym = scopeInfo.attributes.get(name);
 189.263 +                orig = sym;
 189.264 +                while (sym != null && sym.isFree()) {
 189.265 +                    scopeInfo = scopeInfo.up;
 189.266 +                    while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 189.267 +                        scopeInfo = scopeInfo.up;
 189.268 +                    }
 189.269 +                    sym = scopeInfo.tbl.get(name);
 189.270 +                }
 189.271 +
 189.272 +                if (allowFree && sym == null && orig != null) {
 189.273 +                    // Free variable -- might have to resolve it
 189.274 +                    return orig;
 189.275 +                }
 189.276 +            }
 189.277 +
 189.278 +            return sym;
 189.279 +        }
 189.280 +
 189.281 +        return null;
 189.282 +    }
 189.283 +
 189.284 +    public ScopeInfo getScopeInfo(PythonTree node) {
 189.285 +        return scopes.get(node);
 189.286 +    }
 189.287 +
 189.288 +    public List<Error> getErrors() {
 189.289 +        return errors != null ? errors : Collections.<Error>emptyList();
 189.290 +    }
 189.291 +
 189.292 +    public SymInfo findBySignature(ElementKind kind, String signature) {
 189.293 +        PythonTree scope = root;
 189.294 +        String name = signature;
 189.295 +        int dot = signature.lastIndexOf('.');
 189.296 +        if (dot != -1) {
 189.297 +            String clz = signature.substring(0, dot);
 189.298 +            name = signature.substring(dot + 1);
 189.299 +            SymInfo sym = findDeclaration(root, clz, true);
 189.300 +            if (sym != null && sym.node != null) {
 189.301 +                scope = sym.node;
 189.302 +            }
 189.303 +        }
 189.304 +        SymInfo sym = findDeclaration(scope, name, true);
 189.305 +
 189.306 +        return sym;
 189.307 +    }
 189.308 +
 189.309 +    private List<String> getModulesToStarImport() {
 189.310 +        List<String> modules = new ArrayList<>();
 189.311 +
 189.312 +        for (ImportFrom from : importsFrom) {
 189.313 +            List<alias> names = from.getInternalNames();
 189.314 +            if (names != null) {
 189.315 +                for (alias at : names) {
 189.316 +                    if ("*".equals(at.getInternalName())) { // NOI18N
 189.317 +                        modules.add(from.getInternalModule());
 189.318 +                    }
 189.319 +                }
 189.320 +            }
 189.321 +        }
 189.322 +
 189.323 +        modules.addAll(PythonIndex.BUILTIN_MODULES);
 189.324 +
 189.325 +        return modules;
 189.326 +    }
 189.327 +
 189.328 +    private void addSymbolsFromModule(PythonParserResult info, String module, String prefix, QuerySupport.Kind kind, Set<? super IndexedElement> result) {
 189.329 +        if (PythonIndex.isBuiltinModule(module)) {
 189.330 +            Set<IndexedElement> all = getAllSymbolsFromModule(info, module);
 189.331 +            for (IndexedElement e : all) {
 189.332 +                if (kind == QuerySupport.Kind.PREFIX) {
 189.333 +                    if (e.getName().startsWith(prefix)) {
 189.334 +                        result.add(e);
 189.335 +                    }
 189.336 +                } else if (kind == QuerySupport.Kind.EXACT) {
 189.337 +                    if (prefix.equals(e.getName())) {
 189.338 +                        result.add(e);
 189.339 +                    }
 189.340 +                } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX) {
 189.341 +                    if (e.getName().regionMatches(true, 0, prefix, 0, prefix.length())) {
 189.342 +                        result.add(e);
 189.343 +                    }
 189.344 +                }
 189.345 +            }
 189.346 +        } else {
 189.347 +            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 189.348 +            Set<IndexedElement> elements = index.getImportedElements(prefix, kind, Collections.singleton(module), null);
 189.349 +            for (IndexedElement e : elements) {
 189.350 +                result.add(e);
 189.351 +            }
 189.352 +        }
 189.353 +    }
 189.354 +
 189.355 +    private Set<IndexedElement> getAllSymbolsFromModule(PythonParserResult info, String module) {
 189.356 +        Set<IndexedElement> elements = importedElements.get(module);
 189.357 +        if (elements == null) {
 189.358 +            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 189.359 +            Set<String> systemHolder = new HashSet<>(3);
 189.360 +            elements = index.getImportedElements("", QuerySupport.Kind.PREFIX, Collections.singleton(module), systemHolder);
 189.361 +            // Cache system modules - don't cache local modules
 189.362 +            if (!systemHolder.isEmpty()) {
 189.363 +                importedElements.put(module, elements);
 189.364 +            }
 189.365 +        }
 189.366 +
 189.367 +        return elements;
 189.368 +    }
 189.369 +
 189.370 +    public Set<Element> getDefinedElements(PythonParserResult info, PythonTree scope, String prefix, QuerySupport.Kind kind) {
 189.371 +        Set<Element> elements = new HashSet<>(300);
 189.372 +        ScopeInfo scopeInfo = scopes.get(scope);
 189.373 +        String module = PythonUtils.getModuleName(fileObject);
 189.374 +        String url = fileObject.toURL().toExternalForm();
 189.375 +
 189.376 +        // Get builtin symbols
 189.377 +        for (String mod : getModulesToStarImport()) {
 189.378 +            addSymbolsFromModule(info, mod, prefix, kind, elements);
 189.379 +        }
 189.380 +
 189.381 +        // I can't just search the scope table for all variables in scope because this
 189.382 +        // will only include the local -bound- variables and the -used- free variables.
 189.383 +        // I need to find potential free variables as well. This means I should walk up
 189.384 +        // the scope chain and compute all eligible names. By keep track of the ones I've
 189.385 +        // already added I avoid adding references to variables I have re-bound in closer
 189.386 +        // scopes.
 189.387 +
 189.388 +        Set<String> added = new HashSet<>();
 189.389 +
 189.390 +        while (scopeInfo != null) {
 189.391 +            for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 189.392 +                String name = entry.getKey();
 189.393 +                if (added.contains(name)) {
 189.394 +                    // Something in narrower scope already processed this one
 189.395 +                    continue;
 189.396 +                }
 189.397 +                if (kind == QuerySupport.Kind.EXACT) {
 189.398 +                    if (!(name.equals(prefix))) {
 189.399 +                        continue;
 189.400 +                    }
 189.401 +                } else if (kind == QuerySupport.Kind.PREFIX) {
 189.402 +                    if (!name.startsWith(prefix)) {
 189.403 +                        continue;
 189.404 +                    }
 189.405 +                } else if (kind == QuerySupport.Kind.CASE_INSENSITIVE_PREFIX) {
 189.406 +                    if (!name.regionMatches(true, 0, prefix, 0, prefix.length())) {
 189.407 +                        continue;
 189.408 +                    }
 189.409 +                }
 189.410 +                SymInfo sym = entry.getValue();
 189.411 +
 189.412 +                ScopeInfo curr = scopeInfo;
 189.413 +                while (sym != null && sym.isFree()) {
 189.414 +                    curr = curr.up;
 189.415 +                    while (curr != null && curr.kind == CLASSSCOPE) {
 189.416 +                        curr = curr.up;
 189.417 +                    }
 189.418 +                    if (curr == null) {
 189.419 +                        sym = null;
 189.420 +                        break;
 189.421 +                    }
 189.422 +                    sym = scopeInfo.tbl.get(name);
 189.423 +                }
 189.424 +                if (sym == null) {
 189.425 +                    continue;
 189.426 +                }
 189.427 +                if (sym.isUnresolved()) {
 189.428 +                    // Don't add completion items for stuff we're not sure about
 189.429 +                    continue;
 189.430 +                }
 189.431 +
 189.432 +                PythonTree node = sym.node;
 189.433 +                if (node == null) {
 189.434 +                    continue;
 189.435 +                }
 189.436 +
 189.437 +
 189.438 +                if (sym.isImported()) {
 189.439 +                    Element element = new AstElement(this, node, name, Character.isUpperCase(name.charAt(0)) ? ElementKind.CLASS : ElementKind.MODULE);
 189.440 +                    elements.add(element);
 189.441 +                } else if (sym.isDef()) {
 189.442 +                    String signature;
 189.443 +                    if (sym.isClass() && node instanceof ClassDef) {
 189.444 +                        signature = PythonIndexer.computeClassSig((ClassDef)node, sym);
 189.445 +                    } else if (sym.isFunction() && node instanceof FunctionDef) {
 189.446 +                        assert sym.isFunction() && node instanceof FunctionDef : name + ";" + sym + " in " + module;
 189.447 +                        signature = PythonIndexer.computeFunctionSig(name, (FunctionDef)node, sym);
 189.448 +                    } else {
 189.449 +                        // Probably a generator expression
 189.450 +                        continue;
 189.451 +                    }
 189.452 +                    //Element element = AstElement.create(null, node);
 189.453 +                    IndexedElement element = IndexedElement.create(signature, module, url, null);
 189.454 +                    element.setSmart(true);
 189.455 +                    elements.add(element);
 189.456 +                } else {
 189.457 +                    // TODO - class attributes?
 189.458 +                    Element element = new AstElement(this, node, name, ElementKind.VARIABLE);
 189.459 +                    elements.add(element);
 189.460 +                }
 189.461 +
 189.462 +                added.add(name);
 189.463 +            }
 189.464 +
 189.465 +            scopeInfo = scopeInfo.up;
 189.466 +            while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 189.467 +                scopeInfo = scopeInfo.up;
 189.468 +            }
 189.469 +        }
 189.470 +
 189.471 +        return elements;
 189.472 +    }
 189.473 +
 189.474 +    // Return all node references to the given name
 189.475 +    // This will include imports, calls, definitions, etc.
 189.476 +    public List<PythonTree> getOccurrences(PythonTree scope, String name, boolean abortOnFree) {
 189.477 +        ScopeInfo scopeInfo = scopes.get(scope);
 189.478 +        if (scopeInfo != null) {
 189.479 +            SymInfo sym = scopeInfo.tbl.get(name);
 189.480 +            while (sym != null && sym.isFree()) {
 189.481 +                if (abortOnFree) {
 189.482 +                    return null;
 189.483 +                }
 189.484 +                scopeInfo = scopeInfo.up;
 189.485 +                while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 189.486 +                    scopeInfo = scopeInfo.up;
 189.487 +                }
 189.488 +                sym = scopeInfo.tbl.get(name);
 189.489 +            }
 189.490 +
 189.491 +            if (sym != null) {
 189.492 +                NameNodeFinder finder = new NameNodeFinder(name, scopeInfo.scope_node);
 189.493 +                finder.run();
 189.494 +                return finder.getNodes();
 189.495 +            }
 189.496 +        }
 189.497 +
 189.498 +        return Collections.emptyList();
 189.499 +    }
 189.500 +
 189.501 +    /** Return a list of the variables visible from a given scope */
 189.502 +    public Set<String> getVarNames(PythonTree scope, boolean mustBeBound) {
 189.503 +        ScopeInfo scopeInfo = scopes.get(scope);
 189.504 +        Set<String> names = new HashSet<>();
 189.505 +        while (scopeInfo != null) {
 189.506 +            for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 189.507 +                String name = entry.getKey();
 189.508 +                SymInfo sym = entry.getValue();
 189.509 +                if (sym.isVariable(mustBeBound)) {
 189.510 +                    names.add(name);
 189.511 +                }
 189.512 +            }
 189.513 +            scopeInfo = scopeInfo.up;
 189.514 +            while (scopeInfo != null && scopeInfo.kind == CLASSSCOPE) {
 189.515 +                scopeInfo = scopeInfo.up;
 189.516 +            }
 189.517 +        }
 189.518 +
 189.519 +        return names;
 189.520 +    }
 189.521 +
 189.522 +    public List<ImportEntry> getUnusedImports() {
 189.523 +        List<ImportEntry> unused = new ArrayList<>();
 189.524 +        ScopeInfo scopeInfo = scopes.get(root);
 189.525 +        for (Map.Entry<String, SymInfo> entry : scopeInfo.tbl.entrySet()) {
 189.526 +            SymInfo sym = entry.getValue();
 189.527 +            if (sym.isImported() && !sym.isRead()) {
 189.528 +                String name = entry.getKey();
 189.529 +                if (name.equals("*")) { // NOI18N
 189.530 +                    // Not detecting usages of wildcard imports yet...
 189.531 +                    continue;
 189.532 +                }
 189.533 +                PythonTree node = sym.node;
 189.534 +                if (node instanceof Import) {
 189.535 +                    Import imp = (Import)node;
 189.536 +                    int ordinal = 0;
 189.537 +                    String module = null;
 189.538 +                    String asName = null;
 189.539 +                    List<alias> names = imp.getInternalNames();
 189.540 +                    if (names != null) {
 189.541 +                        for (alias at : names) {
 189.542 +                            if (name.equals(at.getInternalAsname())) {
 189.543 +                                module = at.getInternalName();
 189.544 +                                asName = at.getInternalAsname();
 189.545 +                                break;
 189.546 +                            } else if (name.equals(at.getInternalName())) {
 189.547 +                                module = at.getInternalName();
 189.548 +                                break;
 189.549 +                            }
 189.550 +                        }
 189.551 +                        if (module == null) {
 189.552 +                            // For imports with dotted names, like wsgiref.handlers,
 189.553 +                            // the symbol table entry is just "wsgiref", yet I have to match
 189.554 +                            // the symbols, so try again more carefully
 189.555 +                            for (alias at : names) {
 189.556 +                                if (at.getInternalAsname() != null && at.getInternalAsname().startsWith(name) &&
 189.557 +                                        at.getInternalAsname().charAt(name.length()) == '.') {
 189.558 +                                    module = at.getInternalName();
 189.559 +                                    asName = at.getInternalAsname();
 189.560 +                                    break;
 189.561 +                                } else if (at.getInternalName().startsWith(name) &&
 189.562 +                                        at.getInternalName().charAt(name.length()) == '.') {
 189.563 +                                    module = at.getInternalName();
 189.564 +                                    break;
 189.565 +                                }
 189.566 +                            }
 189.567 +                        }
 189.568 +                    }
 189.569 +                    unused.add(new ImportEntry(module, asName, true, imp, imp.getCharStartIndex() + (ordinal++)));
 189.570 +                } else if (node instanceof ImportFrom) {
 189.571 +                    ImportFrom imp = (ImportFrom)node;
 189.572 +                    if (ImportManager.isFutureImport(imp)) {
 189.573 +                        continue;
 189.574 +                    }
 189.575 +                    String module = imp.getInternalModule();
 189.576 +                    String origName = null;
 189.577 +                    String asName = null;
 189.578 +                    int ordinal = 0;
 189.579 +                    List<alias> names = imp.getInternalNames();
 189.580 +                    if (names != null) {
 189.581 +                        for (alias at : names) {
 189.582 +                            if (name.equals(at.getInternalAsname())) {
 189.583 +                                origName = at.getInternalName();
 189.584 +                                asName = at.getInternalAsname();
 189.585 +                                break;
 189.586 +                            } else if (name.equals(at.getInternalName())) {
 189.587 +                                origName = at.getInternalName();
 189.588 +                                break;
 189.589 +                            }
 189.590 +                        }
 189.591 +                        if (origName == null) {
 189.592 +                            // For imports with dotted names, like wsgiref.handlers,
 189.593 +                            // the symbol table entry is just "wsgiref", yet I have to match
 189.594 +                            // the symbols, so try again more carefully
 189.595 +                            for (alias at : names) {
 189.596 +                                if (at.getInternalAsname() != null && at.getInternalAsname().startsWith(name) &&
 189.597 +                                        at.getInternalAsname().charAt(name.length()) == '.') {
 189.598 +                                    origName = at.getInternalName();
 189.599 +                                    asName = at.getInternalAsname();
 189.600 +                                    break;
 189.601 +                                } else if (at.getInternalName().startsWith(name) &&
 189.602 +                                        at.getInternalName().charAt(name.length()) == '.') {
 189.603 +                                    origName = at.getInternalName();
 189.604 +                                    break;
 189.605 +                                }
 189.606 +                            }
 189.607 +                        }
 189.608 +                    }
 189.609 +                    unused.add(new ImportEntry(module, origName, asName, true, imp, imp.getCharStartIndex() + (ordinal++)));
 189.610 +                }
 189.611 +            }
 189.612 +        }
 189.613 +
 189.614 +        return unused;
 189.615 +    }
 189.616 +
 189.617 +    private class NameNodeFinder extends Visitor {
 189.618 +        private List<PythonTree> nodes = new ArrayList<>();
 189.619 +        private PythonTree startScope;
 189.620 +        private String name;
 189.621 +
 189.622 +        public NameNodeFinder(String name, PythonTree startScope) {
 189.623 +            this.name = name;
 189.624 +            this.startScope = startScope;
 189.625 +        }
 189.626 +
 189.627 +        public void run() {
 189.628 +            try {
 189.629 +                visit(startScope);
 189.630 +            } catch (Exception ex) {
 189.631 +                Exceptions.printStackTrace(ex);
 189.632 +            }
 189.633 +        }
 189.634 +
 189.635 +        @Override
 189.636 +        public Object visitImport(Import imp) throws Exception {
 189.637 +            List<alias> names = imp.getInternalNames();
 189.638 +            if (names != null && names.size() > 0) {
 189.639 +                boolean found = false;
 189.640 +                for (alias at : names) {
 189.641 +                    String asName = at.getInternalAsname();
 189.642 +                    if (asName != null) {
 189.643 +                        if (name.equals(asName)) {
 189.644 +                            found = true;
 189.645 +                            break;
 189.646 +                        }
 189.647 +                    } else if (name.equals(at.getInternalName())) {
 189.648 +                        found = true;
 189.649 +                        break;
 189.650 +                    }
 189.651 +                }
 189.652 +                if (found) {
 189.653 +                    nodes.add(imp);
 189.654 +                }
 189.655 +            }
 189.656 +            return super.visitImport(imp);
 189.657 +        }
 189.658 +
 189.659 +        @Override
 189.660 +        public Object visitImportFrom(ImportFrom imp) throws Exception {
 189.661 +            List<alias> names = imp.getInternalNames();
 189.662 +            if (names != null && names.size() > 0) {
 189.663 +                boolean found = false;
 189.664 +                for (alias at : names) {
 189.665 +                    String asName = at.getInternalAsname();
 189.666 +                    if (asName != null) {
 189.667 +                        if (name.equals(asName)) {
 189.668 +                            found = true;
 189.669 +                            break;
 189.670 +                        }
 189.671 +                    } else if (name.equals(at.getInternalName())) {
 189.672 +                        found = true;
 189.673 +                        break;
 189.674 +                    }
 189.675 +                }
 189.676 +                if (found) {
 189.677 +                    nodes.add(imp);
 189.678 +                }
 189.679 +            }
 189.680 +
 189.681 +            return super.visitImportFrom(imp);
 189.682 +        }
 189.683 +
 189.684 +        @Override
 189.685 +        public Object visitName(Name node) throws Exception {
 189.686 +            if (node.getInternalId().equals(name)) {
 189.687 +                nodes.add(node);
 189.688 +            }
 189.689 +            return super.visitName(node);
 189.690 +        }
 189.691 +
 189.692 +        @Override
 189.693 +        public Object visitFunctionDef(FunctionDef node) throws Exception {
 189.694 +            if (name.equals(node.getInternalName())) {
 189.695 +                nodes.add(node);
 189.696 +            }
 189.697 +
 189.698 +            if (isIncludedScope(node)) {
 189.699 +                return super.visitFunctionDef(node);
 189.700 +            } else {
 189.701 +                return null;
 189.702 +            }
 189.703 +        }
 189.704 +
 189.705 +        @Override
 189.706 +        public Object visitClassDef(ClassDef node) throws Exception {
 189.707 +            if (name.equals(node.getInternalName())) {
 189.708 +                nodes.add(node);
 189.709 +            }
 189.710 +
 189.711 +            if (isIncludedScope(node)) {
 189.712 +                return super.visitClassDef(node);
 189.713 +            } else {
 189.714 +                return null;
 189.715 +            }
 189.716 +        }
 189.717 +
 189.718 +        @Override
 189.719 +        public Object visitExpression(Expression node) throws Exception {
 189.720 +            if (isIncludedScope(node)) {
 189.721 +                return super.visitExpression(node);
 189.722 +            } else {
 189.723 +                return null;
 189.724 +            }
 189.725 +        }
 189.726 +
 189.727 +        @Override
 189.728 +        public Object visitInteractive(Interactive node) throws Exception {
 189.729 +            if (isIncludedScope(node)) {
 189.730 +                return super.visitInteractive(node);
 189.731 +            } else {
 189.732 +                return null;
 189.733 +            }
 189.734 +        }
 189.735 +
 189.736 +        @Override
 189.737 +        public Object visitLambda(Lambda node) throws Exception {
 189.738 +            if (isIncludedScope(node)) {
 189.739 +                return super.visitLambda(node);
 189.740 +            } else {
 189.741 +                return null;
 189.742 +            }
 189.743 +        }
 189.744 +
 189.745 +        @Override
 189.746 +        public Object visitGeneratorExp(GeneratorExp node) throws Exception {
 189.747 +            if (isIncludedScope(node)) {
 189.748 +                return super.visitGeneratorExp(node);
 189.749 +            } else {
 189.750 +                return null;
 189.751 +            }
 189.752 +        }
 189.753 +
 189.754 +        private boolean isIncludedScope(PythonTree node) {
 189.755 +            if (node == startScope) {
 189.756 +                return true;
 189.757 +            }
 189.758 +
 189.759 +            ScopeInfo info = scopes.get(node);
 189.760 +            if (info == null) {
 189.761 +                return false;
 189.762 +            }
 189.763 +
 189.764 +            SymInfo sym = info.tbl.get(name);
 189.765 +            // Skip scopes that redefine the variable
 189.766 +            if (sym != null && sym.isBound()) {
 189.767 +                return false;
 189.768 +            }
 189.769 +
 189.770 +            return true;
 189.771 +        }
 189.772 +
 189.773 +        public List<PythonTree> getNodes() {
 189.774 +            return nodes;
 189.775 +        }
 189.776 +    }
 189.777 +
 189.778 +    public Map<String, SymInfo> getUnresolvedNames(PythonParserResult info) {
 189.779 +        Map<String, SymInfo> unresolved = new HashMap<>();
 189.780 +        Set<String> builtin = getBuiltin(info);
 189.781 +
 189.782 +        for (ScopeInfo scopeInfo : scopes.values()) {
 189.783 +            Map<String, SymInfo> tbl = scopeInfo.tbl;
 189.784 +            for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
 189.785 +                SymInfo symInfo = entry.getValue();
 189.786 +                boolean isUnresolved = symInfo.isUnresolved();
 189.787 +                if (!isUnresolved && symInfo.isFree()) {
 189.788 +                    // Peek up scope stack
 189.789 +                    String name = entry.getKey();
 189.790 +                    SymInfo sym = symInfo;
 189.791 +                    ScopeInfo scope = scopeInfo;
 189.792 +                    while (sym != null && sym.isFree()) {
 189.793 +                        scope = scope.up;
 189.794 +                        while (scope != null && scope.kind == CLASSSCOPE) {
 189.795 +                            scope = scope.up;
 189.796 +                        }
 189.797 +                        sym = scope.tbl.get(name);
 189.798 +                    }
 189.799 +                    if (sym == null) {
 189.800 +                        isUnresolved = true;
 189.801 +                    } else {
 189.802 +                        isUnresolved = sym.isUnresolved();
 189.803 +                    }
 189.804 +                }
 189.805 +                if (isUnresolved) {
 189.806 +                    String key = entry.getKey();
 189.807 +                    if (!builtin.contains(key)) {
 189.808 +                        unresolved.put(key, symInfo);
 189.809 +                    }
 189.810 +                }
 189.811 +            }
 189.812 +        }
 189.813 +
 189.814 +        return unresolved;
 189.815 +    }
 189.816 +
 189.817 +    public List<Attribute> getNotInInitAttributes(PythonParserResult info) {
 189.818 +        List<Attribute> notInInitAttribs = new ArrayList<>();
 189.819 +        for (ScopeInfo scopeInfo : scopes.values()) {
 189.820 +            if (scopeInfo.scope_node instanceof ClassDef) {
 189.821 +                if (scopeInfo.attributes != null) {
 189.822 +                    for (Map.Entry<String, SymInfo> entry : scopeInfo.attributes.entrySet()) {
 189.823 +                        SymInfo symInfo = entry.getValue();
 189.824 +                        if (!symInfo.isBoundInConstructor()) {
 189.825 +                            notInInitAttribs.add((Attribute)symInfo.node);
 189.826 +                        }
 189.827 +                    }
 189.828 +                }
 189.829 +            }
 189.830 +        }
 189.831 +        return notInInitAttribs;
 189.832 +    }
 189.833 +
 189.834 +    private ScopeInfo getClassScope(String className) {
 189.835 +        for (ScopeInfo scopeInfo : scopes.values()) {
 189.836 +            if (scopeInfo.scope_node instanceof ClassDef) {
 189.837 +                ClassDef curClass = (ClassDef)scopeInfo.scope_node;
 189.838 +                if (curClass.getInternalName().equals(className)) {
 189.839 +                    return scopeInfo;
 189.840 +                }
 189.841 +            }
 189.842 +        }
 189.843 +        return null;
 189.844 +    }
 189.845 +
 189.846 +    private int belongsToParents(ClassDef cls, String name, HashMap<String, String> cycling) {
 189.847 +        List<expr> bases = cls.getInternalBases();
 189.848 +        if (bases == null || bases.size() == 0) {
 189.849 +            return NO; // no parents
 189.850 +        }
 189.851 +        for (expr base : bases) {
 189.852 +            String className = null;
 189.853 +            if (base instanceof Name) {
 189.854 +                className = ((Name)base).getInternalId();
 189.855 +            } else {
 189.856 +                // should be Attribute here( module.className form )
 189.857 +                // which imply imported from external scope
 189.858 +                // So we give up on scope returning optimistaically True
 189.859 +                return YES;
 189.860 +            }
 189.861 +            assert (className != null);
 189.862 +            if (cycling.get(className) != null) {
 189.863 +                cycling.clear();
 189.864 +                // put parent child conficting back in cycling
 189.865 +                cycling.put(className, cls.getInternalName());
 189.866 +                return CIRCULAR;
 189.867 +            }
 189.868 +            cycling.put(className, className);
 189.869 +            ScopeInfo localClassScope = getClassScope(className);
 189.870 +            if (localClassScope == null) {
 189.871 +                // return true (success) when at least one parent is outside module scope
 189.872 +                // just to notify caller to be optimistic and assume that
 189.873 +                // name is resolved by imported classes inheritance
 189.874 +                // scanning imported classed from here is discouraged for
 189.875 +                // performances reasons
 189.876 +                return YES;
 189.877 +            } else {
 189.878 +                if ((name != null) &&
 189.879 +                        (localClassScope.attributes.get(name) != null)) {
 189.880 +                    return YES;
 189.881 +                }
 189.882 +                // try recurse parentage to resolve attribute
 189.883 +                ClassDef parentClass = (ClassDef)localClassScope.scope_node;
 189.884 +                int recResult = belongsToParents(parentClass, name, cycling);
 189.885 +                if (recResult != NO) // stop on FOUND(YES) or CIRCULAR error
 189.886 +                {
 189.887 +                    return recResult;
 189.888 +                }
 189.889 +            }
 189.890 +        }
 189.891 +        return NO;
 189.892 +    }
 189.893 +
 189.894 +    private boolean isImported(String moduleName) {
 189.895 +        for (Import imported : imports) {
 189.896 +            List<alias> names = imported.getInternalNames();
 189.897 +            if (names != null) {
 189.898 +                for (alias cur : names) {
 189.899 +                    String name = cur.getInternalName();
 189.900 +                    String asName = cur.getInternalAsname();
 189.901 +                    if (((name != null) && (name.equals(moduleName))) ||
 189.902 +                            ((asName != null) && (asName.equals(moduleName)))) {
 189.903 +                        return true;
 189.904 +                    }
 189.905 +                }
 189.906 +            }
 189.907 +        }
 189.908 +        return false;
 189.909 +    }
 189.910 +
 189.911 +    private boolean isImportedFrom(String className) {
 189.912 +        for (ImportFrom importedFrom : importsFrom) {
 189.913 +            List<alias> names = importedFrom.getInternalNames();
 189.914 +            if (names != null) {
 189.915 +                for (alias cur : names) {
 189.916 +                    String name = cur.getInternalName();
 189.917 +                    String asName = cur.getInternalAsname();
 189.918 +                    if (((name != null) && (name.equals(className))) ||
 189.919 +                            ((asName != null) && (asName.equals(className)))) {
 189.920 +                        return true;
 189.921 +                    }
 189.922 +                }
 189.923 +            }
 189.924 +        }
 189.925 +        return false;
 189.926 +    }
 189.927 +
 189.928 +    public List<PythonTree> getUnresolvedParents(PythonParserResult info) {
 189.929 +        // deal with unresolved parents in inherit trees
 189.930 +        List<PythonTree> unresolvedParents = new ArrayList<>();
 189.931 +        PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
 189.932 +
 189.933 +        for (String cur : classes.keySet()) {
 189.934 +            ClassDef cls = classes.get(cur);
 189.935 +            List<expr> bases = cls.getInternalBases();
 189.936 +            if (bases == null || bases.size() > 0) {
 189.937 +                // has parents
 189.938 +                for (expr base : bases) {
 189.939 +                    if (base instanceof Name) {
 189.940 +                        String className = ((Name)base).getInternalId();
 189.941 +                        Set<String> builtin = getBuiltin(info);
 189.942 +                        if ((!classes.containsKey(className)) &&
 189.943 +                                (!builtin.contains(className))) {
 189.944 +                            // check in from imports
 189.945 +                            if (!isImportedFrom(className)) {
 189.946 +                                unresolvedParents.add(base);
 189.947 +                            }
 189.948 +                        }
 189.949 +                    } else {
 189.950 +                        // should be Attribute here( module.className form )
 189.951 +                        // which imply imported from external scope
 189.952 +                        Attribute attr = (Attribute)base;
 189.953 +                        String clsName = attr.getInternalAttr();
 189.954 +                        if (attr.getInternalValue() instanceof Name) {
 189.955 +                            String moduleName = ((Name)(attr.getInternalValue())).getInternalId();
 189.956 +                            // check that import is resolved first
 189.957 +                            if (!isImported(moduleName)) {
 189.958 +                                unresolvedParents.add(base);
 189.959 +                            } else {
 189.960 +                                Set<IndexedElement> found = index.getImportedElements(clsName, QuerySupport.Kind.EXACT, Collections.<String>singleton(moduleName), null);
 189.961 +                                if (found.size() == 0) {
 189.962 +                                    unresolvedParents.add(base);
 189.963 +                                }
 189.964 +                            }
 189.965 +                        } else {
 189.966 +                            unresolvedParents.add(base);
 189.967 +                        }
 189.968 +                    }
 189.969 +                }
 189.970 +            }
 189.971 +        }
 189.972 +        return unresolvedParents;
 189.973 +    }
 189.974 +
 189.975 +    public HashMap<ClassDef, String> getClassesCyclingRedundancies(PythonParserResult info) {
 189.976 +        HashMap<ClassDef, String> cyclingRedundancies = new HashMap<>();
 189.977 +        for (String cur : classes.keySet()) {
 189.978 +            HashMap<String, String> returned = new HashMap<>();
 189.979 +            ClassDef curClass = classes.get(cur);
 189.980 +            if (!cyclingRedundancies.containsKey(curClass)) {
 189.981 +                if (belongsToParents(curClass, null, returned) == CIRCULAR) {
 189.982 +                    // store hashMap returned
 189.983 +                    Map.Entry<String, String> cycling = returned.entrySet().iterator().next();
 189.984 +                    cyclingRedundancies.put(curClass, cycling.getKey());
 189.985 +                }
 189.986 +            }
 189.987 +        }
 189.988 +        return cyclingRedundancies;
 189.989 +    }
 189.990 +
 189.991 +    public List<PythonTree> getUnresolvedAttributes(PythonParserResult info) {
 189.992 +        List<PythonTree> unresolvedNodes = new ArrayList<>();
 189.993 +        for (ScopeInfo scopeInfo : scopes.values()) {
 189.994 +            Set<String> unresolved = new HashSet<>();
 189.995 +            Map<String, SymInfo> tbl = scopeInfo.tbl;
 189.996 +            // unresolved attributes in local classes
 189.997 +            Map<String, SymInfo> attribs = scopeInfo.attributes;
 189.998 +            for (Map.Entry<String, SymInfo> curAttr : attribs.entrySet()) {
 189.999 +                SymInfo symInfo = curAttr.getValue();
189.1000 +                if (symInfo.isRead()) {
189.1001 +                    // check for builtin attribs first
189.1002 +                    if (classAttributes.get(curAttr.getKey()) == null) {
189.1003 +                        // not a builtin attribute
189.1004 +                        ScopeInfo parentScope = scopeInfo.getClassScope();
189.1005 +                        if (parentScope != null) {
189.1006 +                            // limit scope to Classes for self and inherited
189.1007 +                            Map<String, SymInfo> parentattribs = parentScope.attributes;
189.1008 +                            SymInfo classAttr = parentattribs.get(curAttr.getKey());
189.1009 +                            tbl = parentScope.tbl;
189.1010 +                            if (classAttr == null) {
189.1011 +                                // may be  also a reference to a method
189.1012 +                                classAttr = tbl.get(curAttr.getKey());
189.1013 +                            }
189.1014 +                            if (classAttr == null) {
189.1015 +                                // do not bother with method since they are
189.1016 +                                // managed by completion
189.1017 +                                ClassDef curClass = (ClassDef)parentScope.scope_node;
189.1018 +                                if (belongsToParents(curClass, curAttr.getKey(), new HashMap()) == NO) {
189.1019 +                                    if (!symInfo.isCalled()) {
189.1020 +                                        // no corresponding attributes
189.1021 +                                        //PythonTree tree = symInfo.node ;
189.1022 +                                        Attribute attr = (Attribute)symInfo.node;
189.1023 +                                        // Name name = new Name(tree.getToken(),attr.getInternalAttr(),attr.ctx) ;
189.1024 +                                        unresolvedNodes.add(attr);
189.1025 +                                    }
189.1026 +                                }
189.1027 +                            }
189.1028 +                        }
189.1029 +                    }
189.1030 +                }
189.1031 +            }
189.1032 +            if (unresolved.size() > 0) {
189.1033 +                NameFinder finder = new NameFinder(unresolved);
189.1034 +                List<Name> nodes = finder.run(scopeInfo.scope_node);
189.1035 +                unresolvedNodes.addAll(nodes);
189.1036 +            }
189.1037 +
189.1038 +        }
189.1039 +
189.1040 +        if (unresolvedNodes.size() > 1) {
189.1041 +            Collections.sort(unresolvedNodes, PythonUtils.ATTRIBUTE_NAME_NODE_COMPARATOR);
189.1042 +            //Collections.sort(unusedNodes, PythonUtils.NODE_POS_COMPARATOR);
189.1043 +        }
189.1044 +
189.1045 +        return unresolvedNodes;
189.1046 +    }
189.1047 +
189.1048 +    public List<PythonTree> getUnresolved(PythonParserResult info) {
189.1049 +        List<PythonTree> unresolvedNodes = new ArrayList<>();
189.1050 +        Set<String> builtin = getBuiltin(info);
189.1051 +
189.1052 +        for (ScopeInfo scopeInfo : scopes.values()) {
189.1053 +            Set<String> unresolved = new HashSet<>();
189.1054 +            Map<String, SymInfo> tbl = scopeInfo.tbl;
189.1055 +            for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
189.1056 +                SymInfo symInfo = entry.getValue();
189.1057 +                boolean isUnresolved = symInfo.isUnresolved();
189.1058 +                if (!isUnresolved && symInfo.isFree()) {
189.1059 +                    // Peek up scope stack
189.1060 +                    String name = entry.getKey();
189.1061 +                    SymInfo sym = symInfo;
189.1062 +                    ScopeInfo scope = scopeInfo;
189.1063 +                    while (sym != null && sym.isFree()) {
189.1064 +                        scope = scope.up;
189.1065 +                        while (scope != null && scope.kind == CLASSSCOPE) {
189.1066 +                            scope = scope.up;
189.1067 +                        }
189.1068 +                        sym = scope.tbl.get(name);
189.1069 +                    }
189.1070 +                    if (sym == null) {
189.1071 +                        isUnresolved = true;
189.1072 +                    } else {
189.1073 +                        isUnresolved = sym.isUnresolved();
189.1074 +                    }
189.1075 +                }
189.1076 +                if (isUnresolved) {
189.1077 +                    String key = entry.getKey();
189.1078 +                    if (!builtin.contains(key)) {
189.1079 +                        unresolved.add(key);
189.1080 +                    }
189.1081 +                }
189.1082 +            }
189.1083 +
189.1084 +
189.1085 +            if (unresolved.size() > 0) {
189.1086 +                // Check imports and see if it's resolved by existing imports
189.1087 +                PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
189.1088 +                // TODO - cache system libraries!
189.1089 +                // TODO - make method which doesn't create elements for these guys!
189.1090 +//                Set<IndexedElement> elements = index.getImportedElements("", NameKind.PREFIX, PythonIndex.ALL_SCOPE, imports, importsFrom);
189.1091 +//                for (IndexedElement e : elements) {
189.1092 +//                    unresolved.remove(e.getName());
189.1093 +//                }
189.1094 +                Set<String> wildcarded = index.getImportedFromWildcards(importsFrom);
189.1095 +                unresolved.removeAll(wildcarded);
189.1096 +
189.1097 +                if (unresolved.size() > 0) {
189.1098 +                    NameFinder finder = new NameFinder(unresolved);
189.1099 +                    List<Name> nodes = finder.run(scopeInfo.scope_node);
189.1100 +                    unresolvedNodes.addAll(nodes);
189.1101 +                }
189.1102 +            }
189.1103 +        }
189.1104 +
189.1105 +        if (unresolvedNodes.size() > 1) {
189.1106 +            Collections.sort(unresolvedNodes, PythonUtils.ATTRIBUTE_NAME_NODE_COMPARATOR);
189.1107 +            //Collections.sort(unusedNodes, PythonUtils.NODE_POS_COMPARATOR);
189.1108 +        }
189.1109 +
189.1110 +        return unresolvedNodes;
189.1111 +    }
189.1112 +
189.1113 +    public List<PythonTree> getUnused(boolean skipSelf, boolean skipParams) { // not used for unused imports, see separate method
189.1114 +        List<PythonTree> unusedNodes = new ArrayList<>();
189.1115 +
189.1116 +        for (ScopeInfo scopeInfo : scopes.values()) {
189.1117 +            if (scopeInfo.kind != FUNCSCOPE && scopeInfo.kind != TOPSCOPE && scopeInfo.kind != CLASSSCOPE) {
189.1118 +                continue;
189.1119 +            }
189.1120 +            Set<String> unused = new HashSet<>();
189.1121 +            Map<String, SymInfo> tbl = scopeInfo.tbl;
189.1122 +            for (Map.Entry<String, SymInfo> entry : tbl.entrySet()) {
189.1123 +                SymInfo symInfo = entry.getValue();
189.1124 +                if (symInfo.isUnused(scopeInfo) && (!skipParams || !symInfo.isParameter())) {
189.1125 +                    String key = entry.getKey();
189.1126 +                    if (skipSelf && "self".equals(key)) { // NOI18N
189.1127 +                        continue;
189.1128 +                    }
189.1129 +                    unused.add(key);
189.1130 +                }
189.1131 +            }
189.1132 +
189.1133 +            if (unused.size() > 0) {
189.1134 +                NameFinder finder = new NameFinder(unused);
189.1135 +                List<Name> nodes = finder.run(scopeInfo.scope_node);
189.1136 +                unusedNodes.addAll(nodes);
189.1137 +            }
189.1138 +        }
189.1139 +
189.1140 +        if (unusedNodes.size() > 1) {
189.1141 +            Collections.sort(unusedNodes, PythonUtils.NAME_NODE_COMPARATOR);
189.1142 +            //Collections.sort(unusedNodes, PythonUtils.NODE_POS_COMPARATOR);
189.1143 +        }
189.1144 +
189.1145 +        return unusedNodes;
189.1146 +    }
189.1147 +
189.1148 +    private static class NameFinder extends Visitor {
189.1149 +        private Set<String> names;
189.1150 +        private List<Name> nodes = new ArrayList<>();
189.1151 +        private PythonTree acceptDef;
189.1152 +
189.1153 +        private NameFinder(Set<String> names) {
189.1154 +            this.names = names;
189.1155 +        }
189.1156 +
189.1157 +        @Override
189.1158 +        public Object visitClassDef(ClassDef node) throws Exception {
189.1159 +            // Don't look in nested scopes
189.1160 +            if (node != acceptDef) {
189.1161 +                return null;
189.1162 +            }
189.1163 +            return super.visitClassDef(node);
189.1164 +        }
189.1165 +
189.1166 +        @Override
189.1167 +        public Object visitFunctionDef(FunctionDef node) throws Exception {
189.1168 +            // Don't look in nested scopes
189.1169 +            if (node != acceptDef) {
189.1170 +                return null;
189.1171 +            }
189.1172 +            return super.visitFunctionDef(node);
189.1173 +        }
189.1174 +
189.1175 +        @Override
189.1176 +        public Object visitName(Name node) throws Exception {
189.1177 +            String name = node.getInternalId();
189.1178 +            if (names.contains(name)) {
189.1179 +                nodes.add(node);
189.1180 +            }
189.1181 +
189.1182 +            return super.visitName(node);
189.1183 +        }
189.1184 +
189.1185 +        public List<Name> run(PythonTree node) {
189.1186 +            this.acceptDef = node;
189.1187 +            try {
189.1188 +                visit(node);
189.1189 +            } catch (Exception ex) {
189.1190 +                Exceptions.printStackTrace(ex);
189.1191 +            }
189.1192 +
189.1193 +            return nodes;
189.1194 +        }
189.1195 +    }
189.1196 +    private static Set<String> builtinSymbols;
189.1197 +
189.1198 +    private Set<String> getBuiltin(PythonParserResult info) {
189.1199 +        if (builtinSymbols == null) {
189.1200 +            PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
189.1201 +            builtinSymbols = index.getBuiltinSymbols();
189.1202 +        }
189.1203 +
189.1204 +        return builtinSymbols;
189.1205 +    }
189.1206 +
189.1207 +    public void error(String msg, boolean err, PythonTree node) throws Exception {
189.1208 +        assert node != null;
189.1209 +        // TODO - record and register with the hints manager?
189.1210 +        OffsetRange range = PythonAstUtils.getRange(node);
189.1211 +
189.1212 +        if (errors == null) {
189.1213 +            errors = new ArrayList<>();
189.1214 +        }
189.1215 +        Error error = new DefaultError(null, msg, null, fileObject, range.getStart(), range.getEnd(), err ? Severity.ERROR : Severity.WARNING);
189.1216 +        errors.add(error);
189.1217 +    }
189.1218 +
189.1219 +    public String getFilename() {
189.1220 +        return FileUtil.getFileDisplayName(fileObject);
189.1221 +    }
189.1222 +
189.1223 +    public Map<PythonTree, ScopeInfo> getScopes() {
189.1224 +        return scopes;
189.1225 +    }
189.1226 +
189.1227 +    public List<Import> getImports() {
189.1228 +        return imports;
189.1229 +    }
189.1230 +
189.1231 +    public List<ImportFrom> getImportsFrom() {
189.1232 +        return importsFrom;
189.1233 +    }
189.1234 +
189.1235 +    public boolean isTopLevel(PythonTree node) {
189.1236 +        return topLevelImports.contains(node);
189.1237 +    }
189.1238 +
189.1239 +    public List<PythonTree> getMainImports() {
189.1240 +        return mainImports;
189.1241 +    }
189.1242 +
189.1243 +    public Set<PythonTree> getTopLevelImports() {
189.1244 +        return topLevelImports;
189.1245 +    }
189.1246 +
189.1247 +    public List<Str> getPublicSymbols() {
189.1248 +        return publicSymbols;
189.1249 +    }
189.1250 +}
   190.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   190.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/Bundle.properties	Mon Sep 21 13:01:16 2015 +0200
   190.3 @@ -0,0 +1,284 @@
   190.4 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   190.5 +#
   190.6 +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   190.7 +#
   190.8 +# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   190.9 +# Other names may be trademarks of their respective owners.
  190.10 +#
  190.11 +# The contents of this file are subject to the terms of either the GNU
  190.12 +# General Public License Version 2 only ("GPL") or the Common
  190.13 +# Development and Distribution License("CDDL") (collectively, the
  190.14 +# "License"). You may not use this file except in compliance with the
  190.15 +# License. You can obtain a copy of the License at
  190.16 +# http://www.netbeans.org/cddl-gplv2.html
  190.17 +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  190.18 +# specific language governing permissions and limitations under the
  190.19 +# License.  When distributing the software, include this License Header
  190.20 +# Notice in each file and include the License file at
  190.21 +# nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  190.22 +# particular file as subject to the "Classpath" exception as provided
  190.23 +# by Oracle in the GPL Version 2 section of the License file that
  190.24 +# accompanied this code. If applicable, add the following below the
  190.25 +# License Header, with the fields enclosed by brackets [] replaced by
  190.26 +# your own identifying information:
  190.27 +# "Portions Copyrighted [year] [name of copyright owner]"
  190.28 +#
  190.29 +# Contributor(s):
  190.30 +#
  190.31 +# The Original Software is NetBeans. The Initial Developer of the Original
  190.32 +# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  190.33 +# Microsystems, Inc. All Rights Reserved.
  190.34 +#
  190.35 +# If you wish your version of this file to be governed by only the CDDL
  190.36 +# or only the GPL Version 2, indicate your decision by adding
  190.37 +# "[Contributor] elects to include this software in this distribution
  190.38 +# under the [CDDL or GPL Version 2] license." If you do not indicate a
  190.39 +# single choice of license, a recipient has the option to distribute
  190.40 +# your version of this file under either the CDDL, the GPL Version 2 or
  190.41 +# to extend the choice of license to its licensees as provided above.
  190.42 +# However, if you add GPL Version 2 code and therefore, elected the GPL
  190.43 +# Version 2 license, then the option applies only if the new code is
  190.44 +# made subject to such option by the copyright holder.
  190.45 +
  190.46 +# Formating options
  190.47 +
  190.48 +LBL_TabsAndIndents=Tabs and Indents
  190.49 +LBL_CodeGeneration=Code Generation
  190.50 +LBL_Alignment=Alignment
  190.51 +LBL_Wrapping=Wrapping
  190.52 +LBL_BlankLines=Blank Lines
  190.53 +LBL_Spaces=Spaces
  190.54 +LBL_Imports=Imports
  190.55 +
  190.56 +LBL_bp_SAME_LINE=Same Line
  190.57 +LBL_bp_NEW_LINE=New Line
  190.58 +LBL_bp_NEW_LINE_HALF_INDENTED=New Line Half Indented
  190.59 +LBL_bp_NEW_LINE_INDENTED= New Line Indented
  190.60 +    
  190.61 +LBL_bg_GENERATE=Generate
  190.62 +LBL_bg_LEAVE_ALONE=Leave Alone
  190.63 +LBL_bg_ELIMINATE=Eliminate
  190.64 +       
  190.65 +LBL_wrp_WRAP_ALWAYS=Always
  190.66 +LBL_wrp_WRAP_IF_LONG=If Long
  190.67 +LBL_wrp_WRAP_NEVER=Never
  190.68 +
  190.69 +LBL_imp_COMMENT_OUT=Comment Out
  190.70 +LBL_imp_LEAVE_ALONE=Leave Alone
  190.71 +LBL_imp_DELETE=Delete
  190.72 +
  190.73 +LBL_ExpandTabToSpaces=&Expand Tab to Spaces
  190.74 +LBL_TabSize=&Tab Size:
  190.75 +LBL_IndentSize=&Indentation Size:
  190.76 +LBL_ContinuationIndentSize=&Continuation Indentation Size:
  190.77 +LBL_LabelIndent=&Label Indentation\:
  190.78 +LBL_AbsoluteLabelIndent=&Absolute Label Indentation
  190.79 +LBL_IndentTopLevelClassMemberts=Indent Top Level Class &Members
  190.80 +LBL_AddLeadingStarInComment=Add Leading Star In Comment
  190.81 +LBL_RightMargin=&Right Margin:
  190.82 +
  190.83 +LBL_Naming=Naming\:
  190.84 +LBL_PreferLongerNames=Prefer Longer Names
  190.85 +LBL_Prefix=Prefix
  190.86 +LBL_Suffix=Suffix
  190.87 +LBL_Field=Field\:
  190.88 +LBL_StaticField=Static Field\:
  190.89 +LBL_Parameter=Parameter\:
  190.90 +LBL_LocalVariable=Local Variable\:
  190.91 +LBL_Misc=Misc\:
  190.92 +LBL_QualifyFieldAccess=Qualify Field Access
  190.93 +LBL_UseIsForBooleanGetters=Use Is For Boolean Getters
  190.94 +LBL_AddOverrideAnnotation=Add Override Annotation
  190.95 +LBL_FinalMofier=Final Modifier\:
  190.96 +LBL_ParametersFinal=Make Generated Parameters Final
  190.97 +LBL_LocalVariablesFinal=Make Generated Local variables Final
  190.98 +LBL_ImportOredering=Import Ordering\:
  190.99 +LBL_ImportUp=Move Up
 190.100 +LBL_ImportDown=Move Down
 190.101 +LBL_blBeforePackage=Before &Package\:
 190.102 +LBL_blAfterPackage=After P&ackage\:
 190.103 +LBL_blBeforeImports=Before &Imports\:
 190.104 +LBL_blAfterImports=After I&mports\:
 190.105 +LBL_blBeforeClass=Before &Class\:
 190.106 +LBL_blAfterClass=After C&lass\:
 190.107 +LBL_blAfterClassHeader=After Class &Header\:
 190.108 +LBL_blBeforeFields=Before &Field\:
 190.109 +LBL_blAfterFields=After Fi&eld\:
 190.110 +LBL_blBeforeMethods=Before &Method\:
 190.111 +LBL_blAfterMethods=After Me&thod\:
 190.112 +
 190.113 +LBL_BeforeKeywords=Before Keywords
 190.114 +LBL_spaceBeforeWhile="while"
 190.115 +LBL_spaceBeforeElse="else"
 190.116 +LBL_spaceBeforeCatch="catch"
 190.117 +LBL_spaceBeforeFinally="finally"
 190.118 +
 190.119 +LBL_BeforeParentheses=Before Parentheses
 190.120 +LBL_spaceBeforeMethodDeclParen=Method Declaration
 190.121 +LBL_spaceBeforeMethodCallParen=Method Call
 190.122 +LBL_spaceBeforeIfParen="if"
 190.123 +LBL_spaceBeforeForParen="for"
 190.124 +LBL_spaceBeforeWhileParen="while"
 190.125 +LBL_spaceBeforeCatchParen="catch"
 190.126 +LBL_spaceBeforeSwitchParen="switch"
 190.127 +LBL_spaceBeforeSynchronizedParen="synchronized"
 190.128 +LBL_spaceBeforeAnnotationParen=Annotation Parameters
 190.129 +
 190.130 +LBL_AroundOperators=Around Operators
 190.131 +LBL_spaceAroundUnaryOps=Unary Operators
 190.132 +LBL_spaceAroundBinaryOps=Binary Operators
 190.133 +LBL_spaceAroundTernaryOps=Ternary Operators
 190.134 +LBL_spaceAroundAssignOps=Assignment Operators
 190.135 +
 190.136 +LBL_BeforeLeftBraces=Before Left Braces
 190.137 +LBL_spaceBeforeClassDeclLeftBrace=Class Declaration
 190.138 +LBL_spaceBeforeMethodDeclLeftBrace=Method Declaration
 190.139 +LBL_spaceBeforeIfLeftBrace="if"
 190.140 +LBL_spaceBeforeElseLeftBrace="else"
 190.141 +LBL_spaceBeforeWhileLeftBrace="while"
 190.142 +LBL_spaceBeforeForLeftBrace="for"
 190.143 +LBL_spaceBeforeDoLeftBrace="do"
 190.144 +LBL_spaceBeforeSwitchLeftBrace="switch"
 190.145 +LBL_spaceBeforeTryLeftBrace="try"
 190.146 +LBL_spaceBeforeCatchLeftBrace="catch"
 190.147 +LBL_spaceBeforeFinallyLeftBrace="finally"
 190.148 +LBL_spaceBeforeSynchronizedLeftBrace="synchronized"
 190.149 +LBL_spaceBeforeStaticInitLeftBrace=Static Initializer
 190.150 +LBL_spaceBeforeArrayInitLeftBrace=Array Initializer
 190.151 +
 190.152 +LBL_WithinParentheses=Within Parentheses
 190.153 +LBL_spaceWithinParens=Parentheses
 190.154 +LBL_spaceWithinMethodDeclParens=Method Declaration
 190.155 +LBL_spaceWithinMethodCallParens=Method Call
 190.156 +LBL_spaceWithinIfParens="if"
 190.157 +LBL_spaceWithinForParens="for"
 190.158 +LBL_spaceWithinWhileParens="while"
 190.159 +LBL_spaceWithinSwitchParens="switch"
 190.160 +LBL_spaceWithinCatchParens="catch"
 190.161 +LBL_spaceWithinSynchronizedParens="synchronized"
 190.162 +LBL_spaceWithinTypeCastParens=Type Cast
 190.163 +LBL_spaceWithinAnnotationParens=Annotation
 190.164 +LBL_spaceWithinBraces=Braces
 190.165 +LBL_spaceWithinArrayInitBrackets=Array Initializer Brackets
 190.166 +
 190.167 +LBL_Other=Other
 190.168 +LBL_spaceBeforeComma=Before Comma
 190.169 +LBL_spaceAfterComma=After Comma
 190.170 +LBL_spaceBeforeSemi=Before Semicolon
 190.171 +LBL_spaceAfterSemi=After Semicolon
 190.172 +LBL_spaceBeforeColon=Before Colon
 190.173 +LBL_spaceAfterColon=After Colon
 190.174 +LBL_spaceAfterTypeCast=After Type Cast
 190.175 +LBL_wrp_extendsImplementsKeyword=&Extends/Implements Keyword\: 
 190.176 +LBL_wrp_extendsImplementsList=E&xtends/Implements List\:
 190.177 +LBL_wrp_methodParameters=Method &Parameters\:
 190.178 +LBL_wrp_throwsKeyword=&Throws Keyword\:
 190.179 +LBL_wrp_throwsList=Th&rows List\:
 190.180 +LBL_wrp_methodCallArgs=Method Call &Arguments\:
 190.181 +LBL_wrp_annotationArgs=Annotation Arg&uments\:
 190.182 +LBL_wrp_chainedMethodCalls=C&hained Method Calls\:
 190.183 +LBL_wrp_arrayInit=Array Initiali&zer\:
 190.184 +LBL_wrp_for=&For\:
 190.185 +LBL_wrp_forStatement=F&or Statement\:
 190.186 +LBL_wrp_ifStatement=&If Statement\:
 190.187 +LBL_wrp_whileStatement=&While Statement\:
 190.188 +LBL_wrp_doWhileStatement=&Do ... While Statement
 190.189 +LBL_wrp_assert=&Assert\:
 190.190 +LBL_wrp_enumConstants=Enum &Constants\:
 190.191 +LBL_wrp_annotations=A&nnotations\:
 190.192 +LBL_wrp_binaryOps=&Binary Operators\:
 190.193 +LBL_wrp_ternaryOps=Ternar&y Operators\:
 190.194 +LBL_wrp_assignOps=Assi&gnment Operators\:
 190.195 +
 190.196 +LBL_br_bracesPlacement=Braces Placement
 190.197 +LBL_br_bracesGeneration=Braces Generation
 190.198 +LBL_al_newLines=New Lines
 190.199 +LBL_al_multilineAlignment=Multiline Alignment
 190.200 +LBL_nl_Else="&else"
 190.201 +LBL_nl_While="w&hile"
 190.202 +LBL_nl_Catch="c&atch"
 190.203 +LBL_nl_Finally="finall&y"
 190.204 +LBL_nl_Modifiers=after modifie&rs
 190.205 +LBL_am_MethodParams=Method &Parameters
 190.206 +LBL_am_CallArgs=Method Call Arg&uments
 190.207 +LBL_am_AnnotationArgs=&Annotation Arguments
 190.208 +LBL_an_Implements=I&mplements List
 190.209 +LBL_am_Throws=&Throws List
 190.210 +LBL_am_Paren=Parenthesize&d
 190.211 +LBL_am_BinaryOp=&Binary Operators
 190.212 +LBL_am_TernaryOp=Ter&nary Operators
 190.213 +LBL_am_Assign=Assi&gnment
 190.214 +LBL_am_For=&For
 190.215 +LBL_am_ArrayInit=Array Initiali&zer
 190.216 +
 190.217 +LBL_IndentCasesFromSwitch=Indent Case Statements In &Switch
 190.218 +
 190.219 +# Following entries (marked) as samples are used as examples in the formating
 190.220 +# options. It is highly discourage to localize them unless absolutely necessary.
 190.221 +
 190.222 +SAMPLE_Default=public class ClassA extends Object implements InterfaceA, InterfaceB, InterfaceC
 190.223 +SAMPLE_TabsIndents=public class ClassA extends Object implements InterfaceA, InterfaceB, InterfaceC {
 190.224 +SAMPLE_AlignBraces=@Anno(paramA="a Value", paramB="bValue")\n
 190.225 +SAMPLE_Wrapping=@Anno(paramA="a Value", paramB="bValue")
 190.226 +SAMPLE_BlankLines=package org.netbeans.samples;
 190.227 +
 190.228 +SAMPLE_Imports=\
 190.229 +# Copyright 2008\n\
 190.230 +"""My Module"""\n\
 190.231 +\n\
 190.232 +import sys\n\
 190.233 +import wsgiref.handlers\n\
 190.234 +from google.appengine.ext.webapp.util import run_wsgi_app\n\
 190.235 +from google.appengine.ext import webapp\n\
 190.236 +from google.appengine.ext import db\n\
 190.237 +import os\n\
 190.238 +\n\
 190.239 +\n\
 190.240 +from google.appengine.api import users\n\
 190.241 +import google.appengine.api.test\n\
 190.242 +from google.appengine.api import users\n\
 190.243 +\n\
 190.244 +from google.appengine.api import users\n\
 190.245 +from google.appengine.api import users\n\
 190.246 +import string\n\
 190.247 +from google.appengine.ext.webapp import template as FooBar\n\
 190.248 +from google.appengine.ext.webapp.util import login_required\n\
 190.249 +import random\n\
 190.250 +import datetime\n
 190.251 +
 190.252 +#\n\
 190.253 +#new_str = swapcase("foo")
 190.254 +
 190.255 +
 190.256 +# Newlines on the following line since space prefixes are ignored by the .properties loader
 190.257 +SAMPLE_Spaces=\
 190.258 +def func( arg1 ,arg2 ,\
 190.259 +\n  arg3 = 3,  arg  =  4):\
 190.260 +\n\
 190.261 +\n  if pos!=-1 and optval[ pos-1 ].isspace():\
 190.262 +\n      x=5+2\
 190.263 +\n\
 190.264 +\nmodeDict = { 'r':'rb','w':'wb', \\\
 190.265 +\n   'a' : 'r+b' }\
 190.266 +\nx = 2; y=3 ; z    =      5\n
 190.267 +
 190.268 +
 190.269 +nlFinallyCheckBox1.text="finall&y"
 190.270 +
 190.271 +
 190.272 +AN_Preview=Preview
 190.273 +AD_Preview=Preview
 190.274 +FmtImports.formatImportsCb.text=Organize Imports during formatting
 190.275 +FmtImports.removeDuplicateCb.text=Remove Duplicate Imports
 190.276 +FmtImports.systemLibsCb.text=Separate out system libraries
 190.277 +FmtImports.onePerLineCb.text=Prefer one import per line
 190.278 +FmtImports.cleanupLabel.text=Unused imports:
 190.279 +FmtImports.preferSymbols.text=Prefer symbol imports
 190.280 +FmtImports.sortImportsCb.text=Sort Alphabetically
 190.281 +FmtSpaces.addAroundOp.text=Add spaces around operators
 190.282 +FmtSpaces.removeInParam.text=But remove in parameter assignments
 190.283 +FmtSpaces.removeInParen.text=Remove spaces inside ( ), { }, and [ ]
 190.284 +FmtSpaces.addAfterComma.text=Add spaces after commas
 190.285 +FmtSpaces.removeBeforeSep.text=Remove spaces before separators ( : , ; )
 190.286 +FmtSpaces.collapseSpacesCb.text=Collapse multiple spaces
 190.287 +FmtImports.sepFromImpCb.text=Separate "from" and "import" statements
   191.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   191.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtAlignment.form	Mon Sep 21 13:01:16 2015 +0200
   191.3 @@ -0,0 +1,350 @@
   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_Alignment" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  191.10 +    </Property>
  191.11 +    <Property name="opaque" type="boolean" value="false"/>
  191.12 +  </Properties>
  191.13 +  <AuxValues>
  191.14 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
  191.15 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  191.16 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  191.17 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
  191.18 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  191.19 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
  191.20 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
  191.21 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  191.22 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  191.23 +  </AuxValues>
  191.24 +
  191.25 +  <Layout>
  191.26 +    <DimensionLayout dim="0">
  191.27 +      <Group type="103" groupAlignment="0" attributes="0">
  191.28 +          <Group type="102" attributes="0">
  191.29 +              <Group type="103" groupAlignment="0" attributes="0">
  191.30 +                  <Group type="102" alignment="0" attributes="0">
  191.31 +                      <EmptySpace min="-2" max="-2" attributes="0"/>
  191.32 +                      <Component id="amParenthesizedCheckBox1" min="-2" max="-2" attributes="0"/>
  191.33 +                  </Group>
  191.34 +                  <Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
  191.35 +                      <Group type="102" alignment="0" attributes="1">
  191.36 +                          <Component id="newLinesLabel" min="-2" max="-2" attributes="0"/>
  191.37 +                          <EmptySpace max="-2" attributes="0"/>
  191.38 +                          <Component id="jSeparator1" max="32767" attributes="0"/>
  191.39 +                      </Group>
  191.40 +                      <Group type="102" alignment="0" attributes="1">
  191.41 +                          <Component id="multilineAlignmentLabel" min="-2" max="-2" attributes="0"/>
  191.42 +                          <EmptySpace max="-2" attributes="0"/>
  191.43 +                          <Component id="jSeparator2" max="32767" attributes="1"/>
  191.44 +                      </Group>
  191.45 +                      <Group type="102" alignment="0" attributes="0">
  191.46 +                          <EmptySpace max="-2" attributes="0"/>
  191.47 +                          <Group type="103" groupAlignment="0" attributes="0">
  191.48 +                              <Component id="amThrowsCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/>
  191.49 +                              <Component id="amBinaryOpCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/>
  191.50 +                              <Component id="amAssignCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/>
  191.51 +                              <Component id="amAnnotationArgsCheckBox" alignment="0" min="-2" max="-2" attributes="1"/>
  191.52 +                              <Component id="nlElseCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
  191.53 +                              <Component id="nlWhileCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
  191.54 +                              <Component id="nlCatchCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
  191.55 +                              <Component id="amMethodParamsCheckBox" alignment="0" min="-2" max="-2" attributes="1"/>
  191.56 +                          </Group>
  191.57 +                          <EmptySpace min="-2" max="-2" attributes="0"/>
  191.58 +                          <Group type="103" groupAlignment="0" attributes="0">
  191.59 +                              <Component id="amCallArgsCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
  191.60 +                              <Component id="nlModifiersCheckBox" min="-2" max="-2" attributes="0"/>
  191.61 +                              <Component id="nlFinallyCheckBox" min="-2" max="-2" attributes="0"/>
  191.62 +                              <Component id="amImplementsCheckBox1" min="-2" max="-2" attributes="0"/>
  191.63 +                              <Component id="amArrayInitCheckBox1" min="-2" max="-2" attributes="0"/>
  191.64 +                              <Component id="amTernaryOpCheckBox1" min="-2" max="-2" attributes="0"/>
  191.65 +                              <Component id="amForCheckBox1" min="-2" max="-2" attributes="0"/>
  191.66 +                          </Group>
  191.67 +                      </Group>
  191.68 +                  </Group>
  191.69 +              </Group>
  191.70 +              <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
  191.71 +          </Group>
  191.72 +      </Group>
  191.73 +    </DimensionLayout>
  191.74 +    <DimensionLayout dim="1">
  191.75 +      <Group type="103" groupAlignment="0" attributes="0">
  191.76 +          <Group type="102" alignment="0" attributes="0">
  191.77 +              <Group type="103" groupAlignment="0" attributes="0">
  191.78 +                  <Group type="102" attributes="0">
  191.79 +                      <EmptySpace max="-2" attributes="0"/>
  191.80 +                      <Component id="newLinesLabel" min="-2" max="-2" attributes="1"/>
  191.81 +                  </Group>
  191.82 +                  <Group type="102" attributes="0">
  191.83 +                      <EmptySpace min="-2" pref="17" max="-2" attributes="0"/>
  191.84 +                      <Component id="jSeparator1" min="-2" pref="10" max="-2" attributes="0"/>
  191.85 +                  </Group>
  191.86 +              </Group>
  191.87 +              <EmptySpace max="-2" attributes="0"/>
  191.88 +              <Group type="103" groupAlignment="3" attributes="0">
  191.89 +                  <Component id="nlElseCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
  191.90 +                  <Component id="nlFinallyCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
  191.91 +              </Group>
  191.92 +              <EmptySpace max="-2" attributes="0"/>
  191.93 +              <Group type="103" groupAlignment="3" attributes="0">
  191.94 +                  <Component id="nlWhileCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
  191.95 +                  <Component id="nlModifiersCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
  191.96 +              </Group>
  191.97 +              <Group type="103" groupAlignment="0" attributes="0">
  191.98 +                  <Group type="102" attributes="0">
  191.99 +                      <EmptySpace max="-2" attributes="0"/>
 191.100 +                      <Component id="nlCatchCheckBox" min="-2" max="-2" attributes="0"/>
 191.101 +                      <EmptySpace type="separate" max="-2" attributes="0"/>
 191.102 +                      <Component id="multilineAlignmentLabel" min="-2" max="-2" attributes="0"/>
 191.103 +                  </Group>
 191.104 +                  <Group type="102" attributes="0">
 191.105 +                      <EmptySpace min="-2" pref="44" max="-2" attributes="0"/>
 191.106 +                      <Component id="jSeparator2" min="-2" pref="10" max="-2" attributes="0"/>
 191.107 +                  </Group>
 191.108 +              </Group>
 191.109 +              <EmptySpace min="-2" max="-2" attributes="0"/>
 191.110 +              <Group type="103" groupAlignment="3" attributes="0">
 191.111 +                  <Component id="amMethodParamsCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
 191.112 +                  <Component id="amCallArgsCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
 191.113 +              </Group>
 191.114 +              <EmptySpace min="-2" max="-2" attributes="0"/>
 191.115 +              <Group type="103" groupAlignment="3" attributes="0">
 191.116 +                  <Component id="amAnnotationArgsCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
 191.117 +                  <Component id="amImplementsCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
 191.118 +              </Group>
 191.119 +              <EmptySpace max="-2" attributes="0"/>
 191.120 +              <Group type="103" groupAlignment="3" attributes="0">
 191.121 +                  <Component id="amThrowsCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
 191.122 +                  <Component id="amArrayInitCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
 191.123 +              </Group>
 191.124 +              <EmptySpace max="-2" attributes="0"/>
 191.125 +              <Group type="103" groupAlignment="3" attributes="0">
 191.126 +                  <Component id="amBinaryOpCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
 191.127 +                  <Component id="amTernaryOpCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
 191.128 +              </Group>
 191.129 +              <EmptySpace max="-2" attributes="0"/>
 191.130 +              <Group type="103" groupAlignment="3" attributes="0">
 191.131 +                  <Component id="amAssignCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
 191.132 +                  <Component id="amForCheckBox1" alignment="3" min="-2" max="-2" attributes="0"/>
 191.133 +              </Group>
 191.134 +              <EmptySpace min="-2" max="-2" attributes="0"/>
 191.135 +              <Component id="amParenthesizedCheckBox1" min="-2" max="-2" attributes="0"/>
 191.136 +              <EmptySpace max="32767" attributes="0"/>
 191.137 +          </Group>
 191.138 +      </Group>
 191.139 +    </DimensionLayout>
 191.140 +  </Layout>
 191.141 +  <SubComponents>
 191.142 +    <Component class="javax.swing.JLabel" name="newLinesLabel">
 191.143 +      <Properties>
 191.144 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.146 +        </Property>
 191.147 +      </Properties>
 191.148 +    </Component>
 191.149 +    <Component class="javax.swing.JCheckBox" name="nlElseCheckBox">
 191.150 +      <Properties>
 191.151 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.153 +        </Property>
 191.154 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.155 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.156 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.157 +          </Border>
 191.158 +        </Property>
 191.159 +      </Properties>
 191.160 +    </Component>
 191.161 +    <Component class="javax.swing.JCheckBox" name="nlWhileCheckBox">
 191.162 +      <Properties>
 191.163 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.165 +        </Property>
 191.166 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.167 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.168 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.169 +          </Border>
 191.170 +        </Property>
 191.171 +      </Properties>
 191.172 +    </Component>
 191.173 +    <Component class="javax.swing.JCheckBox" name="nlCatchCheckBox">
 191.174 +      <Properties>
 191.175 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.177 +        </Property>
 191.178 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.179 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.180 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.181 +          </Border>
 191.182 +        </Property>
 191.183 +      </Properties>
 191.184 +    </Component>
 191.185 +    <Component class="javax.swing.JCheckBox" name="nlFinallyCheckBox">
 191.186 +      <Properties>
 191.187 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.189 +        </Property>
 191.190 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.191 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.192 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.193 +          </Border>
 191.194 +        </Property>
 191.195 +      </Properties>
 191.196 +    </Component>
 191.197 +    <Component class="javax.swing.JCheckBox" name="nlModifiersCheckBox">
 191.198 +      <Properties>
 191.199 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.201 +        </Property>
 191.202 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.203 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.204 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.205 +          </Border>
 191.206 +        </Property>
 191.207 +      </Properties>
 191.208 +    </Component>
 191.209 +    <Component class="javax.swing.JLabel" name="multilineAlignmentLabel">
 191.210 +      <Properties>
 191.211 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.213 +        </Property>
 191.214 +      </Properties>
 191.215 +    </Component>
 191.216 +    <Component class="javax.swing.JCheckBox" name="amMethodParamsCheckBox">
 191.217 +      <Properties>
 191.218 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.220 +        </Property>
 191.221 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.222 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.223 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.224 +          </Border>
 191.225 +        </Property>
 191.226 +      </Properties>
 191.227 +    </Component>
 191.228 +    <Component class="javax.swing.JCheckBox" name="amCallArgsCheckBox">
 191.229 +      <Properties>
 191.230 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.232 +        </Property>
 191.233 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.234 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.235 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.236 +          </Border>
 191.237 +        </Property>
 191.238 +      </Properties>
 191.239 +    </Component>
 191.240 +    <Component class="javax.swing.JCheckBox" name="amAnnotationArgsCheckBox">
 191.241 +      <Properties>
 191.242 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.244 +        </Property>
 191.245 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.246 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.247 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.248 +          </Border>
 191.249 +        </Property>
 191.250 +      </Properties>
 191.251 +    </Component>
 191.252 +    <Component class="javax.swing.JCheckBox" name="amImplementsCheckBox1">
 191.253 +      <Properties>
 191.254 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.256 +        </Property>
 191.257 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.258 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.259 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.260 +          </Border>
 191.261 +        </Property>
 191.262 +      </Properties>
 191.263 +    </Component>
 191.264 +    <Component class="javax.swing.JCheckBox" name="amThrowsCheckBox1">
 191.265 +      <Properties>
 191.266 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.268 +        </Property>
 191.269 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.270 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.271 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.272 +          </Border>
 191.273 +        </Property>
 191.274 +      </Properties>
 191.275 +    </Component>
 191.276 +    <Component class="javax.swing.JCheckBox" name="amArrayInitCheckBox1">
 191.277 +      <Properties>
 191.278 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.280 +        </Property>
 191.281 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.282 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.283 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.284 +          </Border>
 191.285 +        </Property>
 191.286 +      </Properties>
 191.287 +    </Component>
 191.288 +    <Component class="javax.swing.JCheckBox" name="amBinaryOpCheckBox1">
 191.289 +      <Properties>
 191.290 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.292 +        </Property>
 191.293 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.294 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.295 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.296 +          </Border>
 191.297 +        </Property>
 191.298 +      </Properties>
 191.299 +    </Component>
 191.300 +    <Component class="javax.swing.JCheckBox" name="amTernaryOpCheckBox1">
 191.301 +      <Properties>
 191.302 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.304 +        </Property>
 191.305 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.306 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.307 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.308 +          </Border>
 191.309 +        </Property>
 191.310 +      </Properties>
 191.311 +    </Component>
 191.312 +    <Component class="javax.swing.JCheckBox" name="amAssignCheckBox1">
 191.313 +      <Properties>
 191.314 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.316 +        </Property>
 191.317 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.318 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.319 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.320 +          </Border>
 191.321 +        </Property>
 191.322 +      </Properties>
 191.323 +    </Component>
 191.324 +    <Component class="javax.swing.JCheckBox" name="amForCheckBox1">
 191.325 +      <Properties>
 191.326 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.328 +        </Property>
 191.329 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.330 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.331 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.332 +          </Border>
 191.333 +        </Property>
 191.334 +      </Properties>
 191.335 +    </Component>
 191.336 +    <Component class="javax.swing.JCheckBox" name="amParenthesizedCheckBox1">
 191.337 +      <Properties>
 191.338 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 191.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;)"/>
 191.340 +        </Property>
 191.341 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 191.342 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 191.343 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 191.344 +          </Border>
 191.345 +        </Property>
 191.346 +      </Properties>
 191.347 +    </Component>
 191.348 +    <Component class="javax.swing.JSeparator" name="jSeparator1">
 191.349 +    </Component>
 191.350 +    <Component class="javax.swing.JSeparator" name="jSeparator2">
 191.351 +    </Component>
 191.352 +  </SubComponents>
 191.353 +</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/FmtAlignment.java	Mon Sep 21 13:01:16 2015 +0200
   192.3 @@ -0,0 +1,309 @@
   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.python.editor.options.CodeStyle.WrapStyle;
  192.51 +//import static org.netbeans.modules.python.editor.options.FmtOptions.*;
  192.52 +//import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
  192.53 +//import org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport;
  192.54 +//import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
  192.55 +
  192.56 +
  192.57 +/**
  192.58 + *
  192.59 + * @author  phrebejk
  192.60 + */
  192.61 +public class FmtAlignment extends javax.swing.JPanel {
  192.62 +    
  192.63 +    /** Creates new form FmtAlignment */
  192.64 +    public FmtAlignment() {
  192.65 +        initComponents();
  192.66 +/*
  192.67 +        nlElseCheckBox.putClientProperty(OPTION_ID, placeElseOnNewLine);
  192.68 +        nlWhileCheckBox.putClientProperty(OPTION_ID, placeWhileOnNewLine);
  192.69 +        nlCatchCheckBox.putClientProperty(OPTION_ID, placeCatchOnNewLine);
  192.70 +        nlFinallyCheckBox.putClientProperty(OPTION_ID, placeFinallyOnNewLine);
  192.71 +        nlModifiersCheckBox.putClientProperty(OPTION_ID, placeNewLineAfterModifiers);
  192.72 +        amMethodParamsCheckBox.putClientProperty(OPTION_ID, alignMultilineMethodParams);
  192.73 +        amCallArgsCheckBox.putClientProperty(OPTION_ID, alignMultilineCallArgs);
  192.74 +        amAnnotationArgsCheckBox.putClientProperty(OPTION_ID, alignMultilineAnnotationArgs);
  192.75 +        amArrayInitCheckBox1.putClientProperty(OPTION_ID, alignMultilineArrayInit);
  192.76 +        amAssignCheckBox1.putClientProperty(OPTION_ID, alignMultilineAssignment);
  192.77 +        amBinaryOpCheckBox1.putClientProperty(OPTION_ID, alignMultilineBinaryOp);
  192.78 +        amForCheckBox1.putClientProperty(OPTION_ID, alignMultilineFor);
  192.79 +        amImplementsCheckBox1.putClientProperty(OPTION_ID, alignMultilineImplements);
  192.80 +        amParenthesizedCheckBox1.putClientProperty(OPTION_ID, alignMultilineParenthesized);
  192.81 +        amTernaryOpCheckBox1.putClientProperty(OPTION_ID, alignMultilineTernaryOp);
  192.82 +        amThrowsCheckBox1.putClientProperty(OPTION_ID, alignMultilineThrows);
  192.83 +    }
  192.84 +    
  192.85 +    public static PreferencesCustomizer.Factory getController() {
  192.86 +        return new CategorySupport.Factory("alignment", FmtAlignment.class, //NOI18N
  192.87 +                org.openide.util.NbBundle.getMessage(FmtAlignment.class, "SAMPLE_AlignBraces"), // NOI18N
  192.88 +                new String[] { FmtOptions.wrapAnnotations, WrapStyle.WRAP_ALWAYS.name() },
  192.89 +                new String[] { FmtOptions.wrapArrayInit, WrapStyle.WRAP_ALWAYS.name() },
  192.90 +                new String[] { FmtOptions.wrapAssert, WrapStyle.WRAP_ALWAYS.name() },
  192.91 +                new String[] { FmtOptions.wrapAssignOps, WrapStyle.WRAP_ALWAYS.name() },
  192.92 +                new String[] { FmtOptions.wrapBinaryOps, WrapStyle.WRAP_ALWAYS.name() },
  192.93 +                new String[] { FmtOptions.wrapChainedMethodCalls, WrapStyle.WRAP_ALWAYS.name() },
  192.94 +                new String[] { FmtOptions.wrapDoWhileStatement, WrapStyle.WRAP_ALWAYS.name() },
  192.95 +                new String[] { FmtOptions.wrapEnumConstants, WrapStyle.WRAP_ALWAYS.name() },
  192.96 +                new String[] { FmtOptions.wrapExtendsImplementsKeyword, WrapStyle.WRAP_ALWAYS.name() },
  192.97 +                new String[] { FmtOptions.wrapExtendsImplementsList, WrapStyle.WRAP_ALWAYS.name() },
  192.98 +                new String[] { FmtOptions.wrapFor, WrapStyle.WRAP_ALWAYS.name() },
  192.99 +                new String[] { FmtOptions.wrapForStatement, WrapStyle.WRAP_ALWAYS.name() },
 192.100 +                new String[] { FmtOptions.wrapIfStatement, WrapStyle.WRAP_ALWAYS.name() },
 192.101 +                new String[] { FmtOptions.wrapMethodCallArgs, WrapStyle.WRAP_ALWAYS.name() },
 192.102 +                new String[] { FmtOptions.wrapAnnotationArgs, WrapStyle.WRAP_ALWAYS.name() },
 192.103 +                new String[] { FmtOptions.wrapMethodParams, WrapStyle.WRAP_ALWAYS.name() },
 192.104 +                new String[] { FmtOptions.wrapTernaryOps, WrapStyle.WRAP_ALWAYS.name() },
 192.105 +                new String[] { FmtOptions.wrapThrowsKeyword, WrapStyle.WRAP_ALWAYS.name() },
 192.106 +                new String[] { FmtOptions.wrapThrowsList, WrapStyle.WRAP_ALWAYS.name() },
 192.107 +                new String[] { FmtOptions.wrapWhileStatement, WrapStyle.WRAP_ALWAYS.name() }  );
 192.108 + */
 192.109 +    }
 192.110 +    
 192.111 +    /** This method is called from within the constructor to
 192.112 +     * initialize the form.
 192.113 +     * WARNING: Do NOT modify this code. The content of this method is
 192.114 +     * always regenerated by the Form Editor.
 192.115 +     */
 192.116 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
 192.117 +    private void initComponents() {
 192.118 +
 192.119 +        newLinesLabel = new javax.swing.JLabel();
 192.120 +        nlElseCheckBox = new javax.swing.JCheckBox();
 192.121 +        nlWhileCheckBox = new javax.swing.JCheckBox();
 192.122 +        nlCatchCheckBox = new javax.swing.JCheckBox();
 192.123 +        nlFinallyCheckBox = new javax.swing.JCheckBox();
 192.124 +        nlModifiersCheckBox = new javax.swing.JCheckBox();
 192.125 +        multilineAlignmentLabel = new javax.swing.JLabel();
 192.126 +        amMethodParamsCheckBox = new javax.swing.JCheckBox();
 192.127 +        amCallArgsCheckBox = new javax.swing.JCheckBox();
 192.128 +        amAnnotationArgsCheckBox = new javax.swing.JCheckBox();
 192.129 +        amImplementsCheckBox1 = new javax.swing.JCheckBox();
 192.130 +        amThrowsCheckBox1 = new javax.swing.JCheckBox();
 192.131 +        amArrayInitCheckBox1 = new javax.swing.JCheckBox();
 192.132 +        amBinaryOpCheckBox1 = new javax.swing.JCheckBox();
 192.133 +        amTernaryOpCheckBox1 = new javax.swing.JCheckBox();
 192.134 +        amAssignCheckBox1 = new javax.swing.JCheckBox();
 192.135 +        amForCheckBox1 = new javax.swing.JCheckBox();
 192.136 +        amParenthesizedCheckBox1 = new javax.swing.JCheckBox();
 192.137 +        jSeparator1 = new javax.swing.JSeparator();
 192.138 +        jSeparator2 = new javax.swing.JSeparator();
 192.139 +
 192.140 +        setName(org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_Alignment")); // NOI18N
 192.141 +        setOpaque(false);
 192.142 +
 192.143 +        org.openide.awt.Mnemonics.setLocalizedText(newLinesLabel, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_al_newLines")); // NOI18N
 192.144 +
 192.145 +        org.openide.awt.Mnemonics.setLocalizedText(nlElseCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Else")); // NOI18N
 192.146 +        nlElseCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.147 +
 192.148 +        org.openide.awt.Mnemonics.setLocalizedText(nlWhileCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_While")); // NOI18N
 192.149 +        nlWhileCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.150 +
 192.151 +        org.openide.awt.Mnemonics.setLocalizedText(nlCatchCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Catch")); // NOI18N
 192.152 +        nlCatchCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.153 +
 192.154 +        org.openide.awt.Mnemonics.setLocalizedText(nlFinallyCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Finally")); // NOI18N
 192.155 +        nlFinallyCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.156 +
 192.157 +        org.openide.awt.Mnemonics.setLocalizedText(nlModifiersCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_nl_Modifiers")); // NOI18N
 192.158 +        nlModifiersCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.159 +
 192.160 +        org.openide.awt.Mnemonics.setLocalizedText(multilineAlignmentLabel, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_al_multilineAlignment")); // NOI18N
 192.161 +
 192.162 +        org.openide.awt.Mnemonics.setLocalizedText(amMethodParamsCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_MethodParams")); // NOI18N
 192.163 +        amMethodParamsCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.164 +
 192.165 +        org.openide.awt.Mnemonics.setLocalizedText(amCallArgsCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_CallArgs")); // NOI18N
 192.166 +        amCallArgsCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.167 +
 192.168 +        org.openide.awt.Mnemonics.setLocalizedText(amAnnotationArgsCheckBox, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_AnnotationArgs")); // NOI18N
 192.169 +        amAnnotationArgsCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.170 +
 192.171 +        org.openide.awt.Mnemonics.setLocalizedText(amImplementsCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_an_Implements")); // NOI18N
 192.172 +        amImplementsCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.173 +
 192.174 +        org.openide.awt.Mnemonics.setLocalizedText(amThrowsCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_Throws")); // NOI18N
 192.175 +        amThrowsCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.176 +
 192.177 +        org.openide.awt.Mnemonics.setLocalizedText(amArrayInitCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_ArrayInit")); // NOI18N
 192.178 +        amArrayInitCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.179 +
 192.180 +        org.openide.awt.Mnemonics.setLocalizedText(amBinaryOpCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_BinaryOp")); // NOI18N
 192.181 +        amBinaryOpCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.182 +
 192.183 +        org.openide.awt.Mnemonics.setLocalizedText(amTernaryOpCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_TernaryOp")); // NOI18N
 192.184 +        amTernaryOpCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.185 +
 192.186 +        org.openide.awt.Mnemonics.setLocalizedText(amAssignCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_Assign")); // NOI18N
 192.187 +        amAssignCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.188 +
 192.189 +        org.openide.awt.Mnemonics.setLocalizedText(amForCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_For")); // NOI18N
 192.190 +        amForCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.191 +
 192.192 +        org.openide.awt.Mnemonics.setLocalizedText(amParenthesizedCheckBox1, org.openide.util.NbBundle.getMessage(FmtAlignment.class, "LBL_am_Paren")); // NOI18N
 192.193 +        amParenthesizedCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 192.194 +
 192.195 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
 192.196 +        this.setLayout(layout);
 192.197 +        layout.setHorizontalGroup(
 192.198 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 192.199 +            .addGroup(layout.createSequentialGroup()
 192.200 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 192.201 +                    .addGroup(layout.createSequentialGroup()
 192.202 +                        .addContainerGap()
 192.203 +                        .addComponent(amParenthesizedCheckBox1))
 192.204 +                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
 192.205 +                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
 192.206 +                            .addComponent(newLinesLabel)
 192.207 +                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.208 +                            .addComponent(jSeparator1))
 192.209 +                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
 192.210 +                            .addComponent(multilineAlignmentLabel)
 192.211 +                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.212 +                            .addComponent(jSeparator2))
 192.213 +                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
 192.214 +                            .addContainerGap()
 192.215 +                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 192.216 +                                .addComponent(amThrowsCheckBox1)
 192.217 +                                .addComponent(amBinaryOpCheckBox1)
 192.218 +                                .addComponent(amAssignCheckBox1)
 192.219 +                                .addComponent(amAnnotationArgsCheckBox)
 192.220 +                                .addComponent(nlElseCheckBox)
 192.221 +                                .addComponent(nlWhileCheckBox)
 192.222 +                                .addComponent(nlCatchCheckBox)
 192.223 +                                .addComponent(amMethodParamsCheckBox))
 192.224 +                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.225 +                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 192.226 +                                .addComponent(amCallArgsCheckBox)
 192.227 +                                .addComponent(nlModifiersCheckBox)
 192.228 +                                .addComponent(nlFinallyCheckBox)
 192.229 +                                .addComponent(amImplementsCheckBox1)
 192.230 +                                .addComponent(amArrayInitCheckBox1)
 192.231 +                                .addComponent(amTernaryOpCheckBox1)
 192.232 +                                .addComponent(amForCheckBox1)))))
 192.233 +                .addGap(0, 0, 0))
 192.234 +        );
 192.235 +        layout.setVerticalGroup(
 192.236 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 192.237 +            .addGroup(layout.createSequentialGroup()
 192.238 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 192.239 +                    .addGroup(layout.createSequentialGroup()
 192.240 +                        .addContainerGap()
 192.241 +                        .addComponent(newLinesLabel))
 192.242 +                    .addGroup(layout.createSequentialGroup()
 192.243 +                        .addGap(17, 17, 17)
 192.244 +                        .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)))
 192.245 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.246 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 192.247 +                    .addComponent(nlElseCheckBox)
 192.248 +                    .addComponent(nlFinallyCheckBox))
 192.249 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.250 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 192.251 +                    .addComponent(nlWhileCheckBox)
 192.252 +                    .addComponent(nlModifiersCheckBox))
 192.253 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 192.254 +                    .addGroup(layout.createSequentialGroup()
 192.255 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.256 +                        .addComponent(nlCatchCheckBox)
 192.257 +                        .addGap(18, 18, 18)
 192.258 +                        .addComponent(multilineAlignmentLabel))
 192.259 +                    .addGroup(layout.createSequentialGroup()
 192.260 +                        .addGap(44, 44, 44)
 192.261 +                        .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)))
 192.262 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.263 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 192.264 +                    .addComponent(amMethodParamsCheckBox)
 192.265 +                    .addComponent(amCallArgsCheckBox))
 192.266 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.267 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 192.268 +                    .addComponent(amAnnotationArgsCheckBox)
 192.269 +                    .addComponent(amImplementsCheckBox1))
 192.270 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.271 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 192.272 +                    .addComponent(amThrowsCheckBox1)
 192.273 +                    .addComponent(amArrayInitCheckBox1))
 192.274 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.275 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 192.276 +                    .addComponent(amBinaryOpCheckBox1)
 192.277 +                    .addComponent(amTernaryOpCheckBox1))
 192.278 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.279 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 192.280 +                    .addComponent(amAssignCheckBox1)
 192.281 +                    .addComponent(amForCheckBox1))
 192.282 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 192.283 +                .addComponent(amParenthesizedCheckBox1)
 192.284 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 192.285 +        );
 192.286 +    }// </editor-fold>//GEN-END:initComponents
 192.287 +    
 192.288 +    
 192.289 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 192.290 +    private javax.swing.JCheckBox amAnnotationArgsCheckBox;
 192.291 +    private javax.swing.JCheckBox amArrayInitCheckBox1;
 192.292 +    private javax.swing.JCheckBox amAssignCheckBox1;
 192.293 +    private javax.swing.JCheckBox amBinaryOpCheckBox1;
 192.294 +    private javax.swing.JCheckBox amCallArgsCheckBox;
 192.295 +    private javax.swing.JCheckBox amForCheckBox1;
 192.296 +    private javax.swing.JCheckBox amImplementsCheckBox1;
 192.297 +    private javax.swing.JCheckBox amMethodParamsCheckBox;
 192.298 +    private javax.swing.JCheckBox amParenthesizedCheckBox1;
 192.299 +    private javax.swing.JCheckBox amTernaryOpCheckBox1;
 192.300 +    private javax.swing.JCheckBox amThrowsCheckBox1;
 192.301 +    private javax.swing.JSeparator jSeparator1;
 192.302 +    private javax.swing.JSeparator jSeparator2;
 192.303 +    private javax.swing.JLabel multilineAlignmentLabel;
 192.304 +    private javax.swing.JLabel newLinesLabel;
 192.305 +    private javax.swing.JCheckBox nlCatchCheckBox;
 192.306 +    private javax.swing.JCheckBox nlElseCheckBox;
 192.307 +    private javax.swing.JCheckBox nlFinallyCheckBox;
 192.308 +    private javax.swing.JCheckBox nlModifiersCheckBox;
 192.309 +    private javax.swing.JCheckBox nlWhileCheckBox;
 192.310 +    // End of variables declaration//GEN-END:variables
 192.311 +    
 192.312 +}
   193.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   193.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtBlankLines.form	Mon Sep 21 13:01:16 2015 +0200
   193.3 @@ -0,0 +1,284 @@
   193.4 +<?xml version="1.0" encoding="UTF-8" ?>
   193.5 +
   193.6 +<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   193.7 +  <Properties>
   193.8 +    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   193.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;)"/>
  193.10 +    </Property>
  193.11 +    <Property name="opaque" type="boolean" value="false"/>
  193.12 +  </Properties>
  193.13 +  <AuxValues>
  193.14 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
  193.15 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  193.16 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  193.17 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
  193.18 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  193.19 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
  193.20 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
  193.21 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  193.22 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  193.23 +  </AuxValues>
  193.24 +
  193.25 +  <Layout>
  193.26 +    <DimensionLayout dim="0">
  193.27 +      <Group type="103" groupAlignment="0" attributes="0">
  193.28 +          <Group type="102" attributes="0">
  193.29 +              <Group type="103" groupAlignment="0" attributes="0">
  193.30 +                  <Component id="bPackageLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  193.31 +                  <Component id="aPackageLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  193.32 +                  <Component id="bImportsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  193.33 +                  <Component id="aImports" alignment="0" min="-2" max="-2" attributes="0"/>
  193.34 +                  <Component id="bClassLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  193.35 +                  <Component id="aClassLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  193.36 +                  <Component id="aClassHeaderLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  193.37 +                  <Component id="bFieldsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  193.38 +                  <Component id="aFieldsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  193.39 +                  <Component id="bMethodsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  193.40 +                  <Component id="aMethodsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
  193.41 +              </Group>
  193.42 +              <EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
  193.43 +              <Group type="103" groupAlignment="0" attributes="0">
  193.44 +                  <Component id="aMethodsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  193.45 +                  <Component id="bMethodsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  193.46 +                  <Component id="aFieldsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  193.47 +                  <Component id="bFieldsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  193.48 +                  <Component id="aClassHeaderField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  193.49 +                  <Component id="aClassField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  193.50 +                  <Component id="bClassField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  193.51 +                  <Component id="aImportsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  193.52 +                  <Component id="bImportsField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  193.53 +                  <Component id="aPackageField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  193.54 +                  <Component id="bPackageField" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
  193.55 +              </Group>
  193.56 +          </Group>
  193.57 +      </Group>
  193.58 +    </DimensionLayout>
  193.59 +    <DimensionLayout dim="1">
  193.60 +      <Group type="103" groupAlignment="0" attributes="0">
  193.61 +          <Group type="102" attributes="0">
  193.62 +              <Group type="103" groupAlignment="3" attributes="0">
  193.63 +                  <Component id="bPackageField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  193.64 +                  <Component id="bPackageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  193.65 +              </Group>
  193.66 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  193.67 +              <Group type="103" groupAlignment="3" attributes="0">
  193.68 +                  <Component id="aPackageField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  193.69 +                  <Component id="aPackageLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  193.70 +              </Group>
  193.71 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  193.72 +              <Group type="103" groupAlignment="3" attributes="0">
  193.73 +                  <Component id="bImportsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  193.74 +                  <Component id="bImportsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  193.75 +              </Group>
  193.76 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  193.77 +              <Group type="103" groupAlignment="3" attributes="0">
  193.78 +                  <Component id="aImportsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  193.79 +                  <Component id="aImports" alignment="3" min="-2" max="-2" attributes="0"/>
  193.80 +              </Group>
  193.81 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  193.82 +              <Group type="103" groupAlignment="3" attributes="0">
  193.83 +                  <Component id="bClassField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  193.84 +                  <Component id="bClassLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  193.85 +              </Group>
  193.86 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  193.87 +              <Group type="103" groupAlignment="3" attributes="0">
  193.88 +                  <Component id="aClassField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  193.89 +                  <Component id="aClassLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  193.90 +              </Group>
  193.91 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  193.92 +              <Group type="103" groupAlignment="3" attributes="0">
  193.93 +                  <Component id="aClassHeaderField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  193.94 +                  <Component id="aClassHeaderLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  193.95 +              </Group>
  193.96 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
  193.97 +              <Group type="103" groupAlignment="3" attributes="0">
  193.98 +                  <Component id="bFieldsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
  193.99 +                  <Component id="bFieldsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
 193.100 +              </Group>
 193.101 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
 193.102 +              <Group type="103" groupAlignment="3" attributes="0">
 193.103 +                  <Component id="aFieldsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
 193.104 +                  <Component id="aFieldsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
 193.105 +              </Group>
 193.106 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
 193.107 +              <Group type="103" groupAlignment="3" attributes="0">
 193.108 +                  <Component id="bMethodsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
 193.109 +                  <Component id="bMethodsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
 193.110 +              </Group>
 193.111 +              <EmptySpace min="4" pref="4" max="4" attributes="0"/>
 193.112 +              <Group type="103" groupAlignment="3" attributes="0">
 193.113 +                  <Component id="aMethodsField" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
 193.114 +                  <Component id="aMethodsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
 193.115 +              </Group>
 193.116 +          </Group>
 193.117 +      </Group>
 193.118 +    </DimensionLayout>
 193.119 +  </Layout>
 193.120 +  <SubComponents>
 193.121 +    <Component class="javax.swing.JLabel" name="bPackageLabel">
 193.122 +      <Properties>
 193.123 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 193.124 +          <ComponentRef name="bPackageField"/>
 193.125 +        </Property>
 193.126 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 193.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;)"/>
 193.128 +        </Property>
 193.129 +      </Properties>
 193.130 +    </Component>
 193.131 +    <Component class="javax.swing.JTextField" name="bPackageField">
 193.132 +      <Properties>
 193.133 +        <Property name="columns" type="int" value="5"/>
 193.134 +      </Properties>
 193.135 +    </Component>
 193.136 +    <Component class="javax.swing.JLabel" name="aPackageLabel">
 193.137 +      <Properties>
 193.138 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 193.139 +          <ComponentRef name="aPackageField"/>
 193.140 +        </Property>
 193.141 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 193.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;)"/>
 193.143 +        </Property>
 193.144 +      </Properties>
 193.145 +    </Component>
 193.146 +    <Component class="javax.swing.JTextField" name="aPackageField">
 193.147 +      <Properties>
 193.148 +        <Property name="columns" type="int" value="5"/>
 193.149 +      </Properties>
 193.150 +    </Component>
 193.151 +    <Component class="javax.swing.JLabel" name="bImportsLabel">
 193.152 +      <Properties>
 193.153 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 193.154 +          <ComponentRef name="bImportsField"/>
 193.155 +        </Property>
 193.156 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 193.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;)"/>
 193.158 +        </Property>
 193.159 +      </Properties>
 193.160 +    </Component>
 193.161 +    <Component class="javax.swing.JTextField" name="bImportsField">
 193.162 +      <Properties>
 193.163 +        <Property name="columns" type="int" value="5"/>
 193.164 +      </Properties>
 193.165 +    </Component>
 193.166 +    <Component class="javax.swing.JLabel" name="aImports">
 193.167 +      <Properties>
 193.168 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 193.169 +          <ComponentRef name="aImportsField"/>
 193.170 +        </Property>
 193.171 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 193.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;)"/>
 193.173 +        </Property>
 193.174 +      </Properties>
 193.175 +    </Component>
 193.176 +    <Component class="javax.swing.JTextField" name="aImportsField">
 193.177 +      <Properties>
 193.178 +        <Property name="columns" type="int" value="5"/>
 193.179 +      </Properties>
 193.180 +    </Component>
 193.181 +    <Component class="javax.swing.JLabel" name="bClassLabel">
 193.182 +      <Properties>
 193.183 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 193.184 +          <ComponentRef name="bClassField"/>
 193.185 +        </Property>
 193.186 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 193.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;)"/>
 193.188 +        </Property>
 193.189 +      </Properties>
 193.190 +    </Component>
 193.191 +    <Component class="javax.swing.JTextField" name="bClassField">
 193.192 +      <Properties>
 193.193 +        <Property name="columns" type="int" value="5"/>
 193.194 +      </Properties>
 193.195 +    </Component>
 193.196 +    <Component class="javax.swing.JLabel" name="aClassLabel">
 193.197 +      <Properties>
 193.198 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 193.199 +          <ComponentRef name="aClassField"/>
 193.200 +        </Property>
 193.201 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 193.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;)"/>
 193.203 +        </Property>
 193.204 +      </Properties>
 193.205 +    </Component>
 193.206 +    <Component class="javax.swing.JTextField" name="aClassField">
 193.207 +      <Properties>
 193.208 +        <Property name="columns" type="int" value="5"/>
 193.209 +      </Properties>
 193.210 +    </Component>
 193.211 +    <Component class="javax.swing.JLabel" name="aClassHeaderLabel">
 193.212 +      <Properties>
 193.213 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 193.214 +          <ComponentRef name="aClassHeaderField"/>
 193.215 +        </Property>
 193.216 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 193.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;)"/>
 193.218 +        </Property>
 193.219 +      </Properties>
 193.220 +    </Component>
 193.221 +    <Component class="javax.swing.JTextField" name="aClassHeaderField">
 193.222 +      <Properties>
 193.223 +        <Property name="columns" type="int" value="5"/>
 193.224 +      </Properties>
 193.225 +    </Component>
 193.226 +    <Component class="javax.swing.JLabel" name="bFieldsLabel">
 193.227 +      <Properties>
 193.228 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 193.229 +          <ComponentRef name="bFieldsField"/>
 193.230 +        </Property>
 193.231 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 193.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;)"/>
 193.233 +        </Property>
 193.234 +      </Properties>
 193.235 +    </Component>
 193.236 +    <Component class="javax.swing.JTextField" name="bFieldsField">
 193.237 +      <Properties>
 193.238 +        <Property name="columns" type="int" value="5"/>
 193.239 +      </Properties>
 193.240 +    </Component>
 193.241 +    <Component class="javax.swing.JLabel" name="aFieldsLabel">
 193.242 +      <Properties>
 193.243 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 193.244 +          <ComponentRef name="aFieldsField"/>
 193.245 +        </Property>
 193.246 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 193.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;)"/>
 193.248 +        </Property>
 193.249 +      </Properties>
 193.250 +    </Component>
 193.251 +    <Component class="javax.swing.JTextField" name="aFieldsField">
 193.252 +      <Properties>
 193.253 +        <Property name="columns" type="int" value="5"/>
 193.254 +      </Properties>
 193.255 +    </Component>
 193.256 +    <Component class="javax.swing.JLabel" name="bMethodsLabel">
 193.257 +      <Properties>
 193.258 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 193.259 +          <ComponentRef name="bMethodsField"/>
 193.260 +        </Property>
 193.261 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 193.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;)"/>
 193.263 +        </Property>
 193.264 +      </Properties>
 193.265 +    </Component>
 193.266 +    <Component class="javax.swing.JTextField" name="bMethodsField">
 193.267 +      <Properties>
 193.268 +        <Property name="columns" type="int" value="5"/>
 193.269 +      </Properties>
 193.270 +    </Component>
 193.271 +    <Component class="javax.swing.JLabel" name="aMethodsLabel">
 193.272 +      <Properties>
 193.273 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 193.274 +          <ComponentRef name="aMethodsField"/>
 193.275 +        </Property>
 193.276 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 193.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;)"/>
 193.278 +        </Property>
 193.279 +      </Properties>
 193.280 +    </Component>
 193.281 +    <Component class="javax.swing.JTextField" name="aMethodsField">
 193.282 +      <Properties>
 193.283 +        <Property name="columns" type="int" value="5"/>
 193.284 +      </Properties>
 193.285 +    </Component>
 193.286 +  </SubComponents>
 193.287 +</Form>
   194.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   194.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtBlankLines.java	Mon Sep 21 13:01:16 2015 +0200
   194.3 @@ -0,0 +1,295 @@
   194.4 +/*
   194.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   194.6 + *
   194.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   194.8 + *
   194.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  194.10 + * Other names may be trademarks of their respective owners.
  194.11 + *
  194.12 + * The contents of this file are subject to the terms of either the GNU
  194.13 + * General Public License Version 2 only ("GPL") or the Common
  194.14 + * Development and Distribution License("CDDL") (collectively, the
  194.15 + * "License"). You may not use this file except in compliance with the
  194.16 + * License. You can obtain a copy of the License at
  194.17 + * http://www.netbeans.org/cddl-gplv2.html
  194.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  194.19 + * specific language governing permissions and limitations under the
  194.20 + * License.  When distributing the software, include this License Header
  194.21 + * Notice in each file and include the License file at
  194.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  194.23 + * particular file as subject to the "Classpath" exception as provided
  194.24 + * by Oracle in the GPL Version 2 section of the License file that
  194.25 + * accompanied this code. If applicable, add the following below the
  194.26 + * License Header, with the fields enclosed by brackets [] replaced by
  194.27 + * your own identifying information:
  194.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  194.29 + *
  194.30 + * Contributor(s):
  194.31 + *
  194.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  194.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  194.34 + * Microsystems, Inc. All Rights Reserved.
  194.35 + *
  194.36 + * If you wish your version of this file to be governed by only the CDDL
  194.37 + * or only the GPL Version 2, indicate your decision by adding
  194.38 + * "[Contributor] elects to include this software in this distribution
  194.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  194.40 + * single choice of license, a recipient has the option to distribute
  194.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  194.42 + * to extend the choice of license to its licensees as provided above.
  194.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  194.44 + * Version 2 license, then the option applies only if the new code is
  194.45 + * made subject to such option by the copyright holder.
  194.46 + */
  194.47 +
  194.48 +package org.netbeans.modules.python.source.ui;
  194.49 +
  194.50 +//import static org.netbeans.modules.python.editor.options.FmtOptions.*;
  194.51 +//import static org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport.OPTION_ID;
  194.52 +//import org.netbeans.modules.python.editor.options.FmtOptions.CategorySupport;
  194.53 +//import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
  194.54 +
  194.55 +/**
  194.56 + *
  194.57 + * @author  phrebejk
  194.58 + */
  194.59 +public class FmtBlankLines extends javax.swing.JPanel {
  194.60 +    
  194.61 +    /** Creates new form FmtBlankLines */
  194.62 +    public FmtBlankLines() {
  194.63 +        initComponents();
  194.64 +/*
  194.65 +        bPackageField.putClientProperty(OPTION_ID, blankLinesBeforePackage );
  194.66 +        aPackageField.putClientProperty(OPTION_ID, blankLinesAfterPackage);
  194.67 +        bImportsField.putClientProperty(OPTION_ID, blankLinesBeforeImports);
  194.68 +        aImportsField.putClientProperty(OPTION_ID, blankLinesAfterImports);
  194.69 +        bClassField.putClientProperty(OPTION_ID, blankLinesBeforeClass);
  194.70 +        aClassField.putClientProperty(OPTION_ID, blankLinesAfterClass);
  194.71 +        aClassHeaderField.putClientProperty(OPTION_ID, blankLinesAfterClassHeader);
  194.72 +        bFieldsField.putClientProperty(OPTION_ID, blankLinesBeforeFields);
  194.73 +        aFieldsField.putClientProperty(OPTION_ID, blankLinesAfterFields);
  194.74 +        bMethodsField.putClientProperty(OPTION_ID, blankLinesBeforeMethods );
  194.75 +        aMethodsField.putClientProperty(OPTION_ID, blankLinesAfterMethods);
  194.76 +        
  194.77 +        bPackageField.addKeyListener(new NumericKeyListener());
  194.78 +        aPackageField.addKeyListener(new NumericKeyListener());
  194.79 +        bImportsField.addKeyListener(new NumericKeyListener());
  194.80 +        aImportsField.addKeyListener(new NumericKeyListener());
  194.81 +        bClassField.addKeyListener(new NumericKeyListener());
  194.82 +        aClassField.addKeyListener(new NumericKeyListener());
  194.83 +        aClassHeaderField.addKeyListener(new NumericKeyListener());
  194.84 +        bFieldsField.addKeyListener(new NumericKeyListener());
  194.85 +        aFieldsField.addKeyListener(new NumericKeyListener());
  194.86 +        bMethodsField.addKeyListener(new NumericKeyListener());
  194.87 +        aMethodsField.addKeyListener(new NumericKeyListener());
  194.88 +        
  194.89 +    }
  194.90 +    
  194.91 +    public static PreferencesCustomizer.Factory getController() {
  194.92 +        return new CategorySupport.Factory("blank-lines", FmtBlankLines.class, //NOI18N
  194.93 +                 org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "SAMPLE_BlankLines")); // NOI18N
  194.94 + */
  194.95 +    }
  194.96 +    
  194.97 +    /** This method is called from within the constructor to
  194.98 +     * initialize the form.
  194.99 +     * WARNING: Do NOT modify this code. The content of this method is
 194.100 +     * always regenerated by the Form Editor.
 194.101 +     */
 194.102 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
 194.103 +    private void initComponents() {
 194.104 +
 194.105 +        bPackageLabel = new javax.swing.JLabel();
 194.106 +        bPackageField = new javax.swing.JTextField();
 194.107 +        aPackageLabel = new javax.swing.JLabel();
 194.108 +        aPackageField = new javax.swing.JTextField();
 194.109 +        bImportsLabel = new javax.swing.JLabel();
 194.110 +        bImportsField = new javax.swing.JTextField();
 194.111 +        aImports = new javax.swing.JLabel();
 194.112 +        aImportsField = new javax.swing.JTextField();
 194.113 +        bClassLabel = new javax.swing.JLabel();
 194.114 +        bClassField = new javax.swing.JTextField();
 194.115 +        aClassLabel = new javax.swing.JLabel();
 194.116 +        aClassField = new javax.swing.JTextField();
 194.117 +        aClassHeaderLabel = new javax.swing.JLabel();
 194.118 +        aClassHeaderField = new javax.swing.JTextField();
 194.119 +        bFieldsLabel = new javax.swing.JLabel();
 194.120 +        bFieldsField = new javax.swing.JTextField();
 194.121 +        aFieldsLabel = new javax.swing.JLabel();
 194.122 +        aFieldsField = new javax.swing.JTextField();
 194.123 +        bMethodsLabel = new javax.swing.JLabel();
 194.124 +        bMethodsField = new javax.swing.JTextField();
 194.125 +        aMethodsLabel = new javax.swing.JLabel();
 194.126 +        aMethodsField = new javax.swing.JTextField();
 194.127 +
 194.128 +        setName(org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_BlankLines")); // NOI18N
 194.129 +        setOpaque(false);
 194.130 +
 194.131 +        bPackageLabel.setLabelFor(bPackageField);
 194.132 +        org.openide.awt.Mnemonics.setLocalizedText(bPackageLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforePackage")); // NOI18N
 194.133 +
 194.134 +        bPackageField.setColumns(5);
 194.135 +
 194.136 +        aPackageLabel.setLabelFor(aPackageField);
 194.137 +        org.openide.awt.Mnemonics.setLocalizedText(aPackageLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterPackage")); // NOI18N
 194.138 +
 194.139 +        aPackageField.setColumns(5);
 194.140 +
 194.141 +        bImportsLabel.setLabelFor(bImportsField);
 194.142 +        org.openide.awt.Mnemonics.setLocalizedText(bImportsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeImports")); // NOI18N
 194.143 +
 194.144 +        bImportsField.setColumns(5);
 194.145 +
 194.146 +        aImports.setLabelFor(aImportsField);
 194.147 +        org.openide.awt.Mnemonics.setLocalizedText(aImports, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterImports")); // NOI18N
 194.148 +
 194.149 +        aImportsField.setColumns(5);
 194.150 +
 194.151 +        bClassLabel.setLabelFor(bClassField);
 194.152 +        org.openide.awt.Mnemonics.setLocalizedText(bClassLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeClass")); // NOI18N
 194.153 +
 194.154 +        bClassField.setColumns(5);
 194.155 +
 194.156 +        aClassLabel.setLabelFor(aClassField);
 194.157 +        org.openide.awt.Mnemonics.setLocalizedText(aClassLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterClass")); // NOI18N
 194.158 +
 194.159 +        aClassField.setColumns(5);
 194.160 +
 194.161 +        aClassHeaderLabel.setLabelFor(aClassHeaderField);
 194.162 +        org.openide.awt.Mnemonics.setLocalizedText(aClassHeaderLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterClassHeader")); // NOI18N
 194.163 +
 194.164 +        aClassHeaderField.setColumns(5);
 194.165 +
 194.166 +        bFieldsLabel.setLabelFor(bFieldsField);
 194.167 +        org.openide.awt.Mnemonics.setLocalizedText(bFieldsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeFields")); // NOI18N
 194.168 +
 194.169 +        bFieldsField.setColumns(5);
 194.170 +
 194.171 +        aFieldsLabel.setLabelFor(aFieldsField);
 194.172 +        org.openide.awt.Mnemonics.setLocalizedText(aFieldsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterFields")); // NOI18N
 194.173 +
 194.174 +        aFieldsField.setColumns(5);
 194.175 +
 194.176 +        bMethodsLabel.setLabelFor(bMethodsField);
 194.177 +        org.openide.awt.Mnemonics.setLocalizedText(bMethodsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blBeforeMethods")); // NOI18N
 194.178 +
 194.179 +        bMethodsField.setColumns(5);
 194.180 +
 194.181 +        aMethodsLabel.setLabelFor(aMethodsField);
 194.182 +        org.openide.awt.Mnemonics.setLocalizedText(aMethodsLabel, org.openide.util.NbBundle.getMessage(FmtBlankLines.class, "LBL_blAfterMethods")); // NOI18N
 194.183 +
 194.184 +        aMethodsField.setColumns(5);
 194.185 +
 194.186 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
 194.187 +        this.setLayout(layout);
 194.188 +        layout.setHorizontalGroup(
 194.189 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 194.190 +            .addGroup(layout.createSequentialGroup()
 194.191 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 194.192 +                    .addComponent(bPackageLabel)
 194.193 +                    .addComponent(aPackageLabel)
 194.194 +                    .addComponent(bImportsLabel)
 194.195 +                    .addComponent(aImports)
 194.196 +                    .addComponent(bClassLabel)
 194.197 +                    .addComponent(aClassLabel)
 194.198 +                    .addComponent(aClassHeaderLabel)
 194.199 +                    .addComponent(bFieldsLabel)
 194.200 +                    .addComponent(aFieldsLabel)
 194.201 +                    .addComponent(bMethodsLabel)
 194.202 +                    .addComponent(aMethodsLabel))
 194.203 +                .addGap(6, 6, 6)
 194.204 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 194.205 +                    .addComponent(aMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.206 +                    .addComponent(bMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.207 +                    .addComponent(aFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.208 +                    .addComponent(bFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.209 +                    .addComponent(aClassHeaderField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.210 +                    .addComponent(aClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.211 +                    .addComponent(bClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.212 +                    .addComponent(aImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.213 +                    .addComponent(bImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.214 +                    .addComponent(aPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.215 +                    .addComponent(bPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
 194.216 +        );
 194.217 +
 194.218 +        layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {aClassField, aClassHeaderField, aFieldsField, aImportsField, aMethodsField, aPackageField, bClassField, bFieldsField, bImportsField, bMethodsField, bPackageField});
 194.219 +
 194.220 +        layout.setVerticalGroup(
 194.221 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 194.222 +            .addGroup(layout.createSequentialGroup()
 194.223 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 194.224 +                    .addComponent(bPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.225 +                    .addComponent(bPackageLabel))
 194.226 +                .addGap(4, 4, 4)
 194.227 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 194.228 +                    .addComponent(aPackageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.229 +                    .addComponent(aPackageLabel))
 194.230 +                .addGap(4, 4, 4)
 194.231 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 194.232 +                    .addComponent(bImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.233 +                    .addComponent(bImportsLabel))
 194.234 +                .addGap(4, 4, 4)
 194.235 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 194.236 +                    .addComponent(aImportsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.237 +                    .addComponent(aImports))
 194.238 +                .addGap(4, 4, 4)
 194.239 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 194.240 +                    .addComponent(bClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.241 +                    .addComponent(bClassLabel))
 194.242 +                .addGap(4, 4, 4)
 194.243 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 194.244 +                    .addComponent(aClassField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.245 +                    .addComponent(aClassLabel))
 194.246 +                .addGap(4, 4, 4)
 194.247 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 194.248 +                    .addComponent(aClassHeaderField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.249 +                    .addComponent(aClassHeaderLabel))
 194.250 +                .addGap(4, 4, 4)
 194.251 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 194.252 +                    .addComponent(bFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.253 +                    .addComponent(bFieldsLabel))
 194.254 +                .addGap(4, 4, 4)
 194.255 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 194.256 +                    .addComponent(aFieldsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.257 +                    .addComponent(aFieldsLabel))
 194.258 +                .addGap(4, 4, 4)
 194.259 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 194.260 +                    .addComponent(bMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.261 +                    .addComponent(bMethodsLabel))
 194.262 +                .addGap(4, 4, 4)
 194.263 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 194.264 +                    .addComponent(aMethodsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 194.265 +                    .addComponent(aMethodsLabel)))
 194.266 +        );
 194.267 +
 194.268 +        layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {aClassField, aClassHeaderField, aFieldsField, aImportsField, aMethodsField, aPackageField, bClassField, bFieldsField, bImportsField, bMethodsField, bPackageField});
 194.269 +
 194.270 +    }// </editor-fold>//GEN-END:initComponents
 194.271 +    
 194.272 +    
 194.273 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 194.274 +    private javax.swing.JTextField aClassField;
 194.275 +    private javax.swing.JTextField aClassHeaderField;
 194.276 +    private javax.swing.JLabel aClassHeaderLabel;
 194.277 +    private javax.swing.JLabel aClassLabel;
 194.278 +    private javax.swing.JTextField aFieldsField;
 194.279 +    private javax.swing.JLabel aFieldsLabel;
 194.280 +    private javax.swing.JLabel aImports;
 194.281 +    private javax.swing.JTextField aImportsField;
 194.282 +    private javax.swing.JTextField aMethodsField;
 194.283 +    private javax.swing.JLabel aMethodsLabel;
 194.284 +    private javax.swing.JTextField aPackageField;
 194.285 +    private javax.swing.JLabel aPackageLabel;
 194.286 +    private javax.swing.JTextField bClassField;
 194.287 +    private javax.swing.JLabel bClassLabel;
 194.288 +    private javax.swing.JTextField bFieldsField;
 194.289 +    private javax.swing.JLabel bFieldsLabel;
 194.290 +    private javax.swing.JTextField bImportsField;
 194.291 +    private javax.swing.JLabel bImportsLabel;
 194.292 +    private javax.swing.JTextField bMethodsField;
 194.293 +    private javax.swing.JLabel bMethodsLabel;
 194.294 +    private javax.swing.JTextField bPackageField;
 194.295 +    private javax.swing.JLabel bPackageLabel;
 194.296 +    // End of variables declaration//GEN-END:variables
 194.297 +    
 194.298 +}
   195.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   195.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtImports.form	Mon Sep 21 13:01:16 2015 +0200
   195.3 @@ -0,0 +1,129 @@
   195.4 +<?xml version="1.0" encoding="UTF-8" ?>
   195.5 +
   195.6 +<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   195.7 +  <Properties>
   195.8 +    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   195.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;)"/>
  195.10 +    </Property>
  195.11 +  </Properties>
  195.12 +  <AuxValues>
  195.13 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
  195.14 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  195.15 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  195.16 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
  195.17 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  195.18 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
  195.19 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
  195.20 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  195.21 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  195.22 +  </AuxValues>
  195.23 +
  195.24 +  <Layout>
  195.25 +    <DimensionLayout dim="0">
  195.26 +      <Group type="103" groupAlignment="0" attributes="0">
  195.27 +          <Group type="102" attributes="0">
  195.28 +              <Group type="103" groupAlignment="0" attributes="0">
  195.29 +                  <Component id="formatImportsCb" alignment="0" min="-2" max="-2" attributes="0"/>
  195.30 +                  <Component id="onePerLineCb" alignment="0" min="-2" max="-2" attributes="0"/>
  195.31 +                  <Component id="systemLibsCb" alignment="0" min="-2" max="-2" attributes="0"/>
  195.32 +                  <Component id="sortImportsCb" alignment="0" min="-2" max="-2" attributes="0"/>
  195.33 +                  <Component id="sepFromImpCb" alignment="0" min="-2" max="-2" attributes="0"/>
  195.34 +                  <Component id="removeDuplicateCb" alignment="0" min="-2" max="-2" attributes="0"/>
  195.35 +                  <Component id="preferSymbols" alignment="0" min="-2" max="-2" attributes="0"/>
  195.36 +                  <Group type="102" alignment="0" attributes="0">
  195.37 +                      <Component id="cleanupLabel" min="-2" max="-2" attributes="0"/>
  195.38 +                      <EmptySpace max="-2" attributes="0"/>
  195.39 +                      <Component id="cleanupCombo" min="-2" max="-2" attributes="0"/>
  195.40 +                  </Group>
  195.41 +              </Group>
  195.42 +              <EmptySpace max="32767" attributes="0"/>
  195.43 +          </Group>
  195.44 +      </Group>
  195.45 +    </DimensionLayout>
  195.46 +    <DimensionLayout dim="1">
  195.47 +      <Group type="103" groupAlignment="0" attributes="0">
  195.48 +          <Group type="102" alignment="0" attributes="0">
  195.49 +              <Component id="formatImportsCb" min="-2" max="-2" attributes="0"/>
  195.50 +              <EmptySpace type="separate" max="-2" attributes="0"/>
  195.51 +              <Component id="onePerLineCb" min="-2" max="-2" attributes="0"/>
  195.52 +              <EmptySpace max="-2" attributes="0"/>
  195.53 +              <Component id="systemLibsCb" min="-2" max="-2" attributes="0"/>
  195.54 +              <EmptySpace max="-2" attributes="0"/>
  195.55 +              <Component id="sortImportsCb" min="-2" max="-2" attributes="0"/>
  195.56 +              <EmptySpace max="-2" attributes="0"/>
  195.57 +              <Component id="sepFromImpCb" min="-2" max="-2" attributes="0"/>
  195.58 +              <EmptySpace max="-2" attributes="0"/>
  195.59 +              <Component id="removeDuplicateCb" min="-2" max="-2" attributes="0"/>
  195.60 +              <EmptySpace max="-2" attributes="0"/>
  195.61 +              <Component id="preferSymbols" min="-2" max="-2" attributes="0"/>
  195.62 +              <EmptySpace type="separate" max="-2" attributes="0"/>
  195.63 +              <Group type="103" groupAlignment="3" attributes="0">
  195.64 +                  <Component id="cleanupLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  195.65 +                  <Component id="cleanupCombo" alignment="3" min="-2" max="-2" attributes="0"/>
  195.66 +              </Group>
  195.67 +              <EmptySpace max="32767" attributes="0"/>
  195.68 +          </Group>
  195.69 +      </Group>
  195.70 +    </DimensionLayout>
  195.71 +  </Layout>
  195.72 +  <SubComponents>
  195.73 +    <Component class="javax.swing.JCheckBox" name="formatImportsCb">
  195.74 +      <Properties>
  195.75 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  195.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;)"/>
  195.77 +        </Property>
  195.78 +      </Properties>
  195.79 +    </Component>
  195.80 +    <Component class="javax.swing.JCheckBox" name="onePerLineCb">
  195.81 +      <Properties>
  195.82 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  195.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;)"/>
  195.84 +        </Property>
  195.85 +      </Properties>
  195.86 +    </Component>
  195.87 +    <Component class="javax.swing.JCheckBox" name="systemLibsCb">
  195.88 +      <Properties>
  195.89 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  195.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;)"/>
  195.91 +        </Property>
  195.92 +      </Properties>
  195.93 +    </Component>
  195.94 +    <Component class="javax.swing.JCheckBox" name="removeDuplicateCb">
  195.95 +      <Properties>
  195.96 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  195.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;)"/>
  195.98 +        </Property>
  195.99 +      </Properties>
 195.100 +    </Component>
 195.101 +    <Component class="javax.swing.JLabel" name="cleanupLabel">
 195.102 +      <Properties>
 195.103 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 195.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;)"/>
 195.105 +        </Property>
 195.106 +      </Properties>
 195.107 +    </Component>
 195.108 +    <Component class="javax.swing.JComboBox" name="cleanupCombo">
 195.109 +    </Component>
 195.110 +    <Component class="javax.swing.JCheckBox" name="preferSymbols">
 195.111 +      <Properties>
 195.112 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 195.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;)"/>
 195.114 +        </Property>
 195.115 +      </Properties>
 195.116 +    </Component>
 195.117 +    <Component class="javax.swing.JCheckBox" name="sortImportsCb">
 195.118 +      <Properties>
 195.119 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 195.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;)"/>
 195.121 +        </Property>
 195.122 +      </Properties>
 195.123 +    </Component>
 195.124 +    <Component class="javax.swing.JCheckBox" name="sepFromImpCb">
 195.125 +      <Properties>
 195.126 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 195.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;)"/>
 195.128 +        </Property>
 195.129 +      </Properties>
 195.130 +    </Component>
 195.131 +  </SubComponents>
 195.132 +</Form>
   196.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   196.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtImports.java	Mon Sep 21 13:01:16 2015 +0200
   196.3 @@ -0,0 +1,169 @@
   196.4 +/*
   196.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   196.6 + *
   196.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   196.8 + *
   196.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  196.10 + * Other names may be trademarks of their respective owners.
  196.11 + *
  196.12 + * The contents of this file are subject to the terms of either the GNU
  196.13 + * General Public License Version 2 only ("GPL") or the Common
  196.14 + * Development and Distribution License("CDDL") (collectively, the
  196.15 + * "License"). You may not use this file except in compliance with the
  196.16 + * License. You can obtain a copy of the License at
  196.17 + * http://www.netbeans.org/cddl-gplv2.html
  196.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  196.19 + * specific language governing permissions and limitations under the
  196.20 + * License.  When distributing the software, include this License Header
  196.21 + * Notice in each file and include the License file at
  196.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  196.23 + * particular file as subject to the "Classpath" exception as provided
  196.24 + * by Oracle in the GPL Version 2 section of the License file that
  196.25 + * accompanied this code. If applicable, add the following below the
  196.26 + * License Header, with the fields enclosed by brackets [] replaced by
  196.27 + * your own identifying information:
  196.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  196.29 + *
  196.30 + * Contributor(s):
  196.31 + *
  196.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  196.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  196.34 + * Microsystems, Inc. All Rights Reserved.
  196.35 + *
  196.36 + * If you wish your version of this file to be governed by only the CDDL
  196.37 + * or only the GPL Version 2, indicate your decision by adding
  196.38 + * "[Contributor] elects to include this software in this distribution
  196.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  196.40 + * single choice of license, a recipient has the option to distribute
  196.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  196.42 + * to extend the choice of license to its licensees as provided above.
  196.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  196.44 + * Version 2 license, then the option applies only if the new code is
  196.45 + * made subject to such option by the copyright holder.
  196.46 + */
  196.47 +
  196.48 +package org.netbeans.modules.python.source.ui;
  196.49 +
  196.50 +import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
  196.51 +import static org.netbeans.modules.python.source.ui.FmtOptions.*;
  196.52 +import static org.netbeans.modules.python.source.ui.FmtOptions.CategorySupport.OPTION_ID;
  196.53 +
  196.54 +/**
  196.55 + * Options related to imports
  196.56 + * 
  196.57 + * @author  Tor Norbye
  196.58 + */
  196.59 +public class FmtImports extends javax.swing.JPanel {
  196.60 +    
  196.61 +    /** Creates new form FmtImports */
  196.62 +    public FmtImports() {
  196.63 +        initComponents();
  196.64 +
  196.65 +        formatImportsCb.putClientProperty(OPTION_ID, formatImports);
  196.66 +        onePerLineCb.putClientProperty(OPTION_ID, oneImportPerLine);
  196.67 +        removeDuplicateCb.putClientProperty(OPTION_ID, removeDuplicates);
  196.68 +        systemLibsCb.putClientProperty(OPTION_ID, systemLibsFirst);
  196.69 +        cleanupCombo.putClientProperty(OPTION_ID, cleanupUnusedImports);
  196.70 +        preferSymbols.putClientProperty(OPTION_ID, preferSymbolImports);
  196.71 +        sortImportsCb.putClientProperty(OPTION_ID, sortImports);
  196.72 +        sepFromImpCb.putClientProperty(OPTION_ID, separateFromImps);
  196.73 +    }
  196.74 +    
  196.75 +    public static PreferencesCustomizer.Factory getController() {
  196.76 +        return new CategorySupport.Factory("imports", FmtImports.class,
  196.77 +                org.openide.util.NbBundle.getMessage(FmtImports.class, "SAMPLE_Imports"));
  196.78 +    }
  196.79 +    
  196.80 +    /** This method is called from within the constructor to
  196.81 +     * initialize the form.
  196.82 +     * WARNING: Do NOT modify this code. The content of this method is
  196.83 +     * always regenerated by the Form Editor.
  196.84 +     */
  196.85 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  196.86 +    private void initComponents() {
  196.87 +
  196.88 +        formatImportsCb = new javax.swing.JCheckBox();
  196.89 +        onePerLineCb = new javax.swing.JCheckBox();
  196.90 +        systemLibsCb = new javax.swing.JCheckBox();
  196.91 +        removeDuplicateCb = new javax.swing.JCheckBox();
  196.92 +        cleanupLabel = new javax.swing.JLabel();
  196.93 +        cleanupCombo = new javax.swing.JComboBox();
  196.94 +        preferSymbols = new javax.swing.JCheckBox();
  196.95 +        sortImportsCb = new javax.swing.JCheckBox();
  196.96 +        sepFromImpCb = new javax.swing.JCheckBox();
  196.97 +
  196.98 +        setName(org.openide.util.NbBundle.getMessage(FmtImports.class, "LBL_Imports")); // NOI18N
  196.99 +
 196.100 +        org.openide.awt.Mnemonics.setLocalizedText(formatImportsCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.formatImportsCb.text")); // NOI18N
 196.101 +
 196.102 +        org.openide.awt.Mnemonics.setLocalizedText(onePerLineCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.onePerLineCb.text")); // NOI18N
 196.103 +
 196.104 +        org.openide.awt.Mnemonics.setLocalizedText(systemLibsCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.systemLibsCb.text")); // NOI18N
 196.105 +
 196.106 +        org.openide.awt.Mnemonics.setLocalizedText(removeDuplicateCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.removeDuplicateCb.text")); // NOI18N
 196.107 +
 196.108 +        org.openide.awt.Mnemonics.setLocalizedText(cleanupLabel, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.cleanupLabel.text")); // NOI18N
 196.109 +
 196.110 +        org.openide.awt.Mnemonics.setLocalizedText(preferSymbols, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.preferSymbols.text")); // NOI18N
 196.111 +
 196.112 +        org.openide.awt.Mnemonics.setLocalizedText(sortImportsCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.sortImportsCb.text")); // NOI18N
 196.113 +
 196.114 +        org.openide.awt.Mnemonics.setLocalizedText(sepFromImpCb, org.openide.util.NbBundle.getMessage(FmtImports.class, "FmtImports.sepFromImpCb.text")); // NOI18N
 196.115 +
 196.116 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
 196.117 +        this.setLayout(layout);
 196.118 +        layout.setHorizontalGroup(
 196.119 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 196.120 +            .addGroup(layout.createSequentialGroup()
 196.121 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 196.122 +                    .addComponent(formatImportsCb)
 196.123 +                    .addComponent(onePerLineCb)
 196.124 +                    .addComponent(systemLibsCb)
 196.125 +                    .addComponent(sortImportsCb)
 196.126 +                    .addComponent(sepFromImpCb)
 196.127 +                    .addComponent(removeDuplicateCb)
 196.128 +                    .addComponent(preferSymbols)
 196.129 +                    .addGroup(layout.createSequentialGroup()
 196.130 +                        .addComponent(cleanupLabel)
 196.131 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 196.132 +                        .addComponent(cleanupCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
 196.133 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 196.134 +        );
 196.135 +        layout.setVerticalGroup(
 196.136 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 196.137 +            .addGroup(layout.createSequentialGroup()
 196.138 +                .addComponent(formatImportsCb)
 196.139 +                .addGap(18, 18, 18)
 196.140 +                .addComponent(onePerLineCb)
 196.141 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 196.142 +                .addComponent(systemLibsCb)
 196.143 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 196.144 +                .addComponent(sortImportsCb)
 196.145 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 196.146 +                .addComponent(sepFromImpCb)
 196.147 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 196.148 +                .addComponent(removeDuplicateCb)
 196.149 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 196.150 +                .addComponent(preferSymbols)
 196.151 +                .addGap(18, 18, 18)
 196.152 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 196.153 +                    .addComponent(cleanupLabel)
 196.154 +                    .addComponent(cleanupCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 196.155 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 196.156 +        );
 196.157 +    }// </editor-fold>//GEN-END:initComponents
 196.158 +    
 196.159 +    
 196.160 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 196.161 +    private javax.swing.JComboBox cleanupCombo;
 196.162 +    private javax.swing.JLabel cleanupLabel;
 196.163 +    private javax.swing.JCheckBox formatImportsCb;
 196.164 +    private javax.swing.JCheckBox onePerLineCb;
 196.165 +    private javax.swing.JCheckBox preferSymbols;
 196.166 +    private javax.swing.JCheckBox removeDuplicateCb;
 196.167 +    private javax.swing.JCheckBox sepFromImpCb;
 196.168 +    private javax.swing.JCheckBox sortImportsCb;
 196.169 +    private javax.swing.JCheckBox systemLibsCb;
 196.170 +    // End of variables declaration//GEN-END:variables
 196.171 +    
 196.172 +}
   197.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   197.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtOptions.java	Mon Sep 21 13:01:16 2015 +0200
   197.3 @@ -0,0 +1,1036 @@
   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-2007 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 +package org.netbeans.modules.python.source.ui;
  197.48 +
  197.49 +import org.netbeans.modules.python.source.CodeStyle;
  197.50 +import java.awt.Component;
  197.51 +import java.awt.Container;
  197.52 +import java.awt.Rectangle;
  197.53 +import java.awt.event.ActionEvent;
  197.54 +import java.awt.event.ActionListener;
  197.55 +import java.io.BufferedWriter;
  197.56 +import java.io.File;
  197.57 +import java.io.FileWriter;
  197.58 +import java.io.IOException;
  197.59 +import java.util.Arrays;
  197.60 +import java.util.HashMap;
  197.61 +import java.util.HashSet;
  197.62 +import java.util.LinkedList;
  197.63 +import java.util.List;
  197.64 +import java.util.Map;
  197.65 +import java.util.Set;
  197.66 +import java.util.prefs.AbstractPreferences;
  197.67 +import java.util.prefs.BackingStoreException;
  197.68 +import java.util.prefs.Preferences;
  197.69 +import javax.swing.ComboBoxModel;
  197.70 +import javax.swing.DefaultComboBoxModel;
  197.71 +import javax.swing.JCheckBox;
  197.72 +import javax.swing.JComboBox;
  197.73 +import javax.swing.JComponent;
  197.74 +import javax.swing.JEditorPane;
  197.75 +import javax.swing.JPanel;
  197.76 +import javax.swing.JTextField;
  197.77 +import javax.swing.event.DocumentEvent;
  197.78 +import javax.swing.event.DocumentListener;
  197.79 +import javax.swing.text.BadLocationException;
  197.80 +import javax.swing.text.Document;
  197.81 +import org.netbeans.api.editor.settings.SimpleValueNames;
  197.82 +import static org.netbeans.modules.python.source.CodeStyle.*;
  197.83 +import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
  197.84 +import org.netbeans.modules.options.editor.spi.PreviewProvider;
  197.85 +import org.netbeans.modules.python.api.PythonMIMEResolver;
  197.86 +import org.netbeans.modules.python.source.PythonFormatter;
  197.87 +import org.netbeans.modules.python.source.PythonParserResult;
  197.88 +import org.openide.cookies.SaveCookie;
  197.89 +import org.openide.filesystems.FileObject;
  197.90 +import org.openide.filesystems.FileUtil;
  197.91 +import org.openide.loaders.DataObject;
  197.92 +import org.openide.loaders.DataObjectNotFoundException;
  197.93 +import org.openide.text.CloneableEditorSupport;
  197.94 +import org.openide.util.Exceptions;
  197.95 +import org.openide.util.HelpCtx;
  197.96 +import org.openide.util.NbBundle;
  197.97 +
  197.98 +/**
  197.99 + *
 197.100 + * @author phrebejk
 197.101 + */
 197.102 +public class FmtOptions {
 197.103 +    public static final String expandTabToSpaces = SimpleValueNames.EXPAND_TABS;
 197.104 +    public static final String tabSize = SimpleValueNames.TAB_SIZE;
 197.105 +    public static final String spacesPerTab = SimpleValueNames.SPACES_PER_TAB;
 197.106 +    public static final String indentSize = SimpleValueNames.INDENT_SHIFT_WIDTH;
 197.107 +    public static final String continuationIndentSize = "continuationIndentSize"; //NOI18N
 197.108 +    public static final String labelIndent = "labelIndent"; //NOI18N
 197.109 +    public static final String absoluteLabelIndent = "absoluteLabelIndent"; //NOI18N
 197.110 +    public static final String indentTopLevelClassMembers = "indentTopLevelClassMembers"; //NOI18N
 197.111 +    public static final String indentCasesFromSwitch = "indentCasesFromSwitch"; //NOI18N
 197.112 +    public static final String rightMargin = SimpleValueNames.TEXT_LIMIT_WIDTH;
 197.113 +
 197.114 +    /*
 197.115 +    public static final String addLeadingStarInComment = "addLeadingStarInComment"; //NOI18N
 197.116 +
 197.117 +    public static final String preferLongerNames = "preferLongerNames"; //NOI18N
 197.118 +    public static final String fieldNamePrefix = "fieldNamePrefix"; //NOI18N
 197.119 +    public static final String fieldNameSuffix = "fieldNameSuffix"; //NOI18N
 197.120 +    public static final String staticFieldNamePrefix = "staticFieldNamePrefix"; //NOI18N
 197.121 +    public static final String staticFieldNameSuffix = "staticFieldNameSuffix"; //NOI18N
 197.122 +    public static final String parameterNamePrefix = "parameterNamePrefix"; //NOI18N
 197.123 +    public static final String parameterNameSuffix = "parameterNameSuffix"; //NOI18N
 197.124 +    public static final String localVarNamePrefix = "localVarNamePrefix"; //NOI18N
 197.125 +    public static final String localVarNameSuffix = "localVarNameSuffix"; //NOI18N
 197.126 +    public static final String qualifyFieldAccess = "qualifyFieldAccess"; //NOI18N
 197.127 +    public static final String useIsForBooleanGetters = "useIsForBooleanGetters"; //NOI18N
 197.128 +    public static final String addOverrideAnnotation = "addOverrideAnnotation"; //NOI18N
 197.129 +    public static final String makeLocalVarsFinal = "makeLocalVarsFinal"; //NOI18N
 197.130 +    public static final String makeParametersFinal = "makeParametersFinal"; //NOI18N
 197.131 +    public static final String classMembersOrder = "classMembersOrder"; //NOI18N
 197.132 +    
 197.133 +    public static final String alignMultilineMethodParams = "alignMultilineMethodParams"; //NOI18N
 197.134 +    public static final String alignMultilineCallArgs = "alignMultilineCallArgs"; //NOI18N
 197.135 +    public static final String alignMultilineAnnotationArgs = "alignMultilineAnnotationArgs"; //NOI18N
 197.136 +    public static final String alignMultilineImplements = "alignMultilineImplements"; //NOI18N
 197.137 +    public static final String alignMultilineThrows = "alignMultilineThrows"; //NOI18N
 197.138 +    public static final String alignMultilineParenthesized = "alignMultilineParenthesized"; //NOI18N
 197.139 +    public static final String alignMultilineBinaryOp = "alignMultilineBinaryOp"; //NOI18N
 197.140 +    public static final String alignMultilineTernaryOp = "alignMultilineTernaryOp"; //NOI18N
 197.141 +    public static final String alignMultilineAssignment = "alignMultilineAssignment"; //NOI18N
 197.142 +    public static final String alignMultilineFor = "alignMultilineFor"; //NOI18N
 197.143 +    public static final String alignMultilineArrayInit = "alignMultilineArrayInit"; //NOI18N
 197.144 +    public static final String placeElseOnNewLine = "placeElseOnNewLine"; //NOI18N
 197.145 +    public static final String placeWhileOnNewLine = "placeWhileOnNewLine"; //NOI18N
 197.146 +    public static final String placeCatchOnNewLine = "placeCatchOnNewLine"; //NOI18N
 197.147 +    public static final String placeFinallyOnNewLine = "placeFinallyOnNewLine"; //NOI18N
 197.148 +    public static final String placeNewLineAfterModifiers = "placeNewLineAfterModifiers"; //NOI18N
 197.149 +    
 197.150 +    public static final String wrapExtendsImplementsKeyword = "wrapExtendsImplementsKeyword"; //NOI18N
 197.151 +    public static final String wrapExtendsImplementsList = "wrapExtendsImplementsList"; //NOI18N
 197.152 +    public static final String wrapMethodParams = "wrapMethodParams"; //NOI18N
 197.153 +    public static final String wrapThrowsKeyword = "wrapThrowsKeyword"; //NOI18N
 197.154 +    public static final String wrapThrowsList = "wrapThrowsList"; //NOI18N
 197.155 +    public static final String wrapMethodCallArgs = "wrapMethodCallArgs"; //NOI18N
 197.156 +    public static final String wrapAnnotationArgs = "wrapAnnotationArgs"; //NOI18N
 197.157 +    public static final String wrapChainedMethodCalls = "wrapChainedMethodCalls"; //NOI18N
 197.158 +    public static final String wrapArrayInit = "wrapArrayInit"; //NOI18N
 197.159 +    public static final String wrapFor = "wrapFor"; //NOI18N
 197.160 +    public static final String wrapForStatement = "wrapForStatement"; //NOI18N
 197.161 +    public static final String wrapIfStatement = "wrapIfStatement"; //NOI18N
 197.162 +    public static final String wrapWhileStatement = "wrapWhileStatement"; //NOI18N
 197.163 +    public static final String wrapDoWhileStatement = "wrapDoWhileStatement"; //NOI18N
 197.164 +    public static final String wrapAssert = "wrapAssert"; //NOI18N
 197.165 +    public static final String wrapEnumConstants = "wrapEnumConstants"; //NOI18N
 197.166 +    public static final String wrapAnnotations = "wrapAnnotations"; //NOI18N
 197.167 +    public static final String wrapBinaryOps = "wrapBinaryOps"; //NOI18N
 197.168 +    public static final String wrapTernaryOps = "wrapTernaryOps"; //NOI18N
 197.169 +    public static final String wrapAssignOps = "wrapAssignOps"; //NOI18N
 197.170 +    
 197.171 +    public static final String blankLinesBeforePackage = "blankLinesBeforePackage"; //NOI18N
 197.172 +    public static final String blankLinesAfterPackage = "blankLinesAfterPackage"; //NOI18N
 197.173 +    public static final String blankLinesBeforeImports = "blankLinesBeforeImports"; //NOI18N
 197.174 +    public static final String blankLinesAfterImports = "blankLinesAfterImports"; //NOI18N
 197.175 +    public static final String blankLinesBeforeClass = "blankLinesBeforeClass"; //NOI18N
 197.176 +    public static final String blankLinesAfterClass = "blankLinesAfterClass"; //NOI18N
 197.177 +    public static final String blankLinesAfterClassHeader = "blankLinesAfterClassHeader"; //NOI18N
 197.178 +    public static final String blankLinesBeforeFields = "blankLinesBeforeFields"; //NOI18N
 197.179 +    public static final String blankLinesAfterFields = "blankLinesAfterFields"; //NOI18N
 197.180 +    public static final String blankLinesBeforeMethods = "blankLinesBeforeMethods"; //NOI18N
 197.181 +    public static final String blankLinesAfterMethods = "blankLinesAfterMethods"; //NOI18N
 197.182 +    
 197.183 +    public static final String spaceBeforeWhile = "spaceBeforeWhile"; //NOI18N
 197.184 +    public static final String spaceBeforeElse = "spaceBeforeElse"; //NOI18N
 197.185 +    public static final String spaceBeforeCatch = "spaceBeforeCatch"; //NOI18N
 197.186 +    public static final String spaceBeforeFinally = "spaceBeforeFinally"; //NOI18N
 197.187 +    public static final String spaceBeforeMethodDeclParen = "spaceBeforeMethodDeclParen"; //NOI18N
 197.188 +    public static final String spaceBeforeMethodCallParen = "spaceBeforeMethodCallParen"; //NOI18N
 197.189 +    public static final String spaceBeforeIfParen = "spaceBeforeIfParen"; //NOI18N
 197.190 +    public static final String spaceBeforeForParen = "spaceBeforeForParen"; //NOI18N
 197.191 +    public static final String spaceBeforeWhileParen = "spaceBeforeWhileParen"; //NOI18N
 197.192 +    public static final String spaceBeforeCatchParen = "spaceBeforeCatchParen"; //NOI18N
 197.193 +    public static final String spaceBeforeSwitchParen = "spaceBeforeSwitchParen"; //NOI18N
 197.194 +    public static final String spaceBeforeSynchronizedParen = "spaceBeforeSynchronizedParen"; //NOI18N
 197.195 +    public static final String spaceBeforeAnnotationParen = "spaceBeforeAnnotationParen"; //NOI18N    
 197.196 +    public static final String spaceAroundUnaryOps = "spaceAroundUnaryOps"; //NOI18N
 197.197 +    public static final String spaceAroundBinaryOps = "spaceAroundBinaryOps"; //NOI18N
 197.198 +    public static final String spaceAroundTernaryOps = "spaceAroundTernaryOps"; //NOI18N
 197.199 +    public static final String spaceAroundAssignOps = "spaceAroundAssignOps"; //NOI18N
 197.200 +    public static final String spaceBeforeClassDeclLeftBrace = "spaceBeforeClassDeclLeftBrace"; //NOI18N
 197.201 +    public static final String spaceBeforeMethodDeclLeftBrace = "spaceBeforeMethodDeclLeftBrace"; //NOI18N
 197.202 +    public static final String spaceBeforeIfLeftBrace = "spaceBeforeIfLeftBrace"; //NOI18N
 197.203 +    public static final String spaceBeforeElseLeftBrace = "spaceBeforeElseLeftBrace"; //NOI18N
 197.204 +    public static final String spaceBeforeWhileLeftBrace = "spaceBeforeWhileLeftBrace"; //NOI18N
 197.205 +    public static final String spaceBeforeForLeftBrace = "spaceBeforeForLeftBrace"; //NOI18N
 197.206 +    public static final String spaceBeforeDoLeftBrace = "spaceBeforeDoLeftBrace"; //NOI18N
 197.207 +    public static final String spaceBeforeSwitchLeftBrace = "spaceBeforeSwitchLeftBrace"; //NOI18N
 197.208 +    public static final String spaceBeforeTryLeftBrace = "spaceBeforeTryLeftBrace"; //NOI18N
 197.209 +    public static final String spaceBeforeCatchLeftBrace = "spaceBeforeCatchLeftBrace"; //NOI18N
 197.210 +    public static final String spaceBeforeFinallyLeftBrace = "spaceBeforeFinallyLeftBrace"; //NOI18N
 197.211 +    public static final String spaceBeforeSynchronizedLeftBrace = "spaceBeforeSynchronizedLeftBrace"; //NOI18N
 197.212 +    public static final String spaceBeforeStaticInitLeftBrace = "spaceBeforeStaticInitLeftBrace"; //NOI18N
 197.213 +    public static final String spaceBeforeArrayInitLeftBrace = "spaceBeforeArrayInitLeftBrace"; //NOI18N
 197.214 +    public static final String spaceWithinParens = "spaceWithinParens"; //NOI18N
 197.215 +    public static final String spaceWithinMethodDeclParens = "spaceWithinMethodDeclParens"; //NOI18N
 197.216 +    public static final String spaceWithinMethodCallParens = "spaceWithinMethodCallParens"; //NOI18N
 197.217 +    public static final String spaceWithinIfParens = "spaceWithinIfParens"; //NOI18N
 197.218 +    public static final String spaceWithinForParens = "spaceWithinForParens"; //NOI18N
 197.219 +    public static final String spaceWithinWhileParens = "spaceWithinWhileParens"; //NOI18N
 197.220 +    public static final String spaceWithinSwitchParens = "spaceWithinSwitchParens"; //NOI18N
 197.221 +    public static final String spaceWithinCatchParens = "spaceWithinCatchParens"; //NOI18N
 197.222 +    public static final String spaceWithinSynchronizedParens = "spaceWithinSynchronizedParens"; //NOI18N
 197.223 +    public static final String spaceWithinTypeCastParens = "spaceWithinTypeCastParens"; //NOI18N
 197.224 +    public static final String spaceWithinAnnotationParens = "spaceWithinAnnotationParens"; //NOI18N
 197.225 +    public static final String spaceWithinBraces = "spaceWithinBraces"; //NOI18N
 197.226 +    public static final String spaceWithinArrayInitBrackets = "spaceWithinArrayInitBrackets"; //NOI18N
 197.227 +    public static final String spaceBeforeComma = "spaceBeforeComma"; //NOI18N
 197.228 +    public static final String spaceAfterComma = "spaceAfterComma"; //NOI18N
 197.229 +    public static final String spaceBeforeSemi = "spaceBeforeSemi"; //NOI18N
 197.230 +    public static final String spaceAfterSemi = "spaceAfterSemi"; //NOI18N
 197.231 +    public static final String spaceBeforeColon = "spaceBeforeColon"; //NOI18N
 197.232 +    public static final String spaceAfterColon = "spaceAfterColon"; //NOI18N
 197.233 +    public static final String spaceAfterTypeCast = "spaceAfterTypeCast"; //NOI18N
 197.234 +     */
 197.235 +
 197.236 +    // Spaces
 197.237 +    public static final String addSpaceAroundOperators = "spaceAroundOperators"; //NOI18N
 197.238 +    public static final String removeSpaceInParens = "spaceInsideParens"; //NOI18N
 197.239 +    public static final String addSpaceAfterComma = "spaceAfterComma"; //NOI18N
 197.240 +    public static final String removeSpaceBeforeSep = "spaceBeforeSeparator"; //NOI18N
 197.241 +    public static final String removeSpaceInParamAssign = "spaceInKeywordAssign"; //NOI18N
 197.242 +    public static final String collapseSpaces = "collapseSpaces"; //NOI18N
 197.243 +    // Imports
 197.244 +    public static final String formatImports = "formatImports"; //NOI18N
 197.245 +    public static final String oneImportPerLine = "oneImportPerLine"; //NOI18N
 197.246 +    public static final String removeDuplicates = "removeDuplicates"; //NOI18N
 197.247 +    public static final String systemLibsFirst = "systemLibsFirst"; //NOI18N
 197.248 +    public static final String cleanupUnusedImports = "cleanupUnusedImports"; //NOI18N
 197.249 +    public static final String preferSymbolImports = "preferSymbolImports"; //NOI18N
 197.250 +    public static final String sortImports = "sortImports"; //NOI18N
 197.251 +    public static final String separateFromImps = "separateFromImps"; //NOI18N
 197.252 +    public static CodeStyleProducer codeStyleProducer;
 197.253 +    static final String CODE_STYLE_PROFILE = "CodeStyle"; // NOI18N
 197.254 +    static final String DEFAULT_PROFILE = "default"; // NOI18N
 197.255 +    static final String PROJECT_PROFILE = "project"; // NOI18N
 197.256 +    static final String usedProfile = "usedProfile"; // NOI18N
 197.257 +
 197.258 +    private FmtOptions() {
 197.259 +    }
 197.260 +
 197.261 +    public static int getDefaultAsInt(String key) {
 197.262 +        return Integer.parseInt(defaults.get(key));
 197.263 +    }
 197.264 +
 197.265 +    public static boolean getDefaultAsBoolean(String key) {
 197.266 +        return Boolean.parseBoolean(defaults.get(key));
 197.267 +    }
 197.268 +
 197.269 +    public static String getDefaultAsString(String key) {
 197.270 +        return defaults.get(key);
 197.271 +    }
 197.272 +
 197.273 +    public static boolean isInteger(String optionID) {
 197.274 +        String value = defaults.get(optionID);
 197.275 +
 197.276 +        try {
 197.277 +            Integer.parseInt(value);
 197.278 +            return true;
 197.279 +        } catch (NumberFormatException numberFormatException) {
 197.280 +            return false;
 197.281 +        }
 197.282 +    }
 197.283 +    // Private section ---------------------------------------------------------
 197.284 +    private static final String TRUE = "true";      // NOI18N
 197.285 +    private static final String FALSE = "false";    // NOI18N
 197.286 +    private static final String WRAP_ALWAYS = WrapStyle.WRAP_ALWAYS.name();
 197.287 +    //private static final String WRAP_IF_LONG  = WrapStyle.WRAP_IF_LONG.name();
 197.288 +    private static final String WRAP_NEVER = WrapStyle.WRAP_NEVER.name();
 197.289 +
 197.290 +    //private static final String CLEANUP_COMMENT  = ImportCleanupStyle.COMMENT_OUT.name();
 197.291 +    private static final String IMP_LEAVE_ALONE = ImportCleanupStyle.LEAVE_ALONE.name();
 197.292 +    private static Map<String, String> defaults;
 197.293 +
 197.294 +
 197.295 +    static {
 197.296 +        createDefaults();
 197.297 +    }
 197.298 +
 197.299 +    private static void createDefaults() {
 197.300 +        String defaultValues[][] = {
 197.301 +            {expandTabToSpaces, TRUE}, //NOI18N
 197.302 +            {tabSize, "4"}, //NOI18N
 197.303 +            {spacesPerTab, "4"}, //NOI18N
 197.304 +            {indentSize, "4"}, //NOI18N
 197.305 +            {continuationIndentSize, "8"}, //NOI18N
 197.306 +            {labelIndent, "0"}, //NOI18N
 197.307 +            {absoluteLabelIndent, FALSE}, //NOI18N
 197.308 +            {indentTopLevelClassMembers, TRUE}, //NOI18N
 197.309 +            {indentCasesFromSwitch, TRUE}, //NOI18N
 197.310 +            {rightMargin, "80"}, //NOI18N
 197.311 +
 197.312 +            /*
 197.313 +            { addLeadingStarInComment, TRUE}, //NOI18N
 197.314 +
 197.315 +            { preferLongerNames, TRUE}, //NOI18N
 197.316 +            { fieldNamePrefix, ""}, //NOI18N // XXX null
 197.317 +            { fieldNameSuffix, ""}, //NOI18N // XXX null
 197.318 +            { staticFieldNamePrefix, ""}, //NOI18N // XXX null
 197.319 +            { staticFieldNameSuffix, ""}, //NOI18N // XXX null
 197.320 +            { parameterNamePrefix, ""}, //NOI18N // XXX null
 197.321 +            { parameterNameSuffix, ""}, //NOI18N // XXX null
 197.322 +            { localVarNamePrefix, ""}, //NOI18N // XXX null
 197.323 +            { localVarNameSuffix, ""}, //NOI18N // XXX null
 197.324 +            { qualifyFieldAccess, FALSE}, //NOI18N // XXX
 197.325 +            { useIsForBooleanGetters, TRUE}, //NOI18N
 197.326 +            { addOverrideAnnotation, TRUE}, //NOI18N
 197.327 +            { makeLocalVarsFinal, FALSE}, //NOI18N
 197.328 +            { makeParametersFinal, FALSE}, //NOI18N
 197.329 +            { classMembersOrder, ""}, //NOI18N // XXX
 197.330 +
 197.331 +            { alignMultilineMethodParams, FALSE}, //NOI18N
 197.332 +            { alignMultilineCallArgs, FALSE}, //NOI18N
 197.333 +            { alignMultilineAnnotationArgs, FALSE}, //NOI18N
 197.334 +            { alignMultilineImplements, FALSE}, //NOI18N
 197.335 +            { alignMultilineThrows, FALSE}, //NOI18N
 197.336 +            { alignMultilineParenthesized, FALSE}, //NOI18N
 197.337 +            { alignMultilineBinaryOp, FALSE}, //NOI18N
 197.338 +            { alignMultilineTernaryOp, FALSE}, //NOI18N
 197.339 +            { alignMultilineAssignment, FALSE}, //NOI18N
 197.340 +            { alignMultilineFor, FALSE}, //NOI18N
 197.341 +            { alignMultilineArrayInit, FALSE}, //NOI18N
 197.342 +            { placeElseOnNewLine, FALSE}, //NOI18N 
 197.343 +            { placeWhileOnNewLine, FALSE}, //NOI18N
 197.344 +            { placeCatchOnNewLine, FALSE}, //NOI18N 
 197.345 +            { placeFinallyOnNewLine, FALSE}, //NOI18N 
 197.346 +            { placeNewLineAfterModifiers, FALSE}, //NOI18N
 197.347 +
 197.348 +            { wrapExtendsImplementsKeyword, WRAP_NEVER}, //NOI18N
 197.349 +            { wrapExtendsImplementsList, WRAP_NEVER}, //NOI18N
 197.350 +            { wrapMethodParams, WRAP_NEVER}, //NOI18N
 197.351 +            { wrapThrowsKeyword, WRAP_NEVER}, //NOI18N
 197.352 +            { wrapThrowsList, WRAP_NEVER}, //NOI18N
 197.353 +            { wrapMethodCallArgs, WRAP_NEVER}, //NOI18N
 197.354 +            { wrapAnnotationArgs, WRAP_NEVER}, //NOI18N
 197.355 +            { wrapChainedMethodCalls, WRAP_NEVER}, //NOI18N
 197.356 +            { wrapArrayInit, WRAP_NEVER}, //NOI18N
 197.357 +            { wrapFor, WRAP_NEVER}, //NOI18N
 197.358 +            { wrapForStatement, WRAP_ALWAYS}, //NOI18N
 197.359 +            { wrapIfStatement, WRAP_ALWAYS}, //NOI18N
 197.360 +            { wrapWhileStatement, WRAP_ALWAYS}, //NOI18N
 197.361 +            { wrapDoWhileStatement, WRAP_ALWAYS}, //NOI18N
 197.362 +            { wrapAssert, WRAP_NEVER}, //NOI18N
 197.363 +            { wrapEnumConstants, WRAP_NEVER}, //NOI18N
 197.364 +            { wrapAnnotations, WRAP_ALWAYS}, //NOI18N
 197.365 +            { wrapBinaryOps, WRAP_NEVER}, //NOI18N
 197.366 +            { wrapTernaryOps, WRAP_NEVER}, //NOI18N
 197.367 +            { wrapAssignOps, WRAP_NEVER}, //NOI18N
 197.368 +
 197.369 +            { blankLinesBeforePackage, "0"}, //NOI18N
 197.370 +            { blankLinesAfterPackage, "1"}, //NOI18N
 197.371 +            { blankLinesBeforeImports, "1"}, //NOI18N 
 197.372 +            { blankLinesAfterImports, "1"}, //NOI18N
 197.373 +            { blankLinesBeforeClass, "1"}, //NOI18N 
 197.374 +            { blankLinesAfterClass, "0"}, //NOI18N
 197.375 +            { blankLinesAfterClassHeader, "1"}, //NOI18N 
 197.376 +            { blankLinesBeforeFields, "0"}, //NOI18N 
 197.377 +            { blankLinesAfterFields, "0"}, //NOI18N
 197.378 +            { blankLinesBeforeMethods, "1"}, //NOI18N
 197.379 +            { blankLinesAfterMethods, "0"}, //NOI18N
 197.380 +
 197.381 +            { spaceBeforeWhile, TRUE}, //NOI18N // XXX
 197.382 +            { spaceBeforeElse, TRUE}, //NOI18N // XXX
 197.383 +            { spaceBeforeCatch, TRUE}, //NOI18N // XXX
 197.384 +            { spaceBeforeFinally, TRUE}, //NOI18N // XXX
 197.385 +            { spaceBeforeMethodDeclParen, FALSE}, //NOI18N
 197.386 +            { spaceBeforeMethodCallParen, FALSE}, //NOI18N
 197.387 +            { spaceBeforeIfParen, TRUE}, //NOI18N
 197.388 +            { spaceBeforeForParen, TRUE}, //NOI18N
 197.389 +            { spaceBeforeWhileParen, TRUE}, //NOI18N
 197.390 +            { spaceBeforeCatchParen, TRUE}, //NOI18N
 197.391 +            { spaceBeforeSwitchParen, TRUE}, //NOI18N
 197.392 +            { spaceBeforeSynchronizedParen, TRUE}, //NOI18N
 197.393 +            { spaceBeforeAnnotationParen, FALSE}, //NOI18N    
 197.394 +            { spaceAroundUnaryOps, FALSE}, //NOI18N
 197.395 +            { spaceAroundBinaryOps, TRUE}, //NOI18N
 197.396 +            { spaceAroundTernaryOps, TRUE}, //NOI18N
 197.397 +            { spaceAroundAssignOps, TRUE}, //NOI18N
 197.398 +            { spaceBeforeClassDeclLeftBrace, TRUE}, //NOI18N
 197.399 +            { spaceBeforeMethodDeclLeftBrace, TRUE}, //NOI18N
 197.400 +            { spaceBeforeIfLeftBrace, TRUE}, //NOI18N
 197.401 +            { spaceBeforeElseLeftBrace, TRUE}, //NOI18N
 197.402 +            { spaceBeforeWhileLeftBrace, TRUE}, //NOI18N
 197.403 +            { spaceBeforeForLeftBrace, TRUE}, //NOI18N
 197.404 +            { spaceBeforeDoLeftBrace, TRUE}, //NOI18N
 197.405 +            { spaceBeforeSwitchLeftBrace, TRUE}, //NOI18N
 197.406 +            { spaceBeforeTryLeftBrace, TRUE}, //NOI18N
 197.407 +            { spaceBeforeCatchLeftBrace, TRUE}, //NOI18N
 197.408 +            { spaceBeforeFinallyLeftBrace, TRUE}, //NOI18N
 197.409 +            { spaceBeforeSynchronizedLeftBrace, TRUE}, //NOI18N
 197.410 +            { spaceBeforeStaticInitLeftBrace, TRUE}, //NOI18N
 197.411 +            { spaceBeforeArrayInitLeftBrace, FALSE}, //NOI18N
 197.412 +            { spaceWithinParens, FALSE}, //NOI18N
 197.413 +            { spaceWithinMethodDeclParens, FALSE}, //NOI18N
 197.414 +            { spaceWithinMethodCallParens, FALSE}, //NOI18N
 197.415 +            { spaceWithinIfParens, FALSE}, //NOI18N
 197.416 +            { spaceWithinForParens, FALSE}, //NOI18N
 197.417 +            { spaceWithinWhileParens, FALSE}, //NOI18N
 197.418 +            { spaceWithinSwitchParens, FALSE}, //NOI18N
 197.419 +            { spaceWithinCatchParens, FALSE}, //NOI18N
 197.420 +            { spaceWithinSynchronizedParens, FALSE}, //NOI18N
 197.421 +            { spaceWithinTypeCastParens, FALSE}, //NOI18N
 197.422 +            { spaceWithinAnnotationParens, FALSE}, //NOI18N
 197.423 +            { spaceWithinBraces, FALSE}, //NOI18N
 197.424 +            { spaceWithinArrayInitBrackets, FALSE}, //NOI18N
 197.425 +            { spaceBeforeComma, FALSE}, //NOI18N
 197.426 +            { spaceAfterComma, TRUE}, //NOI18N
 197.427 +            { spaceBeforeSemi, FALSE}, //NOI18N
 197.428 +            { spaceAfterSemi, TRUE}, //NOI18N
 197.429 +            { spaceBeforeColon, TRUE}, //NOI18N
 197.430 +            { spaceAfterColon, TRUE}, //NOI18N
 197.431 +            { spaceAfterTypeCast, TRUE}, //NOI18N
 197.432 +             */
 197.433 +            // Spaces
 197.434 +            {addSpaceAroundOperators, TRUE},
 197.435 +            {removeSpaceInParens, TRUE},
 197.436 +            {addSpaceAfterComma, TRUE},
 197.437 +            {removeSpaceBeforeSep, TRUE},
 197.438 +            {removeSpaceInParamAssign, TRUE},
 197.439 +            {collapseSpaces, TRUE},
 197.440 +            // Imports
 197.441 +            {formatImports, TRUE},
 197.442 +            {oneImportPerLine, TRUE},
 197.443 +            {removeDuplicates, TRUE},
 197.444 +            {systemLibsFirst, TRUE},
 197.445 +            {preferSymbolImports, TRUE},
 197.446 +            {sortImports, TRUE},
 197.447 +            {cleanupUnusedImports, IMP_LEAVE_ALONE},
 197.448 +            {separateFromImps, FALSE},};
 197.449 +
 197.450 +        defaults = new HashMap<>();
 197.451 +
 197.452 +        for (java.lang.String[] strings : defaultValues) {
 197.453 +            defaults.put(strings[0], strings[1]);
 197.454 +        }
 197.455 +
 197.456 +    }
 197.457 +
 197.458 +    // Support section ---------------------------------------------------------
 197.459 +    public static class CategorySupport implements ActionListener, DocumentListener, PreviewProvider, PreferencesCustomizer {
 197.460 +        public static final String OPTION_ID = "org.netbeans.modules.python.editor.options.FormatingOptions.ID";
 197.461 +        private static final int LOAD = 0;
 197.462 +        private static final int STORE = 1;
 197.463 +        private static final int ADD_LISTENERS = 2;
 197.464 +        private static final ComboItem wrap[] = new ComboItem[]{
 197.465 +            new ComboItem(WrapStyle.WRAP_ALWAYS.name(), "LBL_wrp_WRAP_ALWAYS"), // NOI18N
 197.466 +            new ComboItem(WrapStyle.WRAP_IF_LONG.name(), "LBL_wrp_WRAP_IF_LONG"), // NOI18N
 197.467 +            new ComboItem(WrapStyle.WRAP_NEVER.name(), "LBL_wrp_WRAP_NEVER") // NOI18N
 197.468 +        };
 197.469 +        private static final ComboItem cleanupImports[] = new ComboItem[]{
 197.470 +            new ComboItem(ImportCleanupStyle.LEAVE_ALONE.name(), "LBL_imp_LEAVE_ALONE"), // NOI18N
 197.471 +            new ComboItem(ImportCleanupStyle.COMMENT_OUT.name(), "LBL_imp_COMMENT_OUT"), // NOI18N
 197.472 +            new ComboItem(ImportCleanupStyle.DELETE.name(), "LBL_imp_DELETE") // NOI18N
 197.473 +        };
 197.474 +        private final String previewText;
 197.475 +        private final String id;
 197.476 +        protected final JPanel panel;
 197.477 +        private final List<JComponent> components = new LinkedList<>();
 197.478 +        private JEditorPane previewPane;
 197.479 +        private final Preferences preferences;
 197.480 +        private final Preferences previewPrefs;
 197.481 +
 197.482 +        protected CategorySupport(Preferences preferences, String id, JPanel panel, String previewText, String[]... forcedOptions) {
 197.483 +            this.preferences = preferences;
 197.484 +            this.id = id;
 197.485 +            this.panel = panel;
 197.486 +            this.previewText = previewText != null ? previewText : NbBundle.getMessage(FmtOptions.class, "SAMPLE_Default"); //NOI18N
 197.487 +
 197.488 +            // Scan the panel for its components
 197.489 +            scan(panel, components);
 197.490 +
 197.491 +            // Initialize the preview preferences
 197.492 +            Preferences forcedPrefs = new PreviewPreferences();
 197.493 +            for (String[] option : forcedOptions) {
 197.494 +                forcedPrefs.put(option[0], option[1]);
 197.495 +            }
 197.496 +            this.previewPrefs = new ProxyPreferences(preferences, forcedPrefs);
 197.497 +
 197.498 +            // Load and hook up all the components
 197.499 +            loadFrom(preferences);
 197.500 +            addListeners();
 197.501 +        }
 197.502 +
 197.503 +        protected void addListeners() {
 197.504 +            scan(ADD_LISTENERS, null);
 197.505 +        }
 197.506 +
 197.507 +        protected void loadFrom(Preferences preferences) {
 197.508 +//            loaded = true;
 197.509 +            scan(LOAD, preferences);
 197.510 +//            loaded = false;
 197.511 +        }
 197.512 +//
 197.513 +//        public void applyChanges() {
 197.514 +//            storeTo(preferences);
 197.515 +//        }
 197.516 +//
 197.517 +
 197.518 +        protected void storeTo(Preferences p) {
 197.519 +            scan(STORE, p);
 197.520 +        }
 197.521 +
 197.522 +        protected void notifyChanged() {
 197.523 +//            if (loaded)
 197.524 +//                return;
 197.525 +            storeTo(preferences);
 197.526 +            refreshPreview();
 197.527 +        }
 197.528 +
 197.529 +        // ActionListener implementation ---------------------------------------
 197.530 +        @Override
 197.531 +        public void actionPerformed(ActionEvent e) {
 197.532 +            notifyChanged();
 197.533 +        }
 197.534 +
 197.535 +        // DocumentListener implementation -------------------------------------
 197.536 +        @Override
 197.537 +        public void insertUpdate(DocumentEvent e) {
 197.538 +            notifyChanged();
 197.539 +        }
 197.540 +
 197.541 +        @Override
 197.542 +        public void removeUpdate(DocumentEvent e) {
 197.543 +            notifyChanged();
 197.544 +        }
 197.545 +
 197.546 +        @Override
 197.547 +        public void changedUpdate(DocumentEvent e) {
 197.548 +            notifyChanged();
 197.549 +        }
 197.550 +
 197.551 +        // PreviewProvider methods -----------------------------------------------------
 197.552 +        @Override
 197.553 +        public JComponent getPreviewComponent() {
 197.554 +            if (previewPane == null) {
 197.555 +                previewPane = new JEditorPane();
 197.556 +                previewPane.getAccessibleContext().setAccessibleName(NbBundle.getMessage(FmtOptions.class, "AN_Preview")); //NOI18N
 197.557 +                previewPane.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(FmtOptions.class, "AD_Preview")); //NOI18N
 197.558 +                previewPane.putClientProperty("HighlightsLayerIncludes", "^org\\.netbeans\\.modules\\.editor\\.lib2\\.highlighting\\.SyntaxHighlighting$"); //NOI18N
 197.559 +                previewPane.setEditorKit(CloneableEditorSupport.getEditorKit(PythonMIMEResolver.PYTHON_MIME_TYPE));
 197.560 +                previewPane.setEditable(false);
 197.561 +            }
 197.562 +            return previewPane;
 197.563 +        }
 197.564 +
 197.565 +        @Override
 197.566 +        public void refreshPreview() {
 197.567 +            JEditorPane jep = (JEditorPane)getPreviewComponent();
 197.568 +            try {
 197.569 +                int rm = previewPrefs.getInt(rightMargin, getDefaultAsInt(rightMargin));
 197.570 +                jep.putClientProperty("TextLimitLine", rm); //NOI18N
 197.571 +            } catch (NumberFormatException e) {
 197.572 +                // Ignore it
 197.573 +            }
 197.574 +            try {
 197.575 +                Class.forName(CodeStyle.class.getName(), true, CodeStyle.class.getClassLoader());
 197.576 +            } catch (ClassNotFoundException cnfe) {
 197.577 +                // ignore
 197.578 +            }
 197.579 +
 197.580 +            CodeStyle codeStyle = codeStyleProducer.create(previewPrefs);
 197.581 +            jep.setIgnoreRepaint(true);
 197.582 +
 197.583 +//            if (jep.getDocument() instanceof BaseDocument) {
 197.584 +//                BaseDocument document = (BaseDocument) jep.getDocument();
 197.585 +//                final org.netbeans.editor.Formatter f = document.getFormatter();
 197.586 +//                try {
 197.587 +//                    f.reformatLock();
 197.588 +//                    try {
 197.589 +//                        int reformattedLen = f.reformat(document, 0, document.getLength());
 197.590 +//                    } catch (BadLocationException ex) {
 197.591 +//                        Exceptions.printStackTrace(ex);
 197.592 +//                    }
 197.593 +//                } finally {
 197.594 +//                    f.reformatUnlock();
 197.595 +//                }
 197.596 +//            }
 197.597 +
 197.598 +            // Hacky code to do preview: We want to preview blank text without
 197.599 +            // a data object... this doesn't work very well so requires some hacks
 197.600 +            // to create a temp file, format it, then save it and delete it
 197.601 +            // (to avoid save confirmation dialogs on the modified file etc)
 197.602 +            PythonFormatter formatter = new PythonFormatter(codeStyle);
 197.603 +            PythonParserResult info = null;
 197.604 +            File tmp = null;
 197.605 +            FileObject tmpFo = null;
 197.606 +            if (formatter.needsParserResult()) {
 197.607 +                try {
 197.608 +                    tmp = File.createTempFile("preview", ".py"); // NOI18N
 197.609 +                    BufferedWriter writer = new BufferedWriter(new FileWriter(tmp));
 197.610 +                    writer.write(previewText);
 197.611 +                    writer.close();
 197.612 +                    final FileObject fo = FileUtil.toFileObject(FileUtil.normalizeFile(tmp));
 197.613 +                    tmpFo = fo;
 197.614 +                    // TODO - I need to get the classpath involved here such that it can
 197.615 +                    // find used/unused libraries
 197.616 +//                    if (!SourceUtils.isScanInProgress()) {
 197.617 +//                        // I'm using custom GSF code here because I want to set up an explicit
 197.618 +//                        // source path for the fake file object which includes the Python
 197.619 +//                        // libraries (since we need them for the isSystemModule lookup
 197.620 +//                        //SourceModel model = SourceModelFactory.getInstance().getModel(fo);
 197.621 +//                        //if (model != null && !model.isScanInProgress()) {
 197.622 +//                        List<FileObject> roots = new ArrayList<FileObject>(new PythonLanguage().getCoreLibraries());
 197.623 +//
 197.624 +//                        final PythonPlatformManager manager = PythonPlatformManager.getInstance();
 197.625 +//                        final String platformName = manager.getDefaultPlatform();
 197.626 +//                        PythonPlatform activePlatform = manager.getPlatform(platformName);
 197.627 +//                        if (activePlatform != null) {
 197.628 +//                            roots.addAll(activePlatform.getUniqueLibraryRoots());
 197.629 +//                            ClassPath boot = ClassPathSupport.createClassPath(roots.toArray(new FileObject[roots.size()]));
 197.630 +//                            ClassPath source = ClassPathSupport.createClassPath(new FileObject[]{fo.getParent()});
 197.631 +//                            ClassPath compile = source;
 197.632 +//
 197.633 +//                            ClasspathInfo cpInfo = ClasspathInfo.create(boot, compile, source);
 197.634 +//                            Source model = Source.create(cpInfo, fo);
 197.635 +//                            if (model != null) {
 197.636 +//                                final CompilationInfo[] infoHolder = new CompilationInfo[1];
 197.637 +//                                //model.runUserActionTask(new CancellableTask<CompilationInfo>() {
 197.638 +//                                model.runUserActionTask(new CancellableTask<CompilationController>() {
 197.639 +//                                    public void cancel() {
 197.640 +//                                    }
 197.641 +//
 197.642 +//                                    //public void run(CompilationInfo info) throws Exception {
 197.643 +//                                    public void run(CompilationController info) throws Exception {
 197.644 +//                                        info.toPhase(Phase.RESOLVED);
 197.645 +//                                        infoHolder[0] = info;
 197.646 +//                                        // Force open so info.getFileObject will succeed
 197.647 +//                                        GsfUtilities.getDocument(fo, true);
 197.648 +//                                    }
 197.649 +//                                }, false);
 197.650 +//                                info = infoHolder[0];
 197.651 +//                            }
 197.652 +//                        }
 197.653 +//                    }
 197.654 +                } catch (IOException ex) {
 197.655 +                    Exceptions.printStackTrace(ex);
 197.656 +                }
 197.657 +            }
 197.658 +            try {
 197.659 +                if (info != null && info.getSnapshot().getSource().getDocument(false) != null) {
 197.660 +                    Document doc = info.getSnapshot().getSource().getDocument(false);
 197.661 +                    formatter.reformat(null, doc, 0, doc.getLength(), info);
 197.662 +                    jep.setText(doc.getText(0, doc.getLength()));
 197.663 +                    // Save file to avoid warning on exit
 197.664 +                    DataObject dobj = DataObject.find(info.getSnapshot().getSource().getFileObject());
 197.665 +                    SaveCookie cookie = dobj.getCookie(SaveCookie.class);
 197.666 +                    if (cookie != null) {
 197.667 +                        cookie.save();
 197.668 +                    }
 197.669 +                } else {
 197.670 +                    Document doc = jep.getDocument();
 197.671 +                    if (doc.getLength() > 0) {
 197.672 +                        doc.remove(0, doc.getLength());
 197.673 +                    }
 197.674 +                    doc.insertString(0, previewText, null);
 197.675 +                    formatter.reformat(null, doc, 0, doc.getLength(), null);
 197.676 +                    jep.setText(doc.getText(0, doc.getLength()));
 197.677 +                }
 197.678 +            } catch (DataObjectNotFoundException dof) {
 197.679 +                Exceptions.printStackTrace(dof);
 197.680 +            } catch (IOException | BadLocationException ioe) {
 197.681 +                Exceptions.printStackTrace(ioe);
 197.682 +            }
 197.683 +
 197.684 +            if (tmpFo != null) {
 197.685 +                try {
 197.686 +                    tmpFo.delete();
 197.687 +                } catch (IOException ex) {
 197.688 +                    Exceptions.printStackTrace(ex);
 197.689 +                }
 197.690 +            } else if (tmp != null) {
 197.691 +                tmp.delete();
 197.692 +            }
 197.693 +
 197.694 +
 197.695 +            jep.setIgnoreRepaint(false);
 197.696 +            jep.scrollRectToVisible(new Rectangle(0, 0, 10, 10));
 197.697 +            jep.repaint(100);
 197.698 +        }
 197.699 +
 197.700 +        // PreferencesCustomizer implementation --------------------------------
 197.701 +        @Override
 197.702 +        public JComponent getComponent() {
 197.703 +            return panel;
 197.704 +        }
 197.705 +
 197.706 +        @Override
 197.707 +        public String getDisplayName() {
 197.708 +            return panel.getName();
 197.709 +        }
 197.710 +
 197.711 +        @Override
 197.712 +        public String getId() {
 197.713 +            return id;
 197.714 +        }
 197.715 +
 197.716 +        @Override
 197.717 +        public HelpCtx getHelpCtx() {
 197.718 +            return null;
 197.719 +        }
 197.720 +
 197.721 +        // PreferencesCustomizer.Factory implementation ------------------------
 197.722 +        public static final class Factory implements PreferencesCustomizer.Factory {
 197.723 +            private final String id;
 197.724 +            private final Class<? extends JPanel> panelClass;
 197.725 +            private final String previewText;
 197.726 +            private final String[][] forcedOptions;
 197.727 +
 197.728 +            public Factory(String id, Class<? extends JPanel> panelClass, String previewText, String[]... forcedOptions) {
 197.729 +                this.id = id;
 197.730 +                this.panelClass = panelClass;
 197.731 +                this.previewText = previewText;
 197.732 +                this.forcedOptions = forcedOptions;
 197.733 +            }
 197.734 +
 197.735 +            @Override
 197.736 +            public PreferencesCustomizer create(Preferences preferences) {
 197.737 +                try {
 197.738 +                    return new CategorySupport(preferences, id, panelClass.newInstance(), previewText, forcedOptions);
 197.739 +                } catch (IllegalAccessException | InstantiationException e) {
 197.740 +                    return null;
 197.741 +                }
 197.742 +            }
 197.743 +        } // End of CategorySupport.Factory class
 197.744 +
 197.745 +        // Private methods -----------------------------------------------------
 197.746 +        private void performOperation(int operation, JComponent jc, String optionID, Preferences p) {
 197.747 +            switch (operation) {
 197.748 +            case LOAD:
 197.749 +                loadData(jc, optionID, p);
 197.750 +                break;
 197.751 +            case STORE:
 197.752 +                storeData(jc, optionID, p);
 197.753 +                break;
 197.754 +            case ADD_LISTENERS:
 197.755 +                addListener(jc);
 197.756 +                break;
 197.757 +            }
 197.758 +        }
 197.759 +
 197.760 +        private void scan(int what, Preferences p) {
 197.761 +            for (JComponent jc : components) {
 197.762 +                Object o = jc.getClientProperty(OPTION_ID);
 197.763 +                if (o instanceof String) {
 197.764 +                    performOperation(what, jc, (String)o, p);
 197.765 +                } else if (o instanceof String[]) {
 197.766 +                    for (String oid : (String[])o) {
 197.767 +                        performOperation(what, jc, oid, p);
 197.768 +                    }
 197.769 +                }
 197.770 +            }
 197.771 +        }
 197.772 +
 197.773 +        private void scan(Container container, List<JComponent> components) {
 197.774 +            for (Component c : container.getComponents()) {
 197.775 +                if (c instanceof JComponent) {
 197.776 +                    JComponent jc = (JComponent)c;
 197.777 +                    Object o = jc.getClientProperty(OPTION_ID);
 197.778 +                    if (o instanceof String || o instanceof String[]) {
 197.779 +                        components.add(jc);
 197.780 +                    }
 197.781 +                }
 197.782 +                if (c instanceof Container) {
 197.783 +                    scan((Container)c, components);
 197.784 +                }
 197.785 +            }
 197.786 +        }
 197.787 +
 197.788 +        /** Very smart method which tries to set the values in the components correctly
 197.789 +         */
 197.790 +        private void loadData(JComponent jc, String optionID, Preferences node) {
 197.791 +
 197.792 +            if (jc instanceof JTextField) {
 197.793 +                JTextField field = (JTextField)jc;
 197.794 +                field.setText(node.get(optionID, getDefaultAsString(optionID)));
 197.795 +            } else if (jc instanceof JCheckBox) {
 197.796 +                JCheckBox checkBox = (JCheckBox)jc;
 197.797 +                boolean df = getDefaultAsBoolean(optionID);
 197.798 +                checkBox.setSelected(node.getBoolean(optionID, df));
 197.799 +            } else if (jc instanceof JComboBox) {
 197.800 +                JComboBox cb = (JComboBox)jc;
 197.801 +                String value = node.get(optionID, getDefaultAsString(optionID));
 197.802 +                ComboBoxModel model = createModel(value);
 197.803 +                cb.setModel(model);
 197.804 +                ComboItem item = whichItem(value, model);
 197.805 +                cb.setSelectedItem(item);
 197.806 +            }
 197.807 +
 197.808 +        }
 197.809 +
 197.810 +        private void storeData(JComponent jc, String optionID, Preferences node) {
 197.811 +
 197.812 +            if (jc instanceof JTextField) {
 197.813 +                JTextField field = (JTextField)jc;
 197.814 +
 197.815 +                String text = field.getText();
 197.816 +
 197.817 +                // XXX test for numbers
 197.818 +                if (isInteger(optionID)) {
 197.819 +                    try {
 197.820 +                        int i = Integer.parseInt(text);
 197.821 +                    } catch (NumberFormatException e) {
 197.822 +                        return;
 197.823 +                    }
 197.824 +                }
 197.825 +
 197.826 +                // XXX: watch out, tabSize, spacesPerTab, indentSize and expandTabToSpaces
 197.827 +                // fall back on getGlopalXXX() values and not getDefaultAsXXX value,
 197.828 +                // which is why we must not remove them. Proper solution would be to
 197.829 +                // store formatting preferences to MimeLookup and not use NbPreferences.
 197.830 +                // The problem currently is that MimeLookup based Preferences do not support subnodes.
 197.831 +                if (!optionID.equals(tabSize) &&
 197.832 +                        !optionID.equals(spacesPerTab) && !optionID.equals(indentSize) &&
 197.833 +                        getDefaultAsString(optionID).equals(text)) {
 197.834 +                    node.remove(optionID);
 197.835 +                } else {
 197.836 +                    node.put(optionID, text);
 197.837 +                }
 197.838 +            } else if (jc instanceof JCheckBox) {
 197.839 +                JCheckBox checkBox = (JCheckBox)jc;
 197.840 +                if (!optionID.equals(expandTabToSpaces) && getDefaultAsBoolean(optionID) == checkBox.isSelected()) {
 197.841 +                    node.remove(optionID);
 197.842 +                } else {
 197.843 +                    node.putBoolean(optionID, checkBox.isSelected());
 197.844 +                }
 197.845 +            } else if (jc instanceof JComboBox) {
 197.846 +                JComboBox cb = (JComboBox)jc;
 197.847 +                // Logger.global.info( cb.getSelectedItem() + " " + optionID);
 197.848 +                String value = ((ComboItem)cb.getSelectedItem()).value;
 197.849 +                if (getDefaultAsString(optionID).equals(value)) {
 197.850 +                    node.remove(optionID);
 197.851 +                } else {
 197.852 +                    node.put(optionID, value);
 197.853 +                }
 197.854 +            }
 197.855 +        }
 197.856 +
 197.857 +        private void addListener(JComponent jc) {
 197.858 +            if (jc instanceof JTextField) {
 197.859 +                JTextField field = (JTextField)jc;
 197.860 +                field.addActionListener(this);
 197.861 +                field.getDocument().addDocumentListener(this);
 197.862 +            } else if (jc instanceof JCheckBox) {
 197.863 +                JCheckBox checkBox = (JCheckBox)jc;
 197.864 +                checkBox.addActionListener(this);
 197.865 +            } else if (jc instanceof JComboBox) {
 197.866 +                JComboBox cb = (JComboBox)jc;
 197.867 +                cb.addActionListener(this);
 197.868 +            }
 197.869 +        }
 197.870 +
 197.871 +        private ComboBoxModel createModel(String value) {
 197.872 +
 197.873 +            // is it imports?
 197.874 +            for (ComboItem comboItem : cleanupImports) {
 197.875 +                if (value.equals(comboItem.value)) {
 197.876 +                    return new DefaultComboBoxModel(cleanupImports);
 197.877 +                }
 197.878 +            }
 197.879 +
 197.880 +            // is it wrap
 197.881 +            for (ComboItem comboItem : wrap) {
 197.882 +                if (value.equals(comboItem.value)) {
 197.883 +                    return new DefaultComboBoxModel(wrap);
 197.884 +                }
 197.885 +            }
 197.886 +
 197.887 +            return null;
 197.888 +        }
 197.889 +
 197.890 +        private static ComboItem whichItem(String value, ComboBoxModel model) {
 197.891 +
 197.892 +            for (int i = 0; i < model.getSize(); i++) {
 197.893 +                ComboItem item = (ComboItem)model.getElementAt(i);
 197.894 +                if (value.equals(item.value)) {
 197.895 +                    return item;
 197.896 +                }
 197.897 +            }
 197.898 +            return null;
 197.899 +        }
 197.900 +
 197.901 +        private static class ComboItem {
 197.902 +            String value;
 197.903 +            String displayName;
 197.904 +
 197.905 +            public ComboItem(String value, String key) {
 197.906 +                this.value = value;
 197.907 +                this.displayName = NbBundle.getMessage(FmtOptions.class, key);
 197.908 +            }
 197.909 +
 197.910 +            @Override
 197.911 +            public String toString() {
 197.912 +                return displayName;
 197.913 +            }
 197.914 +        }
 197.915 +    }
 197.916 +
 197.917 +    public static class PreviewPreferences extends AbstractPreferences {
 197.918 +        private Map<String, Object> map = new HashMap<>();
 197.919 +
 197.920 +        public PreviewPreferences() {
 197.921 +            super(null, ""); // NOI18N
 197.922 +        }
 197.923 +
 197.924 +        @Override
 197.925 +        protected void putSpi(String key, String value) {
 197.926 +            map.put(key, value);
 197.927 +        }
 197.928 +
 197.929 +        @Override
 197.930 +        protected String getSpi(String key) {
 197.931 +            return (String)map.get(key);
 197.932 +        }
 197.933 +
 197.934 +        @Override
 197.935 +        protected void removeSpi(String key) {
 197.936 +            map.remove(key);
 197.937 +        }
 197.938 +
 197.939 +        @Override
 197.940 +        protected void removeNodeSpi() throws BackingStoreException {
 197.941 +            throw new UnsupportedOperationException("Not supported yet.");
 197.942 +        }
 197.943 +
 197.944 +        @Override
 197.945 +        protected String[] keysSpi() throws BackingStoreException {
 197.946 +            String array[] = new String[map.keySet().size()];
 197.947 +            return map.keySet().toArray(array);
 197.948 +        }
 197.949 +
 197.950 +        @Override
 197.951 +        protected String[] childrenNamesSpi() throws BackingStoreException {
 197.952 +            throw new UnsupportedOperationException("Not supported yet.");
 197.953 +        }
 197.954 +
 197.955 +        @Override
 197.956 +        protected AbstractPreferences childSpi(String name) {
 197.957 +            throw new UnsupportedOperationException("Not supported yet.");
 197.958 +        }
 197.959 +
 197.960 +        @Override
 197.961 +        protected void syncSpi() throws BackingStoreException {
 197.962 +            throw new UnsupportedOperationException("Not supported yet.");
 197.963 +        }
 197.964 +
 197.965 +        @Override
 197.966 +        protected void flushSpi() throws BackingStoreException {
 197.967 +            throw new UnsupportedOperationException("Not supported yet.");
 197.968 +        }
 197.969 +    }
 197.970 +
 197.971 +    // read-only, no subnodes
 197.972 +    public static final class ProxyPreferences extends AbstractPreferences {
 197.973 +        private final Preferences[] delegates;
 197.974 +
 197.975 +        public ProxyPreferences(Preferences... delegates) {
 197.976 +            super(null, ""); // NOI18N
 197.977 +            this.delegates = delegates;
 197.978 +        }
 197.979 +
 197.980 +        @Override
 197.981 +        protected void putSpi(String key, String value) {
 197.982 +            throw new UnsupportedOperationException("Not supported yet.");
 197.983 +        }
 197.984 +
 197.985 +        @Override
 197.986 +        protected String getSpi(String key) {
 197.987 +            for (Preferences p : delegates) {
 197.988 +                String value = p.get(key, null);
 197.989 +                if (value != null) {
 197.990 +                    return value;
 197.991 +                }
 197.992 +            }
 197.993 +            return null;
 197.994 +        }
 197.995 +
 197.996 +        @Override
 197.997 +        protected void removeSpi(String key) {
 197.998 +            throw new UnsupportedOperationException("Not supported yet.");
 197.999 +        }
197.1000 +
197.1001 +        @Override
197.1002 +        protected void removeNodeSpi() throws BackingStoreException {
197.1003 +            throw new UnsupportedOperationException("Not supported yet.");
197.1004 +        }
197.1005 +
197.1006 +        @Override
197.1007 +        protected String[] keysSpi() throws BackingStoreException {
197.1008 +            Set<String> keys = new HashSet<>();
197.1009 +            for (Preferences p : delegates) {
197.1010 +                keys.addAll(Arrays.asList(p.keys()));
197.1011 +            }
197.1012 +            return keys.toArray(new String[keys.size()]);
197.1013 +        }
197.1014 +
197.1015 +        @Override
197.1016 +        protected String[] childrenNamesSpi() throws BackingStoreException {
197.1017 +            throw new UnsupportedOperationException("Not supported yet.");
197.1018 +        }
197.1019 +
197.1020 +        @Override
197.1021 +        protected AbstractPreferences childSpi(String name) {
197.1022 +            throw new UnsupportedOperationException("Not supported yet.");
197.1023 +        }
197.1024 +
197.1025 +        @Override
197.1026 +        protected void syncSpi() throws BackingStoreException {
197.1027 +            throw new UnsupportedOperationException("Not supported yet.");
197.1028 +        }
197.1029 +
197.1030 +        @Override
197.1031 +        protected void flushSpi() throws BackingStoreException {
197.1032 +            throw new UnsupportedOperationException("Not supported yet.");
197.1033 +        }
197.1034 +    } // End of ProxyPreferences class
197.1035 +
197.1036 +    public static interface CodeStyleProducer {
197.1037 +        public CodeStyle create(Preferences preferences);
197.1038 +    }
197.1039 +}
   198.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   198.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtSpaces.form	Mon Sep 21 13:01:16 2015 +0200
   198.3 @@ -0,0 +1,104 @@
   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_Spaces" 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="1"/>
  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 +  </AuxValues>
  198.24 +
  198.25 +  <Layout>
  198.26 +    <DimensionLayout dim="0">
  198.27 +      <Group type="103" groupAlignment="0" attributes="0">
  198.28 +          <Group type="102" attributes="0">
  198.29 +              <Group type="103" groupAlignment="0" attributes="0">
  198.30 +                  <Component id="addAroundOp" alignment="0" min="-2" max="-2" attributes="0"/>
  198.31 +                  <Group type="102" alignment="0" attributes="0">
  198.32 +                      <EmptySpace min="27" pref="27" max="27" attributes="0"/>
  198.33 +                      <Component id="removeInParam" min="-2" max="-2" attributes="0"/>
  198.34 +                  </Group>
  198.35 +                  <Component id="removeInParen" alignment="0" min="-2" max="-2" attributes="0"/>
  198.36 +                  <Component id="addAfterComma" alignment="0" min="-2" max="-2" attributes="0"/>
  198.37 +                  <Component id="removeBeforeSep" alignment="0" min="-2" max="-2" attributes="0"/>
  198.38 +                  <Component id="collapseSpacesCb" alignment="0" min="-2" max="-2" attributes="0"/>
  198.39 +              </Group>
  198.40 +              <EmptySpace max="32767" attributes="0"/>
  198.41 +          </Group>
  198.42 +      </Group>
  198.43 +    </DimensionLayout>
  198.44 +    <DimensionLayout dim="1">
  198.45 +      <Group type="103" groupAlignment="0" attributes="0">
  198.46 +          <Group type="102" alignment="0" attributes="0">
  198.47 +              <Component id="addAroundOp" min="-2" max="-2" attributes="0"/>
  198.48 +              <EmptySpace max="-2" attributes="0"/>
  198.49 +              <Component id="removeInParam" min="-2" max="-2" attributes="0"/>
  198.50 +              <EmptySpace max="-2" attributes="0"/>
  198.51 +              <Component id="removeInParen" min="-2" max="-2" attributes="0"/>
  198.52 +              <EmptySpace max="-2" attributes="0"/>
  198.53 +              <Component id="addAfterComma" min="-2" max="-2" attributes="0"/>
  198.54 +              <EmptySpace max="-2" attributes="0"/>
  198.55 +              <Component id="removeBeforeSep" min="-2" max="-2" attributes="0"/>
  198.56 +              <EmptySpace max="-2" attributes="0"/>
  198.57 +              <Component id="collapseSpacesCb" min="-2" max="-2" attributes="0"/>
  198.58 +              <EmptySpace max="32767" attributes="0"/>
  198.59 +          </Group>
  198.60 +      </Group>
  198.61 +    </DimensionLayout>
  198.62 +  </Layout>
  198.63 +  <SubComponents>
  198.64 +    <Component class="javax.swing.JCheckBox" name="addAroundOp">
  198.65 +      <Properties>
  198.66 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  198.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;)"/>
  198.68 +        </Property>
  198.69 +      </Properties>
  198.70 +    </Component>
  198.71 +    <Component class="javax.swing.JCheckBox" name="removeInParam">
  198.72 +      <Properties>
  198.73 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  198.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;)"/>
  198.75 +        </Property>
  198.76 +      </Properties>
  198.77 +    </Component>
  198.78 +    <Component class="javax.swing.JCheckBox" name="removeInParen">
  198.79 +      <Properties>
  198.80 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  198.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;)"/>
  198.82 +        </Property>
  198.83 +      </Properties>
  198.84 +    </Component>
  198.85 +    <Component class="javax.swing.JCheckBox" name="addAfterComma">
  198.86 +      <Properties>
  198.87 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  198.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;)"/>
  198.89 +        </Property>
  198.90 +      </Properties>
  198.91 +    </Component>
  198.92 +    <Component class="javax.swing.JCheckBox" name="removeBeforeSep">
  198.93 +      <Properties>
  198.94 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  198.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;)"/>
  198.96 +        </Property>
  198.97 +      </Properties>
  198.98 +    </Component>
  198.99 +    <Component class="javax.swing.JCheckBox" name="collapseSpacesCb">
 198.100 +      <Properties>
 198.101 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 198.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;)"/>
 198.103 +        </Property>
 198.104 +      </Properties>
 198.105 +    </Component>
 198.106 +  </SubComponents>
 198.107 +</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/FmtSpaces.java	Mon Sep 21 13:01:16 2015 +0200
   199.3 @@ -0,0 +1,143 @@
   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 javax.swing.JPanel;
  199.51 +import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
  199.52 +import static org.netbeans.modules.python.source.ui.FmtOptions.*;
  199.53 +import static org.netbeans.modules.python.source.ui.FmtOptions.CategorySupport.OPTION_ID;
  199.54 +
  199.55 +/**
  199.56 + * Preferences for formatting related to spaces
  199.57 + * 
  199.58 + * @author  Tor Norbye
  199.59 + */
  199.60 +public class FmtSpaces extends JPanel {
  199.61 +    public FmtSpaces() {
  199.62 +        initComponents();
  199.63 +
  199.64 +        addAroundOp.putClientProperty(OPTION_ID, addSpaceAroundOperators);
  199.65 +        addAfterComma.putClientProperty(OPTION_ID, addSpaceAfterComma);
  199.66 +        removeBeforeSep.putClientProperty(OPTION_ID, removeSpaceBeforeSep);
  199.67 +        removeInParam.putClientProperty(OPTION_ID, removeSpaceInParamAssign);
  199.68 +        removeInParen.putClientProperty(OPTION_ID, removeSpaceInParens);
  199.69 +        collapseSpacesCb.putClientProperty(OPTION_ID, collapseSpaces);
  199.70 +    }
  199.71 +
  199.72 +    public static PreferencesCustomizer.Factory getController() {
  199.73 +        return new CategorySupport.Factory("spaces", FmtSpaces.class, // NOI18N
  199.74 +                org.openide.util.NbBundle.getMessage(FmtSpaces.class, "SAMPLE_Spaces"));
  199.75 +    }
  199.76 +    
  199.77 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  199.78 +    private void initComponents() {
  199.79 +
  199.80 +        addAroundOp = new javax.swing.JCheckBox();
  199.81 +        removeInParam = new javax.swing.JCheckBox();
  199.82 +        removeInParen = new javax.swing.JCheckBox();
  199.83 +        addAfterComma = new javax.swing.JCheckBox();
  199.84 +        removeBeforeSep = new javax.swing.JCheckBox();
  199.85 +        collapseSpacesCb = new javax.swing.JCheckBox();
  199.86 +
  199.87 +        setName(org.openide.util.NbBundle.getMessage(FmtSpaces.class, "LBL_Spaces")); // NOI18N
  199.88 +        setOpaque(false);
  199.89 +
  199.90 +        org.openide.awt.Mnemonics.setLocalizedText(addAroundOp, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.addAroundOp.text")); // NOI18N
  199.91 +
  199.92 +        org.openide.awt.Mnemonics.setLocalizedText(removeInParam, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.removeInParam.text")); // NOI18N
  199.93 +
  199.94 +        org.openide.awt.Mnemonics.setLocalizedText(removeInParen, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.removeInParen.text")); // NOI18N
  199.95 +
  199.96 +        org.openide.awt.Mnemonics.setLocalizedText(addAfterComma, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.addAfterComma.text")); // NOI18N
  199.97 +
  199.98 +        org.openide.awt.Mnemonics.setLocalizedText(removeBeforeSep, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.removeBeforeSep.text")); // NOI18N
  199.99 +
 199.100 +        org.openide.awt.Mnemonics.setLocalizedText(collapseSpacesCb, org.openide.util.NbBundle.getMessage(FmtSpaces.class, "FmtSpaces.collapseSpacesCb.text")); // NOI18N
 199.101 +
 199.102 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
 199.103 +        this.setLayout(layout);
 199.104 +        layout.setHorizontalGroup(
 199.105 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 199.106 +            .addGroup(layout.createSequentialGroup()
 199.107 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 199.108 +                    .addComponent(addAroundOp)
 199.109 +                    .addGroup(layout.createSequentialGroup()
 199.110 +                        .addGap(27, 27, 27)
 199.111 +                        .addComponent(removeInParam))
 199.112 +                    .addComponent(removeInParen)
 199.113 +                    .addComponent(addAfterComma)
 199.114 +                    .addComponent(removeBeforeSep)
 199.115 +                    .addComponent(collapseSpacesCb))
 199.116 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 199.117 +        );
 199.118 +        layout.setVerticalGroup(
 199.119 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 199.120 +            .addGroup(layout.createSequentialGroup()
 199.121 +                .addComponent(addAroundOp)
 199.122 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 199.123 +                .addComponent(removeInParam)
 199.124 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 199.125 +                .addComponent(removeInParen)
 199.126 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 199.127 +                .addComponent(addAfterComma)
 199.128 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 199.129 +                .addComponent(removeBeforeSep)
 199.130 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 199.131 +                .addComponent(collapseSpacesCb)
 199.132 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 199.133 +        );
 199.134 +    }// </editor-fold>//GEN-END:initComponents
 199.135 +    
 199.136 +    
 199.137 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 199.138 +    private javax.swing.JCheckBox addAfterComma;
 199.139 +    private javax.swing.JCheckBox addAroundOp;
 199.140 +    private javax.swing.JCheckBox collapseSpacesCb;
 199.141 +    private javax.swing.JCheckBox removeBeforeSep;
 199.142 +    private javax.swing.JCheckBox removeInParam;
 199.143 +    private javax.swing.JCheckBox removeInParen;
 199.144 +    // End of variables declaration//GEN-END:variables
 199.145 +    
 199.146 +}
   200.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   200.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtTabsIndents.form	Mon Sep 21 13:01:16 2015 +0200
   200.3 @@ -0,0 +1,127 @@
   200.4 +<?xml version="1.0" encoding="UTF-8" ?>
   200.5 +
   200.6 +<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   200.7 +  <Properties>
   200.8 +    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   200.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;)"/>
  200.10 +    </Property>
  200.11 +    <Property name="opaque" type="boolean" value="false"/>
  200.12 +  </Properties>
  200.13 +  <AuxValues>
  200.14 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
  200.15 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  200.16 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  200.17 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
  200.18 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  200.19 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
  200.20 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
  200.21 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  200.22 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  200.23 +  </AuxValues>
  200.24 +
  200.25 +  <Layout>
  200.26 +    <DimensionLayout dim="0">
  200.27 +      <Group type="103" groupAlignment="0" attributes="0">
  200.28 +          <Group type="102" alignment="0" attributes="0">
  200.29 +              <Group type="103" groupAlignment="0" attributes="0">
  200.30 +                  <Component id="continuationIndentSizeLabel" max="32767" attributes="0"/>
  200.31 +                  <Component id="labelIndentLabel" min="-2" max="-2" attributes="0"/>
  200.32 +              </Group>
  200.33 +              <EmptySpace max="-2" attributes="0"/>
  200.34 +              <Group type="103" groupAlignment="1" attributes="0">
  200.35 +                  <Component id="continuationIndentSizeField" linkSize="2" min="-2" pref="36" max="-2" attributes="1"/>
  200.36 +                  <Component id="labelIndentField" linkSize="2" min="-2" pref="36" max="-2" attributes="1"/>
  200.37 +              </Group>
  200.38 +          </Group>
  200.39 +          <Component id="indentCasesFromSwitchCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
  200.40 +          <Component id="indentTopLevelClassMembersCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
  200.41 +          <Component id="absoluteLabelIndentCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
  200.42 +      </Group>
  200.43 +    </DimensionLayout>
  200.44 +    <DimensionLayout dim="1">
  200.45 +      <Group type="103" groupAlignment="0" attributes="0">
  200.46 +          <Group type="102" attributes="0">
  200.47 +              <EmptySpace max="-2" attributes="0"/>
  200.48 +              <Group type="103" groupAlignment="3" attributes="0">
  200.49 +                  <Component id="continuationIndentSizeLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  200.50 +                  <Component id="continuationIndentSizeField" alignment="3" min="-2" max="-2" attributes="0"/>
  200.51 +              </Group>
  200.52 +              <EmptySpace min="-2" max="-2" attributes="0"/>
  200.53 +              <Group type="103" groupAlignment="3" attributes="0">
  200.54 +                  <Component id="labelIndentLabel" alignment="3" min="-2" max="-2" attributes="0"/>
  200.55 +                  <Component id="labelIndentField" alignment="3" min="-2" max="-2" attributes="0"/>
  200.56 +              </Group>
  200.57 +              <EmptySpace type="unrelated" max="-2" attributes="0"/>
  200.58 +              <Component id="absoluteLabelIndentCheckBox" min="-2" max="-2" attributes="0"/>
  200.59 +              <EmptySpace max="-2" attributes="0"/>
  200.60 +              <Component id="indentTopLevelClassMembersCheckBox" min="-2" max="-2" attributes="0"/>
  200.61 +              <EmptySpace max="-2" attributes="0"/>
  200.62 +              <Component id="indentCasesFromSwitchCheckBox" min="-2" max="-2" attributes="0"/>
  200.63 +              <EmptySpace max="32767" attributes="0"/>
  200.64 +          </Group>
  200.65 +      </Group>
  200.66 +    </DimensionLayout>
  200.67 +  </Layout>
  200.68 +  <SubComponents>
  200.69 +    <Component class="javax.swing.JLabel" name="continuationIndentSizeLabel">
  200.70 +      <Properties>
  200.71 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  200.72 +          <ComponentRef name="continuationIndentSizeField"/>
  200.73 +        </Property>
  200.74 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  200.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;)"/>
  200.76 +        </Property>
  200.77 +      </Properties>
  200.78 +    </Component>
  200.79 +    <Component class="javax.swing.JTextField" name="continuationIndentSizeField">
  200.80 +    </Component>
  200.81 +    <Component class="javax.swing.JLabel" name="labelIndentLabel">
  200.82 +      <Properties>
  200.83 +        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  200.84 +          <ComponentRef name="labelIndentField"/>
  200.85 +        </Property>
  200.86 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  200.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;)"/>
  200.88 +        </Property>
  200.89 +      </Properties>
  200.90 +    </Component>
  200.91 +    <Component class="javax.swing.JTextField" name="labelIndentField">
  200.92 +    </Component>
  200.93 +    <Component class="javax.swing.JCheckBox" name="absoluteLabelIndentCheckBox">
  200.94 +      <Properties>
  200.95 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  200.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;)"/>
  200.97 +        </Property>
  200.98 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
  200.99 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 200.100 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 200.101 +          </Border>
 200.102 +        </Property>
 200.103 +      </Properties>
 200.104 +    </Component>
 200.105 +    <Component class="javax.swing.JCheckBox" name="indentTopLevelClassMembersCheckBox">
 200.106 +      <Properties>
 200.107 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 200.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;)"/>
 200.109 +        </Property>
 200.110 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 200.111 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 200.112 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 200.113 +          </Border>
 200.114 +        </Property>
 200.115 +      </Properties>
 200.116 +    </Component>
 200.117 +    <Component class="javax.swing.JCheckBox" name="indentCasesFromSwitchCheckBox">
 200.118 +      <Properties>
 200.119 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 200.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;)"/>
 200.121 +        </Property>
 200.122 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
 200.123 +          <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
 200.124 +            <EmptyBorder bottom="0" left="0" right="0" top="0"/>
 200.125 +          </Border>
 200.126 +        </Property>
 200.127 +      </Properties>
 200.128 +    </Component>
 200.129 +  </SubComponents>
 200.130 +</Form>
   201.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   201.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtTabsIndents.java	Mon Sep 21 13:01:16 2015 +0200
   201.3 @@ -0,0 +1,196 @@
   201.4 +/*
   201.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   201.6 + *
   201.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   201.8 + *
   201.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  201.10 + * Other names may be trademarks of their respective owners.
  201.11 + *
  201.12 + * The contents of this file are subject to the terms of either the GNU
  201.13 + * General Public License Version 2 only ("GPL") or the Common
  201.14 + * Development and Distribution License("CDDL") (collectively, the
  201.15 + * "License"). You may not use this file except in compliance with the
  201.16 + * License. You can obtain a copy of the License at
  201.17 + * http://www.netbeans.org/cddl-gplv2.html
  201.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  201.19 + * specific language governing permissions and limitations under the
  201.20 + * License.  When distributing the software, include this License Header
  201.21 + * Notice in each file and include the License file at
  201.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  201.23 + * particular file as subject to the "Classpath" exception as provided
  201.24 + * by Oracle in the GPL Version 2 section of the License file that
  201.25 + * accompanied this code. If applicable, add the following below the
  201.26 + * License Header, with the fields enclosed by brackets [] replaced by
  201.27 + * your own identifying information:
  201.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  201.29 + *
  201.30 + * Contributor(s):
  201.31 + *
  201.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  201.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  201.34 + * Microsystems, Inc. All Rights Reserved.
  201.35 + *
  201.36 + * If you wish your version of this file to be governed by only the CDDL
  201.37 + * or only the GPL Version 2, indicate your decision by adding
  201.38 + * "[Contributor] elects to include this software in this distribution
  201.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  201.40 + * single choice of license, a recipient has the option to distribute
  201.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  201.42 + * to extend the choice of license to its licensees as provided above.
  201.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  201.44 + * Version 2 license, then the option applies only if the new code is
  201.45 + * made subject to such option by the copyright holder.
  201.46 + */
  201.47 +
  201.48 +package org.netbeans.modules.python.source.ui;
  201.49 +
  201.50 +//import org.netbeans.modules.python.source.CodeStyle.WrapStyle;
  201.51 +//import static org.netbeans.modules.python.source.ui.FmtOptions.*;
  201.52 +//import static org.netbeans.modules.python.source.ui.FmtOptions.CategorySupport.OPTION_ID;
  201.53 +//import org.netbeans.modules.python.source.ui.FmtOptions.CategorySupport;
  201.54 +//import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
  201.55 +
  201.56 +/**
  201.57 + *
  201.58 + * @author  phrebejk
  201.59 + */
  201.60 +public class FmtTabsIndents extends javax.swing.JPanel {
  201.61 +   
  201.62 +    /** Creates new form FmtTabsIndents */
  201.63 +    public FmtTabsIndents() {
  201.64 +        initComponents();
  201.65 +/*
  201.66 +//        expandTabCheckBox.putClientProperty(OPTION_ID, expandTabToSpaces);
  201.67 +//        tabSizeField.putClientProperty(OPTION_ID, tabSize);
  201.68 +//        indentSizeField.putClientProperty(OPTION_ID, new String [] { indentSize, spacesPerTab });
  201.69 +        continuationIndentSizeField.putClientProperty(OPTION_ID, continuationIndentSize);
  201.70 +        labelIndentField.putClientProperty(OPTION_ID, labelIndent);
  201.71 +        absoluteLabelIndentCheckBox.putClientProperty(OPTION_ID, absoluteLabelIndent);
  201.72 +        indentTopLevelClassMembersCheckBox.putClientProperty(OPTION_ID, indentTopLevelClassMembers);
  201.73 +        indentCasesFromSwitchCheckBox.putClientProperty(OPTION_ID, indentCasesFromSwitch);
  201.74 +//        rightMarginField.putClientProperty(OPTION_ID, rightMargin);
  201.75 +    }
  201.76 +    
  201.77 +    public static PreferencesCustomizer.Factory getController() {
  201.78 +        return new CategorySupport.Factory(PreferencesCustomizer.TABS_AND_INDENTS_ID, FmtTabsIndents.class, //NOI18N
  201.79 +                org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "SAMPLE_TabsIndents"), // NOI18N
  201.80 +                new String[] { FmtOptions.rightMargin, "30" }, //NOI18N
  201.81 +                new String[] { FmtOptions.wrapAnnotations, WrapStyle.WRAP_ALWAYS.name() },
  201.82 +                new String[] { FmtOptions.wrapArrayInit, WrapStyle.WRAP_ALWAYS.name() },
  201.83 +                new String[] { FmtOptions.wrapAssert, WrapStyle.WRAP_ALWAYS.name() },
  201.84 +                new String[] { FmtOptions.wrapAssignOps, WrapStyle.WRAP_ALWAYS.name() },
  201.85 +                new String[] { FmtOptions.wrapBinaryOps, WrapStyle.WRAP_ALWAYS.name() },
  201.86 +                new String[] { FmtOptions.wrapChainedMethodCalls, WrapStyle.WRAP_ALWAYS.name() },
  201.87 +                new String[] { FmtOptions.wrapDoWhileStatement, WrapStyle.WRAP_ALWAYS.name() },
  201.88 +                new String[] { FmtOptions.wrapEnumConstants, WrapStyle.WRAP_ALWAYS.name() },
  201.89 +                new String[] { FmtOptions.wrapExtendsImplementsKeyword, WrapStyle.WRAP_ALWAYS.name() },
  201.90 +                new String[] { FmtOptions.wrapExtendsImplementsList, WrapStyle.WRAP_ALWAYS.name() },
  201.91 +                new String[] { FmtOptions.wrapFor, WrapStyle.WRAP_ALWAYS.name() },
  201.92 +                new String[] { FmtOptions.wrapForStatement, WrapStyle.WRAP_ALWAYS.name() },
  201.93 +                new String[] { FmtOptions.wrapIfStatement, WrapStyle.WRAP_ALWAYS.name() },
  201.94 +                new String[] { FmtOptions.wrapMethodCallArgs, WrapStyle.WRAP_ALWAYS.name() },
  201.95 +                new String[] { FmtOptions.wrapMethodParams, WrapStyle.WRAP_ALWAYS.name() },
  201.96 +                new String[] { FmtOptions.wrapTernaryOps, WrapStyle.WRAP_ALWAYS.name() },
  201.97 +                new String[] { FmtOptions.wrapThrowsKeyword, WrapStyle.WRAP_ALWAYS.name() },
  201.98 +                new String[] { FmtOptions.wrapThrowsList, WrapStyle.WRAP_ALWAYS.name() },
  201.99 +                new String[] { FmtOptions.wrapWhileStatement, WrapStyle.WRAP_ALWAYS.name() },
 201.100 +                new String[] { FmtOptions.alignMultilineArrayInit, Boolean.FALSE.toString() },
 201.101 +                new String[] { FmtOptions.alignMultilineAssignment, Boolean.FALSE.toString() },
 201.102 +                new String[] { FmtOptions.alignMultilineBinaryOp, Boolean.FALSE.toString() },
 201.103 +                new String[] { FmtOptions.alignMultilineCallArgs, Boolean.FALSE.toString() },
 201.104 +                new String[] { FmtOptions.alignMultilineFor, Boolean.FALSE.toString() },
 201.105 +                new String[] { FmtOptions.alignMultilineImplements, Boolean.FALSE.toString() },
 201.106 +                new String[] { FmtOptions.alignMultilineMethodParams, Boolean.FALSE.toString() },
 201.107 +                new String[] { FmtOptions.alignMultilineParenthesized, Boolean.FALSE.toString() },
 201.108 +                new String[] { FmtOptions.alignMultilineTernaryOp, Boolean.FALSE.toString() },
 201.109 +                new String[] { FmtOptions.alignMultilineThrows, Boolean.FALSE.toString() }
 201.110 +                );
 201.111 + */
 201.112 +    }
 201.113 +    
 201.114 +    /** This method is called from within the constructor to
 201.115 +     * initialize the form.
 201.116 +     * WARNING: Do NOT modify this code. The content of this method is
 201.117 +     * always regenerated by the Form Editor.
 201.118 +     */
 201.119 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
 201.120 +    private void initComponents() {
 201.121 +
 201.122 +        continuationIndentSizeLabel = new javax.swing.JLabel();
 201.123 +        continuationIndentSizeField = new javax.swing.JTextField();
 201.124 +        labelIndentLabel = new javax.swing.JLabel();
 201.125 +        labelIndentField = new javax.swing.JTextField();
 201.126 +        absoluteLabelIndentCheckBox = new javax.swing.JCheckBox();
 201.127 +        indentTopLevelClassMembersCheckBox = new javax.swing.JCheckBox();
 201.128 +        indentCasesFromSwitchCheckBox = new javax.swing.JCheckBox();
 201.129 +
 201.130 +        setName(org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_TabsAndIndents")); // NOI18N
 201.131 +        setOpaque(false);
 201.132 +
 201.133 +        continuationIndentSizeLabel.setLabelFor(continuationIndentSizeField);
 201.134 +        org.openide.awt.Mnemonics.setLocalizedText(continuationIndentSizeLabel, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_ContinuationIndentSize")); // NOI18N
 201.135 +
 201.136 +        labelIndentLabel.setLabelFor(labelIndentField);
 201.137 +        org.openide.awt.Mnemonics.setLocalizedText(labelIndentLabel, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_LabelIndent")); // NOI18N
 201.138 +
 201.139 +        org.openide.awt.Mnemonics.setLocalizedText(absoluteLabelIndentCheckBox, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_AbsoluteLabelIndent")); // NOI18N
 201.140 +        absoluteLabelIndentCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 201.141 +
 201.142 +        org.openide.awt.Mnemonics.setLocalizedText(indentTopLevelClassMembersCheckBox, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_IndentTopLevelClassMemberts")); // NOI18N
 201.143 +        indentTopLevelClassMembersCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 201.144 +
 201.145 +        org.openide.awt.Mnemonics.setLocalizedText(indentCasesFromSwitchCheckBox, org.openide.util.NbBundle.getMessage(FmtTabsIndents.class, "LBL_IndentCasesFromSwitch")); // NOI18N
 201.146 +        indentCasesFromSwitchCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
 201.147 +
 201.148 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
 201.149 +        this.setLayout(layout);
 201.150 +        layout.setHorizontalGroup(
 201.151 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 201.152 +            .addGroup(layout.createSequentialGroup()
 201.153 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 201.154 +                    .addComponent(continuationIndentSizeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 201.155 +                    .addComponent(labelIndentLabel))
 201.156 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 201.157 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
 201.158 +                    .addComponent(continuationIndentSizeField, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE)
 201.159 +                    .addComponent(labelIndentField, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE)))
 201.160 +            .addComponent(indentCasesFromSwitchCheckBox)
 201.161 +            .addComponent(indentTopLevelClassMembersCheckBox)
 201.162 +            .addComponent(absoluteLabelIndentCheckBox)
 201.163 +        );
 201.164 +
 201.165 +        layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {continuationIndentSizeField, labelIndentField});
 201.166 +
 201.167 +        layout.setVerticalGroup(
 201.168 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 201.169 +            .addGroup(layout.createSequentialGroup()
 201.170 +                .addContainerGap()
 201.171 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 201.172 +                    .addComponent(continuationIndentSizeLabel)
 201.173 +                    .addComponent(continuationIndentSizeField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 201.174 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 201.175 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 201.176 +                    .addComponent(labelIndentLabel)
 201.177 +                    .addComponent(labelIndentField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 201.178 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 201.179 +                .addComponent(absoluteLabelIndentCheckBox)
 201.180 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 201.181 +                .addComponent(indentTopLevelClassMembersCheckBox)
 201.182 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 201.183 +                .addComponent(indentCasesFromSwitchCheckBox)
 201.184 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 201.185 +        );
 201.186 +    }// </editor-fold>//GEN-END:initComponents
 201.187 +    
 201.188 +    
 201.189 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 201.190 +    private javax.swing.JCheckBox absoluteLabelIndentCheckBox;
 201.191 +    private javax.swing.JTextField continuationIndentSizeField;
 201.192 +    private javax.swing.JLabel continuationIndentSizeLabel;
 201.193 +    private javax.swing.JCheckBox indentCasesFromSwitchCheckBox;
 201.194 +    private javax.swing.JCheckBox indentTopLevelClassMembersCheckBox;
 201.195 +    private javax.swing.JTextField labelIndentField;
 201.196 +    private javax.swing.JLabel labelIndentLabel;
 201.197 +    // End of variables declaration//GEN-END:variables
 201.198 +    
 201.199 +}
   202.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   202.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtWrapping.form	Mon Sep 21 13:01:16 2015 +0200
   202.3 @@ -0,0 +1,706 @@
   202.4 +<?xml version="1.0" encoding="UTF-8" ?>
   202.5 +
   202.6 +<Form version="1.4" maxVersion="1.4" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
   202.7 +  <Properties>
   202.8 +    <Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   202.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;)"/>
  202.10 +    </Property>
  202.11 +    <Property name="opaque" type="boolean" value="false"/>
  202.12 +  </Properties>
  202.13 +  <AuxValues>
  202.14 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
  202.15 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
  202.16 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
  202.17 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
  202.18 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
  202.19 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
  202.20 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
  202.21 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
  202.22 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
  202.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"/>
  202.24 +  </AuxValues>
  202.25 +
  202.26 +  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
  202.27 +  <SubComponents>
  202.28 +    <Container class="javax.swing.JScrollPane" name="scrollPane">
  202.29 +      <Properties>
  202.30 +        <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
  202.31 +          <Dimension value="[300, 200]"/>
  202.32 +        </Property>
  202.33 +        <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
  202.34 +          <Dimension value="[350, 600]"/>
  202.35 +        </Property>
  202.36 +      </Properties>
  202.37 +      <Constraints>
  202.38 +        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
  202.39 +          <BorderConstraints direction="Center"/>
  202.40 +        </Constraint>
  202.41 +      </Constraints>
  202.42 +
  202.43 +      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
  202.44 +      <SubComponents>
  202.45 +        <Container class="javax.swing.JPanel" name="panel1">
  202.46 +          <Properties>
  202.47 +            <Property name="opaque" type="boolean" value="false"/>
  202.48 +          </Properties>
  202.49 +
  202.50 +          <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
  202.51 +          <SubComponents>
  202.52 +            <Component class="javax.swing.JLabel" name="extendsImplemetsKeywordLabel">
  202.53 +              <Properties>
  202.54 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  202.55 +                  <ComponentRef name="extendsImplementsKeywordCombo"/>
  202.56 +                </Property>
  202.57 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  202.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;)"/>
  202.59 +                </Property>
  202.60 +              </Properties>
  202.61 +              <Constraints>
  202.62 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  202.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"/>
  202.64 +                </Constraint>
  202.65 +              </Constraints>
  202.66 +            </Component>
  202.67 +            <Component class="javax.swing.JComboBox" name="extendsImplementsKeywordCombo">
  202.68 +              <Properties>
  202.69 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
  202.70 +                  <StringArray count="4">
  202.71 +                    <StringItem index="0" value="Item 1"/>
  202.72 +                    <StringItem index="1" value="Item 2"/>
  202.73 +                    <StringItem index="2" value="Item 3"/>
  202.74 +                    <StringItem index="3" value="Item 4"/>
  202.75 +                  </StringArray>
  202.76 +                </Property>
  202.77 +              </Properties>
  202.78 +              <Constraints>
  202.79 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  202.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"/>
  202.81 +                </Constraint>
  202.82 +              </Constraints>
  202.83 +            </Component>
  202.84 +            <Component class="javax.swing.JLabel" name="extendsImplementsListLabel">
  202.85 +              <Properties>
  202.86 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
  202.87 +                  <ComponentRef name="extendsImplementsListCombo"/>
  202.88 +                </Property>
  202.89 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  202.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;)"/>
  202.91 +                </Property>
  202.92 +              </Properties>
  202.93 +              <Constraints>
  202.94 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
  202.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"/>
  202.96 +                </Constraint>
  202.97 +              </Constraints>
  202.98 +            </Component>
  202.99 +            <Component class="javax.swing.JComboBox" name="extendsImplementsListCombo">
 202.100 +              <Properties>
 202.101 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.102 +                  <StringArray count="4">
 202.103 +                    <StringItem index="0" value="Item 1"/>
 202.104 +                    <StringItem index="1" value="Item 2"/>
 202.105 +                    <StringItem index="2" value="Item 3"/>
 202.106 +                    <StringItem index="3" value="Item 4"/>
 202.107 +                  </StringArray>
 202.108 +                </Property>
 202.109 +              </Properties>
 202.110 +              <Constraints>
 202.111 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.113 +                </Constraint>
 202.114 +              </Constraints>
 202.115 +            </Component>
 202.116 +            <Component class="javax.swing.JLabel" name="methodParamsLabel">
 202.117 +              <Properties>
 202.118 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.119 +                  <ComponentRef name="methodParamsCombo"/>
 202.120 +                </Property>
 202.121 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.123 +                </Property>
 202.124 +              </Properties>
 202.125 +              <Constraints>
 202.126 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.128 +                </Constraint>
 202.129 +              </Constraints>
 202.130 +            </Component>
 202.131 +            <Component class="javax.swing.JComboBox" name="methodParamsCombo">
 202.132 +              <Properties>
 202.133 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.134 +                  <StringArray count="4">
 202.135 +                    <StringItem index="0" value="Item 1"/>
 202.136 +                    <StringItem index="1" value="Item 2"/>
 202.137 +                    <StringItem index="2" value="Item 3"/>
 202.138 +                    <StringItem index="3" value="Item 4"/>
 202.139 +                  </StringArray>
 202.140 +                </Property>
 202.141 +              </Properties>
 202.142 +              <Constraints>
 202.143 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.145 +                </Constraint>
 202.146 +              </Constraints>
 202.147 +            </Component>
 202.148 +            <Component class="javax.swing.JLabel" name="methodCallArgsLabel">
 202.149 +              <Properties>
 202.150 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.151 +                  <ComponentRef name="methodCallArgsCombo"/>
 202.152 +                </Property>
 202.153 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.155 +                </Property>
 202.156 +              </Properties>
 202.157 +              <Constraints>
 202.158 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.160 +                </Constraint>
 202.161 +              </Constraints>
 202.162 +            </Component>
 202.163 +            <Component class="javax.swing.JComboBox" name="methodCallArgsCombo">
 202.164 +              <Properties>
 202.165 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.166 +                  <StringArray count="4">
 202.167 +                    <StringItem index="0" value="Item 1"/>
 202.168 +                    <StringItem index="1" value="Item 2"/>
 202.169 +                    <StringItem index="2" value="Item 3"/>
 202.170 +                    <StringItem index="3" value="Item 4"/>
 202.171 +                  </StringArray>
 202.172 +                </Property>
 202.173 +              </Properties>
 202.174 +              <Constraints>
 202.175 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.177 +                </Constraint>
 202.178 +              </Constraints>
 202.179 +            </Component>
 202.180 +            <Component class="javax.swing.JLabel" name="annotationArgsLabel">
 202.181 +              <Properties>
 202.182 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.183 +                  <ComponentRef name="annotationArgsCombo"/>
 202.184 +                </Property>
 202.185 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.187 +                </Property>
 202.188 +              </Properties>
 202.189 +              <Constraints>
 202.190 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.192 +                </Constraint>
 202.193 +              </Constraints>
 202.194 +            </Component>
 202.195 +            <Component class="javax.swing.JComboBox" name="annotationArgsCombo">
 202.196 +              <Properties>
 202.197 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.198 +                  <StringArray count="4">
 202.199 +                    <StringItem index="0" value="Item 1"/>
 202.200 +                    <StringItem index="1" value="Item 2"/>
 202.201 +                    <StringItem index="2" value="Item 3"/>
 202.202 +                    <StringItem index="3" value="Item 4"/>
 202.203 +                  </StringArray>
 202.204 +                </Property>
 202.205 +              </Properties>
 202.206 +              <Constraints>
 202.207 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.209 +                </Constraint>
 202.210 +              </Constraints>
 202.211 +            </Component>
 202.212 +            <Component class="javax.swing.JLabel" name="chainedMethodCallsLabel">
 202.213 +              <Properties>
 202.214 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.215 +                  <ComponentRef name="chainedMethodCallsCombo"/>
 202.216 +                </Property>
 202.217 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.219 +                </Property>
 202.220 +              </Properties>
 202.221 +              <Constraints>
 202.222 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.224 +                </Constraint>
 202.225 +              </Constraints>
 202.226 +            </Component>
 202.227 +            <Component class="javax.swing.JComboBox" name="chainedMethodCallsCombo">
 202.228 +              <Properties>
 202.229 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.230 +                  <StringArray count="4">
 202.231 +                    <StringItem index="0" value="Item 1"/>
 202.232 +                    <StringItem index="1" value="Item 2"/>
 202.233 +                    <StringItem index="2" value="Item 3"/>
 202.234 +                    <StringItem index="3" value="Item 4"/>
 202.235 +                  </StringArray>
 202.236 +                </Property>
 202.237 +              </Properties>
 202.238 +              <Constraints>
 202.239 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.241 +                </Constraint>
 202.242 +              </Constraints>
 202.243 +            </Component>
 202.244 +            <Component class="javax.swing.JLabel" name="throwsKeywordLabel">
 202.245 +              <Properties>
 202.246 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.247 +                  <ComponentRef name="throwsKeywordCombo"/>
 202.248 +                </Property>
 202.249 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.251 +                </Property>
 202.252 +              </Properties>
 202.253 +              <Constraints>
 202.254 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.256 +                </Constraint>
 202.257 +              </Constraints>
 202.258 +            </Component>
 202.259 +            <Component class="javax.swing.JComboBox" name="throwsKeywordCombo">
 202.260 +              <Properties>
 202.261 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.262 +                  <StringArray count="4">
 202.263 +                    <StringItem index="0" value="Item 1"/>
 202.264 +                    <StringItem index="1" value="Item 2"/>
 202.265 +                    <StringItem index="2" value="Item 3"/>
 202.266 +                    <StringItem index="3" value="Item 4"/>
 202.267 +                  </StringArray>
 202.268 +                </Property>
 202.269 +              </Properties>
 202.270 +              <Constraints>
 202.271 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.273 +                </Constraint>
 202.274 +              </Constraints>
 202.275 +            </Component>
 202.276 +            <Component class="javax.swing.JLabel" name="throwsListLabel">
 202.277 +              <Properties>
 202.278 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.279 +                  <ComponentRef name="throwsListCombo"/>
 202.280 +                </Property>
 202.281 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.283 +                </Property>
 202.284 +              </Properties>
 202.285 +              <Constraints>
 202.286 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.288 +                </Constraint>
 202.289 +              </Constraints>
 202.290 +            </Component>
 202.291 +            <Component class="javax.swing.JComboBox" name="throwsListCombo">
 202.292 +              <Properties>
 202.293 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.294 +                  <StringArray count="4">
 202.295 +                    <StringItem index="0" value="Item 1"/>
 202.296 +                    <StringItem index="1" value="Item 2"/>
 202.297 +                    <StringItem index="2" value="Item 3"/>
 202.298 +                    <StringItem index="3" value="Item 4"/>
 202.299 +                  </StringArray>
 202.300 +                </Property>
 202.301 +              </Properties>
 202.302 +              <Constraints>
 202.303 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.305 +                </Constraint>
 202.306 +              </Constraints>
 202.307 +            </Component>
 202.308 +            <Component class="javax.swing.JLabel" name="arrayInitLabel">
 202.309 +              <Properties>
 202.310 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.311 +                  <ComponentRef name="arrayInitCombo"/>
 202.312 +                </Property>
 202.313 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.315 +                </Property>
 202.316 +              </Properties>
 202.317 +              <Constraints>
 202.318 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.320 +                </Constraint>
 202.321 +              </Constraints>
 202.322 +            </Component>
 202.323 +            <Component class="javax.swing.JComboBox" name="arrayInitCombo">
 202.324 +              <Properties>
 202.325 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.326 +                  <StringArray count="4">
 202.327 +                    <StringItem index="0" value="Item 1"/>
 202.328 +                    <StringItem index="1" value="Item 2"/>
 202.329 +                    <StringItem index="2" value="Item 3"/>
 202.330 +                    <StringItem index="3" value="Item 4"/>
 202.331 +                  </StringArray>
 202.332 +                </Property>
 202.333 +              </Properties>
 202.334 +              <Constraints>
 202.335 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.337 +                </Constraint>
 202.338 +              </Constraints>
 202.339 +            </Component>
 202.340 +            <Component class="javax.swing.JLabel" name="forLabel">
 202.341 +              <Properties>
 202.342 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.343 +                  <ComponentRef name="forCombo"/>
 202.344 +                </Property>
 202.345 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.347 +                </Property>
 202.348 +              </Properties>
 202.349 +              <Constraints>
 202.350 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.352 +                </Constraint>
 202.353 +              </Constraints>
 202.354 +            </Component>
 202.355 +            <Component class="javax.swing.JComboBox" name="forCombo">
 202.356 +              <Properties>
 202.357 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.358 +                  <StringArray count="4">
 202.359 +                    <StringItem index="0" value="Item 1"/>
 202.360 +                    <StringItem index="1" value="Item 2"/>
 202.361 +                    <StringItem index="2" value="Item 3"/>
 202.362 +                    <StringItem index="3" value="Item 4"/>
 202.363 +                  </StringArray>
 202.364 +                </Property>
 202.365 +              </Properties>
 202.366 +              <Constraints>
 202.367 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.369 +                </Constraint>
 202.370 +              </Constraints>
 202.371 +            </Component>
 202.372 +            <Component class="javax.swing.JLabel" name="forStatementLabel">
 202.373 +              <Properties>
 202.374 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.375 +                  <ComponentRef name="forStatementCombo"/>
 202.376 +                </Property>
 202.377 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.379 +                </Property>
 202.380 +              </Properties>
 202.381 +              <Constraints>
 202.382 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.384 +                </Constraint>
 202.385 +              </Constraints>
 202.386 +            </Component>
 202.387 +            <Component class="javax.swing.JComboBox" name="forStatementCombo">
 202.388 +              <Properties>
 202.389 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.390 +                  <StringArray count="4">
 202.391 +                    <StringItem index="0" value="Item 1"/>
 202.392 +                    <StringItem index="1" value="Item 2"/>
 202.393 +                    <StringItem index="2" value="Item 3"/>
 202.394 +                    <StringItem index="3" value="Item 4"/>
 202.395 +                  </StringArray>
 202.396 +                </Property>
 202.397 +              </Properties>
 202.398 +              <Constraints>
 202.399 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.401 +                </Constraint>
 202.402 +              </Constraints>
 202.403 +            </Component>
 202.404 +            <Component class="javax.swing.JLabel" name="ifStatementLabel">
 202.405 +              <Properties>
 202.406 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.407 +                  <ComponentRef name="ifStatementCombo"/>
 202.408 +                </Property>
 202.409 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.411 +                </Property>
 202.412 +              </Properties>
 202.413 +              <Constraints>
 202.414 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.416 +                </Constraint>
 202.417 +              </Constraints>
 202.418 +            </Component>
 202.419 +            <Component class="javax.swing.JComboBox" name="ifStatementCombo">
 202.420 +              <Properties>
 202.421 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.422 +                  <StringArray count="4">
 202.423 +                    <StringItem index="0" value="Item 1"/>
 202.424 +                    <StringItem index="1" value="Item 2"/>
 202.425 +                    <StringItem index="2" value="Item 3"/>
 202.426 +                    <StringItem index="3" value="Item 4"/>
 202.427 +                  </StringArray>
 202.428 +                </Property>
 202.429 +              </Properties>
 202.430 +              <Constraints>
 202.431 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.433 +                </Constraint>
 202.434 +              </Constraints>
 202.435 +            </Component>
 202.436 +            <Component class="javax.swing.JLabel" name="whileStatementLabel">
 202.437 +              <Properties>
 202.438 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.439 +                  <ComponentRef name="whileStatementComboBox"/>
 202.440 +                </Property>
 202.441 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.443 +                </Property>
 202.444 +              </Properties>
 202.445 +              <Constraints>
 202.446 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.448 +                </Constraint>
 202.449 +              </Constraints>
 202.450 +            </Component>
 202.451 +            <Component class="javax.swing.JComboBox" name="whileStatementComboBox">
 202.452 +              <Properties>
 202.453 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.454 +                  <StringArray count="4">
 202.455 +                    <StringItem index="0" value="Item 1"/>
 202.456 +                    <StringItem index="1" value="Item 2"/>
 202.457 +                    <StringItem index="2" value="Item 3"/>
 202.458 +                    <StringItem index="3" value="Item 4"/>
 202.459 +                  </StringArray>
 202.460 +                </Property>
 202.461 +              </Properties>
 202.462 +              <Constraints>
 202.463 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.465 +                </Constraint>
 202.466 +              </Constraints>
 202.467 +            </Component>
 202.468 +            <Component class="javax.swing.JLabel" name="doWhileStatementLabel">
 202.469 +              <Properties>
 202.470 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.471 +                  <ComponentRef name="doWhileStatementCombo"/>
 202.472 +                </Property>
 202.473 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.475 +                </Property>
 202.476 +              </Properties>
 202.477 +              <Constraints>
 202.478 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.480 +                </Constraint>
 202.481 +              </Constraints>
 202.482 +            </Component>
 202.483 +            <Component class="javax.swing.JComboBox" name="doWhileStatementCombo">
 202.484 +              <Properties>
 202.485 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.486 +                  <StringArray count="4">
 202.487 +                    <StringItem index="0" value="Item 1"/>
 202.488 +                    <StringItem index="1" value="Item 2"/>
 202.489 +                    <StringItem index="2" value="Item 3"/>
 202.490 +                    <StringItem index="3" value="Item 4"/>
 202.491 +                  </StringArray>
 202.492 +                </Property>
 202.493 +              </Properties>
 202.494 +              <Constraints>
 202.495 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.497 +                </Constraint>
 202.498 +              </Constraints>
 202.499 +            </Component>
 202.500 +            <Component class="javax.swing.JLabel" name="assertLabel">
 202.501 +              <Properties>
 202.502 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.503 +                  <ComponentRef name="assertCombo"/>
 202.504 +                </Property>
 202.505 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.507 +                </Property>
 202.508 +              </Properties>
 202.509 +              <Constraints>
 202.510 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.512 +                </Constraint>
 202.513 +              </Constraints>
 202.514 +            </Component>
 202.515 +            <Component class="javax.swing.JComboBox" name="assertCombo">
 202.516 +              <Properties>
 202.517 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.518 +                  <StringArray count="4">
 202.519 +                    <StringItem index="0" value="Item 1"/>
 202.520 +                    <StringItem index="1" value="Item 2"/>
 202.521 +                    <StringItem index="2" value="Item 3"/>
 202.522 +                    <StringItem index="3" value="Item 4"/>
 202.523 +                  </StringArray>
 202.524 +                </Property>
 202.525 +              </Properties>
 202.526 +              <Constraints>
 202.527 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.529 +                </Constraint>
 202.530 +              </Constraints>
 202.531 +            </Component>
 202.532 +            <Component class="javax.swing.JLabel" name="enumConstantsLabel">
 202.533 +              <Properties>
 202.534 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.535 +                  <ComponentRef name="enumConstantsCombo"/>
 202.536 +                </Property>
 202.537 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.539 +                </Property>
 202.540 +              </Properties>
 202.541 +              <Constraints>
 202.542 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.544 +                </Constraint>
 202.545 +              </Constraints>
 202.546 +            </Component>
 202.547 +            <Component class="javax.swing.JComboBox" name="enumConstantsCombo">
 202.548 +              <Properties>
 202.549 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.550 +                  <StringArray count="4">
 202.551 +                    <StringItem index="0" value="Item 1"/>
 202.552 +                    <StringItem index="1" value="Item 2"/>
 202.553 +                    <StringItem index="2" value="Item 3"/>
 202.554 +                    <StringItem index="3" value="Item 4"/>
 202.555 +                  </StringArray>
 202.556 +                </Property>
 202.557 +              </Properties>
 202.558 +              <Constraints>
 202.559 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.561 +                </Constraint>
 202.562 +              </Constraints>
 202.563 +            </Component>
 202.564 +            <Component class="javax.swing.JLabel" name="annotationsLabel">
 202.565 +              <Properties>
 202.566 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.567 +                  <ComponentRef name="annotationsCombo"/>
 202.568 +                </Property>
 202.569 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.571 +                </Property>
 202.572 +              </Properties>
 202.573 +              <Constraints>
 202.574 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.576 +                </Constraint>
 202.577 +              </Constraints>
 202.578 +            </Component>
 202.579 +            <Component class="javax.swing.JComboBox" name="annotationsCombo">
 202.580 +              <Properties>
 202.581 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.582 +                  <StringArray count="4">
 202.583 +                    <StringItem index="0" value="Item 1"/>
 202.584 +                    <StringItem index="1" value="Item 2"/>
 202.585 +                    <StringItem index="2" value="Item 3"/>
 202.586 +                    <StringItem index="3" value="Item 4"/>
 202.587 +                  </StringArray>
 202.588 +                </Property>
 202.589 +              </Properties>
 202.590 +              <Constraints>
 202.591 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.593 +                </Constraint>
 202.594 +              </Constraints>
 202.595 +            </Component>
 202.596 +            <Component class="javax.swing.JLabel" name="binaryOpsLabel">
 202.597 +              <Properties>
 202.598 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.599 +                  <ComponentRef name="binaryOpsCombo"/>
 202.600 +                </Property>
 202.601 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.603 +                </Property>
 202.604 +              </Properties>
 202.605 +              <Constraints>
 202.606 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.608 +                </Constraint>
 202.609 +              </Constraints>
 202.610 +            </Component>
 202.611 +            <Component class="javax.swing.JComboBox" name="binaryOpsCombo">
 202.612 +              <Properties>
 202.613 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.614 +                  <StringArray count="4">
 202.615 +                    <StringItem index="0" value="Item 1"/>
 202.616 +                    <StringItem index="1" value="Item 2"/>
 202.617 +                    <StringItem index="2" value="Item 3"/>
 202.618 +                    <StringItem index="3" value="Item 4"/>
 202.619 +                  </StringArray>
 202.620 +                </Property>
 202.621 +              </Properties>
 202.622 +              <Constraints>
 202.623 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.625 +                </Constraint>
 202.626 +              </Constraints>
 202.627 +            </Component>
 202.628 +            <Component class="javax.swing.JLabel" name="ternaryOpsLabel">
 202.629 +              <Properties>
 202.630 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.631 +                  <ComponentRef name="ternaryOpsCombo"/>
 202.632 +                </Property>
 202.633 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.635 +                </Property>
 202.636 +              </Properties>
 202.637 +              <Constraints>
 202.638 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.640 +                </Constraint>
 202.641 +              </Constraints>
 202.642 +            </Component>
 202.643 +            <Component class="javax.swing.JComboBox" name="ternaryOpsCombo">
 202.644 +              <Properties>
 202.645 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.646 +                  <StringArray count="4">
 202.647 +                    <StringItem index="0" value="Item 1"/>
 202.648 +                    <StringItem index="1" value="Item 2"/>
 202.649 +                    <StringItem index="2" value="Item 3"/>
 202.650 +                    <StringItem index="3" value="Item 4"/>
 202.651 +                  </StringArray>
 202.652 +                </Property>
 202.653 +              </Properties>
 202.654 +              <Constraints>
 202.655 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.657 +                </Constraint>
 202.658 +              </Constraints>
 202.659 +            </Component>
 202.660 +            <Component class="javax.swing.JLabel" name="assignOpsLabel">
 202.661 +              <Properties>
 202.662 +                <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
 202.663 +                  <ComponentRef name="assignOpsCombo"/>
 202.664 +                </Property>
 202.665 +                <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
 202.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;)"/>
 202.667 +                </Property>
 202.668 +              </Properties>
 202.669 +              <Constraints>
 202.670 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.672 +                </Constraint>
 202.673 +              </Constraints>
 202.674 +            </Component>
 202.675 +            <Component class="javax.swing.JComboBox" name="assignOpsCombo">
 202.676 +              <Properties>
 202.677 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
 202.678 +                  <StringArray count="4">
 202.679 +                    <StringItem index="0" value="Item 1"/>
 202.680 +                    <StringItem index="1" value="Item 2"/>
 202.681 +                    <StringItem index="2" value="Item 3"/>
 202.682 +                    <StringItem index="3" value="Item 4"/>
 202.683 +                  </StringArray>
 202.684 +                </Property>
 202.685 +              </Properties>
 202.686 +              <Constraints>
 202.687 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.689 +                </Constraint>
 202.690 +              </Constraints>
 202.691 +            </Component>
 202.692 +            <Container class="javax.swing.JPanel" name="spacerPanel1">
 202.693 +              <Properties>
 202.694 +                <Property name="opaque" type="boolean" value="false"/>
 202.695 +              </Properties>
 202.696 +              <Constraints>
 202.697 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
 202.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"/>
 202.699 +                </Constraint>
 202.700 +              </Constraints>
 202.701 +
 202.702 +              <Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
 202.703 +            </Container>
 202.704 +          </SubComponents>
 202.705 +        </Container>
 202.706 +      </SubComponents>
 202.707 +    </Container>
 202.708 +  </SubComponents>
 202.709 +</Form>
   203.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   203.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/FmtWrapping.java	Mon Sep 21 13:01:16 2015 +0200
   203.3 @@ -0,0 +1,505 @@
   203.4 +/*
   203.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   203.6 + *
   203.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   203.8 + *
   203.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  203.10 + * Other names may be trademarks of their respective owners.
  203.11 + *
  203.12 + * The contents of this file are subject to the terms of either the GNU
  203.13 + * General Public License Version 2 only ("GPL") or the Common
  203.14 + * Development and Distribution License("CDDL") (collectively, the
  203.15 + * "License"). You may not use this file except in compliance with the
  203.16 + * License. You can obtain a copy of the License at
  203.17 + * http://www.netbeans.org/cddl-gplv2.html
  203.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  203.19 + * specific language governing permissions and limitations under the
  203.20 + * License.  When distributing the software, include this License Header
  203.21 + * Notice in each file and include the License file at
  203.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  203.23 + * particular file as subject to the "Classpath" exception as provided
  203.24 + * by Oracle in the GPL Version 2 section of the License file that
  203.25 + * accompanied this code. If applicable, add the following below the
  203.26 + * License Header, with the fields enclosed by brackets [] replaced by
  203.27 + * your own identifying information:
  203.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  203.29 + *
  203.30 + * Contributor(s):
  203.31 + *
  203.32 + * The Original Software is NetBeans. The Initial Developer of the Original
  203.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  203.34 + * Microsystems, Inc. All Rights Reserved.
  203.35 + *
  203.36 + * If you wish your version of this file to be governed by only the CDDL
  203.37 + * or only the GPL Version 2, indicate your decision by adding
  203.38 + * "[Contributor] elects to include this software in this distribution
  203.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  203.40 + * single choice of license, a recipient has the option to distribute
  203.41 + * your version of this file under either the CDDL, the GPL Version 2 or
  203.42 + * to extend the choice of license to its licensees as provided above.
  203.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  203.44 + * Version 2 license, then the option applies only if the new code is
  203.45 + * made subject to such option by the copyright holder.
  203.46 + */
  203.47 +
  203.48 +package org.netbeans.modules.python.source.ui;
  203.49 +
  203.50 +//import org.netbeans.modules.python.source.CodeStyle;
  203.51 +//import static org.netbeans.modules.python.source.ui.FmtOptions.*;
  203.52 +//import static org.netbeans.modules.python.source.ui.FmtOptions.CategorySupport.OPTION_ID;
  203.53 +//import org.netbeans.modules.python.source.ui.FmtOptions.CategorySupport;
  203.54 +//import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
  203.55 +
  203.56 +
  203.57 +/**
  203.58 + *
  203.59 + * @author  phrebejk
  203.60 + */
  203.61 +public class FmtWrapping extends javax.swing.JPanel {
  203.62 +    
  203.63 +    /** Creates new form FmtWrapping */
  203.64 +    public FmtWrapping() {
  203.65 +        initComponents();
  203.66 +        
  203.67 +        scrollPane.getViewport().setBackground(java.awt.SystemColor.controlLtHighlight);
  203.68 +        
  203.69 +/*
  203.70 +        extendsImplementsKeywordCombo.putClientProperty(OPTION_ID, wrapExtendsImplementsKeyword);
  203.71 +        extendsImplementsListCombo.putClientProperty(OPTION_ID, wrapExtendsImplementsList);
  203.72 +        methodParamsCombo.putClientProperty(OPTION_ID, wrapMethodParams);
  203.73 +        methodCallArgsCombo.putClientProperty(OPTION_ID, wrapMethodCallArgs);
  203.74 +        annotationArgsCombo.putClientProperty(OPTION_ID, wrapAnnotationArgs);
  203.75 +        chainedMethodCallsCombo.putClientProperty(OPTION_ID, wrapChainedMethodCalls);
  203.76 +        throwsKeywordCombo.putClientProperty(OPTION_ID, wrapThrowsKeyword);
  203.77 +        throwsListCombo.putClientProperty(OPTION_ID, wrapThrowsList);
  203.78 +        arrayInitCombo.putClientProperty(OPTION_ID, wrapArrayInit);
  203.79 +        forCombo.putClientProperty(OPTION_ID, wrapFor);
  203.80 +        forStatementCombo.putClientProperty(OPTION_ID, wrapForStatement );
  203.81 +        ifStatementCombo.putClientProperty(OPTION_ID, wrapIfStatement);
  203.82 +        whileStatementComboBox.putClientProperty(OPTION_ID, wrapWhileStatement);
  203.83 +        doWhileStatementCombo.putClientProperty(OPTION_ID, wrapDoWhileStatement);
  203.84 +        assertCombo.putClientProperty(OPTION_ID, wrapAssert);
  203.85 +        enumConstantsCombo.putClientProperty(OPTION_ID, wrapEnumConstants);
  203.86 +        annotationsCombo.putClientProperty(OPTION_ID, wrapAnnotations);
  203.87 +        binaryOpsCombo.putClientProperty(OPTION_ID, wrapBinaryOps);
  203.88 +        ternaryOpsCombo.putClientProperty(OPTION_ID, wrapTernaryOps);
  203.89 +        assignOpsCombo.putClientProperty(OPTION_ID, wrapAssignOps);
  203.90 +    }
  203.91 +    
  203.92 +    public static PreferencesCustomizer.Factory getController() {
  203.93 +        return new CategorySupport.Factory("wrapping", FmtWrapping.class, //NOI18N
  203.94 +                org.openide.util.NbBundle.getMessage(FmtWrapping.class, "SAMPLE_Wrapping"), //NOI18N
  203.95 +                new String[] { FmtOptions.rightMargin, "30" } //NOI18N
  203.96 +//                new String[] { FmtOptions.redundantDoWhileBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() },
  203.97 +//                new String[] { FmtOptions.redundantForBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() },
  203.98 +//                new String[] { FmtOptions.redundantIfBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() },
  203.99 +//                new String[] { FmtOptions.redundantWhileBraces, CodeStyle.BracesGenerationStyle.LEAVE_ALONE.name() }
 203.100 +        ); // NOI18N
 203.101 + */
 203.102 +    }
 203.103 +    
 203.104 +    /** This method is called from within the constructor to
 203.105 +     * initialize the form.
 203.106 +     * WARNING: Do NOT modify this code. The content of this method is
 203.107 +     * always regenerated by the Form Editor.
 203.108 +     */
 203.109 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
 203.110 +    private void initComponents() {
 203.111 +        java.awt.GridBagConstraints gridBagConstraints;
 203.112 +
 203.113 +        scrollPane = new javax.swing.JScrollPane();
 203.114 +        panel1 = new javax.swing.JPanel();
 203.115 +        extendsImplemetsKeywordLabel = new javax.swing.JLabel();
 203.116 +        extendsImplementsKeywordCombo = new javax.swing.JComboBox();
 203.117 +        extendsImplementsListLabel = new javax.swing.JLabel();
 203.118 +        extendsImplementsListCombo = new javax.swing.JComboBox();
 203.119 +        methodParamsLabel = new javax.swing.JLabel();
 203.120 +        methodParamsCombo = new javax.swing.JComboBox();
 203.121 +        methodCallArgsLabel = new javax.swing.JLabel();
 203.122 +        methodCallArgsCombo = new javax.swing.JComboBox();
 203.123 +        annotationArgsLabel = new javax.swing.JLabel();
 203.124 +        annotationArgsCombo = new javax.swing.JComboBox();
 203.125 +        chainedMethodCallsLabel = new javax.swing.JLabel();
 203.126 +        chainedMethodCallsCombo = new javax.swing.JComboBox();
 203.127 +        throwsKeywordLabel = new javax.swing.JLabel();
 203.128 +        throwsKeywordCombo = new javax.swing.JComboBox();
 203.129 +        throwsListLabel = new javax.swing.JLabel();
 203.130 +        throwsListCombo = new javax.swing.JComboBox();
 203.131 +        arrayInitLabel = new javax.swing.JLabel();
 203.132 +        arrayInitCombo = new javax.swing.JComboBox();
 203.133 +        forLabel = new javax.swing.JLabel();
 203.134 +        forCombo = new javax.swing.JComboBox();
 203.135 +        forStatementLabel = new javax.swing.JLabel();
 203.136 +        forStatementCombo = new javax.swing.JComboBox();
 203.137 +        ifStatementLabel = new javax.swing.JLabel();
 203.138 +        ifStatementCombo = new javax.swing.JComboBox();
 203.139 +        whileStatementLabel = new javax.swing.JLabel();
 203.140 +        whileStatementComboBox = new javax.swing.JComboBox();
 203.141 +        doWhileStatementLabel = new javax.swing.JLabel();
 203.142 +        doWhileStatementCombo = new javax.swing.JComboBox();
 203.143 +        assertLabel = new javax.swing.JLabel();
 203.144 +        assertCombo = new javax.swing.JComboBox();
 203.145 +        enumConstantsLabel = new javax.swing.JLabel();
 203.146 +        enumConstantsCombo = new javax.swing.JComboBox();
 203.147 +        annotationsLabel = new javax.swing.JLabel();
 203.148 +        annotationsCombo = new javax.swing.JComboBox();
 203.149 +        binaryOpsLabel = new javax.swing.JLabel();
 203.150 +        binaryOpsCombo = new javax.swing.JComboBox();
 203.151 +        ternaryOpsLabel = new javax.swing.JLabel();
 203.152 +        ternaryOpsCombo = new javax.swing.JComboBox();
 203.153 +        assignOpsLabel = new javax.swing.JLabel();
 203.154 +        assignOpsCombo = new javax.swing.JComboBox();
 203.155 +        spacerPanel1 = new javax.swing.JPanel();
 203.156 +
 203.157 +        setName(org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_Wrapping")); // NOI18N
 203.158 +        setOpaque(false);
 203.159 +        setLayout(new java.awt.BorderLayout());
 203.160 +
 203.161 +        scrollPane.setMinimumSize(new java.awt.Dimension(300, 200));
 203.162 +        scrollPane.setPreferredSize(new java.awt.Dimension(350, 600));
 203.163 +
 203.164 +        panel1.setOpaque(false);
 203.165 +        panel1.setLayout(new java.awt.GridBagLayout());
 203.166 +
 203.167 +        extendsImplemetsKeywordLabel.setLabelFor(extendsImplementsKeywordCombo);
 203.168 +        org.openide.awt.Mnemonics.setLocalizedText(extendsImplemetsKeywordLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_extendsImplementsKeyword")); // NOI18N
 203.169 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.170 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.171 +        gridBagConstraints.insets = new java.awt.Insets(8, 8, 4, 0);
 203.172 +        panel1.add(extendsImplemetsKeywordLabel, gridBagConstraints);
 203.173 +
 203.174 +        extendsImplementsKeywordCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.175 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.176 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.177 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.178 +        gridBagConstraints.weightx = 1.0;
 203.179 +        gridBagConstraints.insets = new java.awt.Insets(8, 6, 4, 8);
 203.180 +        panel1.add(extendsImplementsKeywordCombo, gridBagConstraints);
 203.181 +
 203.182 +        extendsImplementsListLabel.setLabelFor(extendsImplementsListCombo);
 203.183 +        org.openide.awt.Mnemonics.setLocalizedText(extendsImplementsListLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_extendsImplementsList")); // NOI18N
 203.184 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.185 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.186 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.187 +        panel1.add(extendsImplementsListLabel, gridBagConstraints);
 203.188 +
 203.189 +        extendsImplementsListCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.190 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.191 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.192 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.193 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.194 +        panel1.add(extendsImplementsListCombo, gridBagConstraints);
 203.195 +
 203.196 +        methodParamsLabel.setLabelFor(methodParamsCombo);
 203.197 +        org.openide.awt.Mnemonics.setLocalizedText(methodParamsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_methodParameters")); // NOI18N
 203.198 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.199 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.200 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.201 +        panel1.add(methodParamsLabel, gridBagConstraints);
 203.202 +
 203.203 +        methodParamsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.204 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.205 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.206 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.207 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.208 +        panel1.add(methodParamsCombo, gridBagConstraints);
 203.209 +
 203.210 +        methodCallArgsLabel.setLabelFor(methodCallArgsCombo);
 203.211 +        org.openide.awt.Mnemonics.setLocalizedText(methodCallArgsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_methodCallArgs")); // NOI18N
 203.212 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.213 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.214 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.215 +        panel1.add(methodCallArgsLabel, gridBagConstraints);
 203.216 +
 203.217 +        methodCallArgsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.218 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.219 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.220 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.221 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.222 +        panel1.add(methodCallArgsCombo, gridBagConstraints);
 203.223 +
 203.224 +        annotationArgsLabel.setLabelFor(annotationArgsCombo);
 203.225 +        org.openide.awt.Mnemonics.setLocalizedText(annotationArgsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_annotationArgs")); // NOI18N
 203.226 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.227 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.228 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.229 +        panel1.add(annotationArgsLabel, gridBagConstraints);
 203.230 +
 203.231 +        annotationArgsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.232 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.233 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.234 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.235 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.236 +        panel1.add(annotationArgsCombo, gridBagConstraints);
 203.237 +
 203.238 +        chainedMethodCallsLabel.setLabelFor(chainedMethodCallsCombo);
 203.239 +        org.openide.awt.Mnemonics.setLocalizedText(chainedMethodCallsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_chainedMethodCalls")); // NOI18N
 203.240 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.241 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.242 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.243 +        panel1.add(chainedMethodCallsLabel, gridBagConstraints);
 203.244 +
 203.245 +        chainedMethodCallsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.246 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.247 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.248 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.249 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.250 +        panel1.add(chainedMethodCallsCombo, gridBagConstraints);
 203.251 +
 203.252 +        throwsKeywordLabel.setLabelFor(throwsKeywordCombo);
 203.253 +        org.openide.awt.Mnemonics.setLocalizedText(throwsKeywordLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_throwsKeyword")); // NOI18N
 203.254 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.255 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.256 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.257 +        panel1.add(throwsKeywordLabel, gridBagConstraints);
 203.258 +
 203.259 +        throwsKeywordCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.260 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.261 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.262 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.263 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.264 +        panel1.add(throwsKeywordCombo, gridBagConstraints);
 203.265 +
 203.266 +        throwsListLabel.setLabelFor(throwsListCombo);
 203.267 +        org.openide.awt.Mnemonics.setLocalizedText(throwsListLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_throwsList")); // NOI18N
 203.268 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.269 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.270 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.271 +        panel1.add(throwsListLabel, gridBagConstraints);
 203.272 +
 203.273 +        throwsListCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.274 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.275 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.276 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.277 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.278 +        panel1.add(throwsListCombo, gridBagConstraints);
 203.279 +
 203.280 +        arrayInitLabel.setLabelFor(arrayInitCombo);
 203.281 +        org.openide.awt.Mnemonics.setLocalizedText(arrayInitLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_arrayInit")); // NOI18N
 203.282 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.283 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.284 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.285 +        panel1.add(arrayInitLabel, gridBagConstraints);
 203.286 +
 203.287 +        arrayInitCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.288 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.289 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.290 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.291 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.292 +        panel1.add(arrayInitCombo, gridBagConstraints);
 203.293 +
 203.294 +        forLabel.setLabelFor(forCombo);
 203.295 +        org.openide.awt.Mnemonics.setLocalizedText(forLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_for")); // NOI18N
 203.296 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.297 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.298 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.299 +        panel1.add(forLabel, gridBagConstraints);
 203.300 +
 203.301 +        forCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.302 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.303 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.304 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.305 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.306 +        panel1.add(forCombo, gridBagConstraints);
 203.307 +
 203.308 +        forStatementLabel.setLabelFor(forStatementCombo);
 203.309 +        org.openide.awt.Mnemonics.setLocalizedText(forStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_forStatement")); // NOI18N
 203.310 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.311 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.312 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.313 +        panel1.add(forStatementLabel, gridBagConstraints);
 203.314 +
 203.315 +        forStatementCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.316 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.317 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.318 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.319 +        gridBagConstraints.weightx = 1.0;
 203.320 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.321 +        panel1.add(forStatementCombo, gridBagConstraints);
 203.322 +
 203.323 +        ifStatementLabel.setLabelFor(ifStatementCombo);
 203.324 +        org.openide.awt.Mnemonics.setLocalizedText(ifStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_ifStatement")); // NOI18N
 203.325 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.326 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.327 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.328 +        panel1.add(ifStatementLabel, gridBagConstraints);
 203.329 +
 203.330 +        ifStatementCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.331 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.332 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.333 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.334 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.335 +        panel1.add(ifStatementCombo, gridBagConstraints);
 203.336 +
 203.337 +        whileStatementLabel.setLabelFor(whileStatementComboBox);
 203.338 +        org.openide.awt.Mnemonics.setLocalizedText(whileStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_whileStatement")); // NOI18N
 203.339 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.340 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.341 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.342 +        panel1.add(whileStatementLabel, gridBagConstraints);
 203.343 +
 203.344 +        whileStatementComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.345 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.346 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.347 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.348 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.349 +        panel1.add(whileStatementComboBox, gridBagConstraints);
 203.350 +
 203.351 +        doWhileStatementLabel.setLabelFor(doWhileStatementCombo);
 203.352 +        org.openide.awt.Mnemonics.setLocalizedText(doWhileStatementLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_doWhileStatement")); // NOI18N
 203.353 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.354 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.355 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.356 +        panel1.add(doWhileStatementLabel, gridBagConstraints);
 203.357 +
 203.358 +        doWhileStatementCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.359 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.360 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.361 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.362 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.363 +        panel1.add(doWhileStatementCombo, gridBagConstraints);
 203.364 +
 203.365 +        assertLabel.setLabelFor(assertCombo);
 203.366 +        org.openide.awt.Mnemonics.setLocalizedText(assertLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_assert")); // NOI18N
 203.367 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.368 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.369 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.370 +        panel1.add(assertLabel, gridBagConstraints);
 203.371 +
 203.372 +        assertCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.373 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.374 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.375 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.376 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.377 +        panel1.add(assertCombo, gridBagConstraints);
 203.378 +
 203.379 +        enumConstantsLabel.setLabelFor(enumConstantsCombo);
 203.380 +        org.openide.awt.Mnemonics.setLocalizedText(enumConstantsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_enumConstants")); // NOI18N
 203.381 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.382 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.383 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.384 +        panel1.add(enumConstantsLabel, gridBagConstraints);
 203.385 +
 203.386 +        enumConstantsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.387 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.388 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.389 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.390 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.391 +        panel1.add(enumConstantsCombo, gridBagConstraints);
 203.392 +
 203.393 +        annotationsLabel.setLabelFor(annotationsCombo);
 203.394 +        org.openide.awt.Mnemonics.setLocalizedText(annotationsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_annotations")); // NOI18N
 203.395 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.396 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.397 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.398 +        panel1.add(annotationsLabel, gridBagConstraints);
 203.399 +
 203.400 +        annotationsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.401 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.402 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.403 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.404 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.405 +        panel1.add(annotationsCombo, gridBagConstraints);
 203.406 +
 203.407 +        binaryOpsLabel.setLabelFor(binaryOpsCombo);
 203.408 +        org.openide.awt.Mnemonics.setLocalizedText(binaryOpsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_binaryOps")); // NOI18N
 203.409 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.410 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.411 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.412 +        panel1.add(binaryOpsLabel, gridBagConstraints);
 203.413 +
 203.414 +        binaryOpsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.415 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.416 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.417 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.418 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.419 +        panel1.add(binaryOpsCombo, gridBagConstraints);
 203.420 +
 203.421 +        ternaryOpsLabel.setLabelFor(ternaryOpsCombo);
 203.422 +        org.openide.awt.Mnemonics.setLocalizedText(ternaryOpsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_ternaryOps")); // NOI18N
 203.423 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.424 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.425 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.426 +        panel1.add(ternaryOpsLabel, gridBagConstraints);
 203.427 +
 203.428 +        ternaryOpsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.429 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.430 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.431 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.432 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.433 +        panel1.add(ternaryOpsCombo, gridBagConstraints);
 203.434 +
 203.435 +        assignOpsLabel.setLabelFor(assignOpsCombo);
 203.436 +        org.openide.awt.Mnemonics.setLocalizedText(assignOpsLabel, org.openide.util.NbBundle.getMessage(FmtWrapping.class, "LBL_wrp_assignOps")); // NOI18N
 203.437 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.438 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
 203.439 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 4, 0);
 203.440 +        panel1.add(assignOpsLabel, gridBagConstraints);
 203.441 +
 203.442 +        assignOpsCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
 203.443 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.444 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.445 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 203.446 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 4, 8);
 203.447 +        panel1.add(assignOpsCombo, gridBagConstraints);
 203.448 +
 203.449 +        spacerPanel1.setOpaque(false);
 203.450 +        gridBagConstraints = new java.awt.GridBagConstraints();
 203.451 +        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
 203.452 +        gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER;
 203.453 +        gridBagConstraints.weighty = 1.0;
 203.454 +        gridBagConstraints.insets = new java.awt.Insets(0, 8, 0, 8);
 203.455 +        panel1.add(spacerPanel1, gridBagConstraints);
 203.456 +
 203.457 +        scrollPane.setViewportView(panel1);
 203.458 +
 203.459 +        add(scrollPane, java.awt.BorderLayout.CENTER);
 203.460 +    }// </editor-fold>//GEN-END:initComponents
 203.461 +    
 203.462 +    // Variables declaration - do not modify//GEN-BEGIN:variables
 203.463 +    private javax.swing.JComboBox annotationArgsCombo;
 203.464 +    private javax.swing.JLabel annotationArgsLabel;
 203.465 +    private javax.swing.JComboBox annotationsCombo;
 203.466 +    private javax.swing.JLabel annotationsLabel;
 203.467 +    private javax.swing.JComboBox arrayInitCombo;
 203.468 +    private javax.swing.JLabel arrayInitLabel;
 203.469 +    private javax.swing.JComboBox assertCombo;
 203.470 +    private javax.swing.JLabel assertLabel;
 203.471 +    private javax.swing.JComboBox assignOpsCombo;
 203.472 +    private javax.swing.JLabel assignOpsLabel;
 203.473 +    private javax.swing.JComboBox binaryOpsCombo;
 203.474 +    private javax.swing.JLabel binaryOpsLabel;
 203.475 +    private javax.swing.JComboBox chainedMethodCallsCombo;
 203.476 +    private javax.swing.JLabel chainedMethodCallsLabel;
 203.477 +    private javax.swing.JComboBox doWhileStatementCombo;
 203.478 +    private javax.swing.JLabel doWhileStatementLabel;
 203.479 +    private javax.swing.JComboBox enumConstantsCombo;
 203.480 +    private javax.swing.JLabel enumConstantsLabel;
 203.481 +    private javax.swing.JComboBox extendsImplementsKeywordCombo;
 203.482 +    private javax.swing.JComboBox extendsImplementsListCombo;
 203.483 +    private javax.swing.JLabel extendsImplementsListLabel;
 203.484 +    private javax.swing.JLabel extendsImplemetsKeywordLabel;
 203.485 +    private javax.swing.JComboBox forCombo;
 203.486 +    private javax.swing.JLabel forLabel;
 203.487 +    private javax.swing.JComboBox forStatementCombo;
 203.488 +    private javax.swing.JLabel forStatementLabel;
 203.489 +    private javax.swing.JComboBox ifStatementCombo;
 203.490 +    private javax.swing.JLabel ifStatementLabel;
 203.491 +    private javax.swing.JComboBox methodCallArgsCombo;
 203.492 +    private javax.swing.JLabel methodCallArgsLabel;
 203.493 +    private javax.swing.JComboBox methodParamsCombo;
 203.494 +    private javax.swing.JLabel methodParamsLabel;
 203.495 +    private javax.swing.JPanel panel1;
 203.496 +    private javax.swing.JScrollPane scrollPane;
 203.497 +    private javax.swing.JPanel spacerPanel1;
 203.498 +    private javax.swing.JComboBox ternaryOpsCombo;
 203.499 +    private javax.swing.JLabel ternaryOpsLabel;
 203.500 +    private javax.swing.JComboBox throwsKeywordCombo;
 203.501 +    private javax.swing.JLabel throwsKeywordLabel;
 203.502 +    private javax.swing.JComboBox throwsListCombo;
 203.503 +    private javax.swing.JLabel throwsListLabel;
 203.504 +    private javax.swing.JComboBox whileStatementComboBox;
 203.505 +    private javax.swing.JLabel whileStatementLabel;
 203.506 +    // End of variables declaration//GEN-END:variables
 203.507 +    
 203.508 +}
   204.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   204.2 +++ b/python.source/src/org/netbeans/modules/python/source/ui/NumericKeyListener.java	Mon Sep 21 13:01:16 2015 +0200
   204.3 @@ -0,0 +1,74 @@
   204.4 +/*
   204.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   204.6 + *
   204.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
   204.8 + *
   204.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  204.10 + * Other names may be trademarks of their respective owners.
  204.11 + *
  204.12 + * The contents of this file are subject to the terms of either the GNU
  204.13 + * General Public License Version 2 only ("GPL") or the Common
  204.14 + * Development and Distribution License("CDDL") (collectively, the
  204.15 + * "License"). You may not use this file except in compliance with the
  204.16 + * License. You can obtain a copy of the License at
  204.17 + * http://www.netbeans.org/cddl-gplv2.html
  204.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  204.19 + * specific language governing permissions and limitations under the
  204.20 + * License.  When distributing the software, include this License Header
  204.21 + * Notice in each file and include the License file at
  204.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  204.23 + * particular file as subject to the "Classpath" exception as provided
  204.24 + * by Oracle in the GPL Version 2 section of the License file that
  204.25 + * accompanied this code. If applicable, add the following below the
  204.26 + * License Header, with the fields enclosed by brackets [] replaced by
  204.27 + * your own identifying information:
  204.28 + * "Portions Copyrighted [year] [name of copyright owner]"
  204.29 + *
  204.30 + * If you wish your version of this file to be governed by only the CDDL
  204.31 + * or only the GPL Version 2, indicate your decision by adding
  204.32 + * "[Contributor] elects to include this software in this distribution
  204.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
  204.34 + * single choice of license, a recipient has the option to distribute
  204.35 + * your version of this file under either the CDDL, the GPL Version 2 or
  204.36 + * to extend the choice of license to its licensees as provided above.
  204.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
  204.38 + * Version 2 license, then the option applies only if the new code is
  204.39 + * made subject to such option by the copyright holder.
  204.40 + *
  204.41 + * Contributor(s):
  204.42 + *
  204.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
  204.44 + */
  204.45 +package org.netbeans.modules.python.editor.options;
  204.46 +
  204.47 +import java.awt.Component;
  204.48 +import java.awt.event.KeyEvent;
  204.49 +import java.awt.event.KeyListener;
  204.50 +
  204.51 +/**
  204.52 + *
  204.53 + * @author tester
  204.54 + */
  204.55 +public class NumericKeyListener implements KeyListener {
  204.56 +    public NumericKeyListener() {
  204.57 +    }
  204.58 +
  204.59 +    @Override
  204.60 +    public void keyPressed(KeyEvent evt) {
  204.61 +    }
  204.62 +
  204.63 +    @Override
  204.64 +    public void keyReleased(KeyEvent evt) {
  204.65 +    }
  204.66 +
  204.67 +    @Override
  204.68 +    public void keyTyped(KeyEvent evt) {
  204.69 +        if (!Character.isDigit(evt.getKeyChar()) && !Character.isISOControl(evt.getKeyChar())) {
  204.70 +            evt.consume();
  204.71 +            Component c = evt.getComponent();
  204.72 +            if (c != null) {
  204.73 +                c.getToolkit().beep();
  204.74 +            }
  204.75 +        }
  204.76 +    }
  204.77 +}