# HG changeset patch # User Jan Lahoda # Date 1311281512 -7200 # Node ID cb630b7113bf663df5c779626e2ff6ebc3841a32 # Parent fcb0069e23c5707522d1b8f87017e6a4d6bc920f bitbucket-20: adding conditions for enclosing class/package (transplanting from trunk). diff -r fcb0069e23c5 -r cb630b7113bf file/src/org/netbeans/modules/jackpot30/file/conditionapi/Context.java --- a/file/src/org/netbeans/modules/jackpot30/file/conditionapi/Context.java Sun Jul 10 21:50:05 2011 +0200 +++ b/file/src/org/netbeans/modules/jackpot30/file/conditionapi/Context.java Thu Jul 21 22:51:52 2011 +0200 @@ -39,6 +39,7 @@ package org.netbeans.modules.jackpot30.file.conditionapi; +import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.Tree.Kind; import com.sun.source.util.TreePath; import java.util.ArrayList; @@ -55,11 +56,13 @@ import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import org.netbeans.api.annotations.common.CheckForNull; import org.netbeans.api.annotations.common.NonNull; import org.netbeans.api.java.queries.SourceLevelQuery; +import org.netbeans.api.java.source.TreeUtilities; import org.netbeans.modules.jackpot30.file.APIAccessor; import org.netbeans.modules.jackpot30.spi.Hacks; import org.netbeans.modules.jackpot30.spi.HintContext; @@ -250,6 +253,46 @@ APIAccessor.IMPL = new APIAccessorImpl(); } + /**Returns canonical names of classes that enclose the {@link Variable}. + * If the given {@link Variable} represents a class, its canonical name is also listed. + * The names are given from the innermost class to the outermost class. + * + * @return the canonical names of the enclosing classes + */ + public @NonNull Iterable enclosingClasses(Variable forVariable) { + List result = new ArrayList(); + TreePath path = getSingleVariable(forVariable); + + while (path != null) { + TreePath current = path; + + path = path.getParentPath(); + + if (!TreeUtilities.CLASS_TREE_KINDS.contains(current.getLeaf().getKind())) continue; + + Element e = ctx.getInfo().getTrees().getElement(current); + + if (e == null) continue; + + if (e.getKind().isClass() || e.getKind().isInterface()) { + result.add(((TypeElement) e).getQualifiedName().toString()); + } + } + + return result; + } + + /**Returns name of package in which the current file is located. Default package + * is represented by an empty string. + * + * @return the name of the enclosing package + */ + public @NonNull String enclosingPackage() { + CompilationUnitTree cut = ctx.getInfo().getCompilationUnit(); + + return cut.getPackageName() != null ? cut.getPackageName().toString() : ""; + } + static final class APIAccessorImpl extends APIAccessor { @Override diff -r fcb0069e23c5 -r cb630b7113bf file/src/org/netbeans/modules/jackpot30/file/conditionapi/DefaultRuleUtilities.java --- a/file/src/org/netbeans/modules/jackpot30/file/conditionapi/DefaultRuleUtilities.java Sun Jul 10 21:50:05 2011 +0200 +++ b/file/src/org/netbeans/modules/jackpot30/file/conditionapi/DefaultRuleUtilities.java Thu Jul 21 22:51:52 2011 +0200 @@ -42,6 +42,7 @@ import java.util.Arrays; import java.util.EnumSet; import java.util.Set; +import java.util.regex.Pattern; import javax.lang.model.SourceVersion; import javax.lang.model.element.ElementKind; import javax.lang.model.element.Modifier; @@ -114,4 +115,51 @@ public boolean containsAny(Variable var, String... patterns) { return matcher.containsAny(var, patterns); } + + /**Tests whether the current occurrences is enclosed (directly or indirectly) + * by any of the specified classes. + * + * @param className canonical class names of possibly enclosing classes + * @return true if and only if the current occurrence is directly or indirectly + * enclosed by any of the given classes. + */ + public boolean inClass(String... className) { + Pattern p = constructRegexp(className); + Variable current = context.variableForName("$_"); + + assert current != null; + + for (String canonicalName : context.enclosingClasses(current)) { + if (p.matcher(canonicalName).matches()) return true; + } + + return false; + } + + /**Tests whether the current occurrences is in any of the given packages. + * + * @param packageName names of possibly enclosing packages + * @return true if and only if the current occurrence is inside any of the + * given packages + */ + public boolean inPackage(String... packageName) { + Pattern p = constructRegexp(packageName); + + return p.matcher(context.enclosingPackage()).matches(); + } + + private static Pattern constructRegexp(String[] pattern) { + StringBuilder regexp = new StringBuilder(); + boolean first = true; + for (String p : pattern) { + if (first) regexp.append("|"); + + regexp.append("("); + regexp.append(Pattern.quote(p)); + regexp.append(")"); + first = false; + } + Pattern p = Pattern.compile(regexp.toString()); + return p; + } } diff -r fcb0069e23c5 -r cb630b7113bf file/test/unit/src/org/netbeans/modules/jackpot30/file/conditionapi/ContextTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/file/test/unit/src/org/netbeans/modules/jackpot30/file/conditionapi/ContextTest.java Thu Jul 21 22:51:52 2011 +0200 @@ -0,0 +1,84 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009-2011 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2009-2011 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.jackpot30.file.conditionapi; + +import com.sun.source.util.TreePath; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; +import org.netbeans.modules.jackpot30.impl.TestBase; +import org.netbeans.modules.jackpot30.spi.HintContext; + +/** + * + * @author lahvac + */ +public class ContextTest extends TestBase { + + public ContextTest(String name) { + super(name); + } + + public void testEnclosingClasses() throws Exception { + String code = "package test; public class Test { public static class X { private int i|i; } }"; + int pos = code.indexOf("|"); + + code = code.replaceAll(Pattern.quote("|"), ""); + + prepareTest("test/Test.java", code); + + TreePath tp = info.getTreeUtilities().pathFor(pos); + Map variables = new HashMap(); + variables.put("$1", tp); + variables.put("$2", tp.getParentPath()); + variables.put("$3", tp.getParentPath().getParentPath()); + Map> multiVariables = Collections.>emptyMap(); + Map variables2Names = Collections.emptyMap(); + Context ctx = new Context(HintContext.create(info, null, null, variables, multiVariables, variables2Names)); + + assertEquals(Arrays.asList("test.Test.X", "test.Test"), ctx.enclosingClasses(new Variable("$1"))); + assertEquals(Arrays.asList("test.Test.X", "test.Test"), ctx.enclosingClasses(new Variable("$2"))); + assertEquals(Arrays.asList("test.Test"), ctx.enclosingClasses(new Variable("$3"))); + } + +} diff -r fcb0069e23c5 -r cb630b7113bf file/test/unit/src/org/netbeans/modules/jackpot30/file/conditionapi/DefaultRuleUtilitiesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/file/test/unit/src/org/netbeans/modules/jackpot30/file/conditionapi/DefaultRuleUtilitiesTest.java Thu Jul 21 22:51:52 2011 +0200 @@ -0,0 +1,77 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + *

+ * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + *

+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + *

+ * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development and + * Distribution License("CDDL") (collectively, the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy of + * the License at http://www.netbeans.org/cddl-gplv2.html or + * nbbuild/licenses/CDDL-GPL-2-CP. See the License for the specific language + * governing permissions and limitations under the License. When distributing + * the software, include this License Header Notice in each file and include + * the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided by + * Oracle in the GPL Version 2 section of the License file that accompanied + * this code. If applicable, add the following below the License Header, with + * the fields enclosed by brackets [] replaced by your own identifying + * information: "Portions Copyrighted [year] [name of copyright owner]" + *

+ * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you do not indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to its + * licensees as provided above. However, if you add GPL Version 2 code and + * therefore, elected the GPL Version 2 license, then the option applies only + * if the new code is made subject to such option by the copyright holder. + *

+ * Contributor(s): + *

+ * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.modules.jackpot30.file.conditionapi; + +import com.sun.source.util.TreePath; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.regex.Pattern; +import org.netbeans.modules.jackpot30.impl.TestBase; +import org.netbeans.modules.jackpot30.spi.HintContext; + +/** + * + * @author lahvac + */ +public class DefaultRuleUtilitiesTest extends TestBase { + + public DefaultRuleUtilitiesTest(String name) { + super(name); + } + + public void testEnclosingClasses() throws Exception { + String code = "package test; public class Test { public static class X { private int i|i; } }"; + int pos = code.indexOf("|"); + + code = code.replaceAll(Pattern.quote("|"), ""); + + prepareTest("test/Test.java", code); + + TreePath tp = info.getTreeUtilities().pathFor(pos); + Map variables = Collections.emptyMap(); + Map> multiVariables = Collections.>emptyMap(); + Map variables2Names = Collections.emptyMap(); + Context ctx = new Context(HintContext.create(info, null, tp, variables, multiVariables, variables2Names)); + DefaultRuleUtilities utils = new DefaultRuleUtilities(ctx, new Matcher(ctx)); + + assertTrue(utils.inClass("test.Test.X")); + assertTrue(utils.inClass("test.Test")); + assertFalse(utils.inClass("test.TestA")); + } +}