// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.collide.client.code.autocomplete.codegraph; import static com.google.collide.client.codeunderstanding.CodeGraphTestUtils.createCodeBlock; import static com.google.collide.client.codeunderstanding.CodeGraphTestUtils.createInheritanceAssociation; import static com.google.collide.client.codeunderstanding.CodeGraphTestUtils.createRootImportAssociation; import static com.google.collide.client.codeunderstanding.CodeGraphTestUtils.createTypeAssociation; import com.google.collide.client.code.autocomplete.TestUtils; import com.google.collide.client.testutil.SynchronousTestCase; import com.google.collide.client.util.PathUtil; import com.google.collide.codemirror2.SyntaxType; import com.google.collide.dto.CodeBlock; import com.google.collide.dto.ImportAssociation; import com.google.collide.dto.client.DtoClientImpls.CodeGraphImpl; import com.google.collide.json.client.JsoArray; import com.google.collide.json.client.JsoStringMap; import com.google.collide.shared.util.JsonCollections; import org.junit.Ignore; /** * Tests for code block => autocomplete proposal translator. */ public class CodeGraphPrefixIndexTest extends SynchronousTestCase { @Override public String getModuleName() { return "com.google.collide.client.TestCode"; } public void testCaseInsensitiveSearch() { CodeBlock fileBar = createCodeBlock("1", "/bar.js", CodeBlock.Type.FILE, 0, 0, 0, 99); CodeBlock varBar = createCodeBlock(fileBar, "11", "Bar", CodeBlock.Type.FIELD, 0, 0, 0, 99); createCodeBlock(fileBar, "12", "doThis", CodeBlock.Type.FUNCTION, 1, 0, 10, 99); createCodeBlock(fileBar, "13", "doThat", CodeBlock.Type.FUNCTION, 11, 0, 20, 99); JsoStringMap<CodeBlock> files = JsoStringMap.<CodeBlock>create(); files.put(fileBar.getName(), fileBar); CodeGraphImpl codeGraph = CodeGraphImpl.make(); codeGraph.setCodeBlockMap(files); CodeGraphPrefixIndex prefixIndex = new CodeGraphPrefixIndex(codeGraph, SyntaxType.JS); assertEquals(JsonCollections.createStringSet("doThat", "doThis"), TestUtils.createNameSet(prefixIndex.search("dot"))); } public void testTypeAssociations() { /* * /bar.js: * * Bar { * doThis: function() {}, * doThat: function() {} * } */ CodeBlock fileBar = createCodeBlock("1", "/bar.js", CodeBlock.Type.FILE, 0, 0, 0, 99); CodeBlock varBar = createCodeBlock(fileBar, "11", "Bar", CodeBlock.Type.FIELD, 0, 0, 0, 99); createCodeBlock(fileBar, "12", "Bar.doThis", CodeBlock.Type.FUNCTION, 1, 0, 10, 99); createCodeBlock(fileBar, "13", "Bar.doThat", CodeBlock.Type.FUNCTION, 11, 0, 20, 99); /* * /foo.js: * * // @type {Bar} * var Foo; */ CodeBlock fileFoo = createCodeBlock("0", "/foo.js", CodeBlock.Type.FILE, 0, 0, 0, 99); CodeBlock varFoo = createCodeBlock("11", "Foo", CodeBlock.Type.FIELD, 0, 0, 0, 99); fileFoo.getChildren().add(varFoo); JsoStringMap<CodeBlock> files = JsoStringMap.<CodeBlock>create(); files.put(fileBar.getName(), fileBar); files.put(fileFoo.getName(), fileFoo); CodeGraphImpl codeGraph = CodeGraphImpl.make(); codeGraph.setCodeBlockMap(files); codeGraph.setTypeAssociations(JsoArray.from( createTypeAssociation(fileFoo, varFoo, fileBar, varBar))); CodeGraphPrefixIndex prefixIndex = new CodeGraphPrefixIndex(codeGraph, SyntaxType.JS); assertEquals(JsonCollections.createStringSet("Foo.doThat", "Foo.doThis"), TestUtils.createNameSet(prefixIndex.search("Foo."))); } @Ignore public void testTypeAssociationChain() { CodeBlock fileFoo = createCodeBlock("0", "/foo.js", CodeBlock.Type.FILE, 0, 0, 99, 0); createCodeBlock(fileFoo, "11", "Foo", CodeBlock.Type.FIELD, 0, 0, 99, 0); CodeBlock typeFoo = createCodeBlock( fileFoo, "12", "Foo.prototype", CodeBlock.Type.FIELD, 0, 0, 99, 0); createCodeBlock(fileFoo, "13", "Foo.prototype.doThis", CodeBlock.Type.FUNCTION, 11, 0, 20, 0); CodeBlock fileBar = createCodeBlock("1", "/bar.js", CodeBlock.Type.FILE, 0, 0, 10, 0); createCodeBlock(fileBar, "11", "Bar", CodeBlock.Type.FIELD, 0, 0, 1, 0); CodeBlock typeBar = createCodeBlock( fileBar, "12", "Bar.prototype", CodeBlock.Type.FIELD, 0, 4, 1, 0); CodeBlock fieldFoo = createCodeBlock( fileBar, "13", "Bar.prototype.foo", CodeBlock.Type.FIELD, 0, 14, 1, 0); CodeBlock varBaz = createCodeBlock(fileBar, "14", "baz", CodeBlock.Type.FIELD, 5, 0, 6, 0); JsoStringMap<CodeBlock> files = JsoStringMap.<CodeBlock>create(); files.put(fileBar.getName(), fileBar); files.put(fileFoo.getName(), fileFoo); CodeGraphImpl codeGraph = CodeGraphImpl.make(); codeGraph.setCodeBlockMap(files); codeGraph.setTypeAssociations(JsoArray.from( createTypeAssociation(fileBar, varBaz, fileBar, typeBar), createTypeAssociation(fileBar, fieldFoo, fileFoo, typeFoo))); CodeGraphPrefixIndex prefixIndex = new CodeGraphPrefixIndex(codeGraph, SyntaxType.JS); assertEquals(JsonCollections.createStringSet("baz.foo.doThis"), TestUtils.createNameSet(prefixIndex.search("baz.foo."))); } public void testMultipleLinkRepresentatives() { /* * /window.js: * * Window.prototype.doThis = function() {} */ CodeBlock fileWindow = createCodeBlock("1", "/bar.js", CodeBlock.Type.FILE, 0, 0, 0, 99); createCodeBlock(fileWindow, "11", "Window", CodeBlock.Type.FIELD, 0, 0, 0, 99); CodeBlock typeWindow = createCodeBlock(fileWindow, "12", "Window.prototype", CodeBlock.Type.FIELD, 0, 0, 0, 99); createCodeBlock(fileWindow, "13", "Window.prototype.doThis", CodeBlock.Type.FUNCTION, 0, 0, 0, 99); /* * /jquery.js: * * Window.prototype.doThat = function() {} */ CodeBlock fileJquery = createCodeBlock("0", "/jquery.js", CodeBlock.Type.FILE, 0, 0, 0, 99); CodeBlock varJqueryWindow = createCodeBlock(fileJquery, "11", "Window", CodeBlock.Type.FIELD, 0, 0, 0, 99); createCodeBlock(fileJquery, "12", "Window.prototype", CodeBlock.Type.FIELD, 0, 0, 0, 99); createCodeBlock(fileJquery, "13", "Window.prototype.doThat", CodeBlock.Type.FUNCTION, 0, 0, 0, 99); /* * /decl.js: * * // @type{Window} * var top; */ CodeBlock fileDecl = createCodeBlock("2", "/decl.js", CodeBlock.Type.FILE, 0, 0, 0, 99); CodeBlock varWindow = createCodeBlock(fileDecl, "11", "top", CodeBlock.Type.FIELD, 0, 0, 0, 99); JsoStringMap<CodeBlock> files = JsoStringMap.<CodeBlock>create(); files.put(fileWindow.getName(), fileWindow); files.put(fileJquery.getName(), fileJquery); files.put(fileDecl.getName(), fileDecl); CodeGraphImpl codeGraph = CodeGraphImpl.make(); codeGraph.setCodeBlockMap(files); codeGraph.setTypeAssociations(JsoArray.from( createTypeAssociation(fileDecl, varWindow, fileWindow, typeWindow))); CodeGraphPrefixIndex prefixIndex = new CodeGraphPrefixIndex(codeGraph, SyntaxType.JS); assertEquals(JsonCollections.createStringSet("top.doThat", "top.doThis"), TestUtils.createNameSet(prefixIndex.search("top."))); } public void testInheritanceAssociations() { /* * /bar.js: * * function Bar() {}; * Bar.prototype.doThis = function() {}; * Bar.prototype.doThat = function() {}; * * // @extends {Bar} * function Foo() {}; * Foo.prototype.doThird = function() {}; */ CodeBlock fileBar = createCodeBlock("1", "/bar.js", CodeBlock.Type.FILE, 0, 0, 0, 99); createCodeBlock(fileBar, "11", "Bar", CodeBlock.Type.FUNCTION, 0, 0, 0, 99); CodeBlock prototypeBar = createCodeBlock( fileBar, "12", "Bar.prototype", CodeBlock.Type.FIELD, 0, 0, 0, 99); createCodeBlock(fileBar, "13", "Bar.prototype.doThis", CodeBlock.Type.FUNCTION, 1, 0, 10, 99); createCodeBlock(fileBar, "14", "Bar.prototype.doThat", CodeBlock.Type.FUNCTION, 11, 0, 20, 99); createCodeBlock(fileBar, "15", "Foo", CodeBlock.Type.FUNCTION, 100, 0, 199, 99); CodeBlock prototypeFoo = createCodeBlock( fileBar, "16", "Foo.prototype", CodeBlock.Type.FIELD, 100, 0, 199, 99); createCodeBlock( fileBar, "17", "Foo.prototype.doThird", CodeBlock.Type.FUNCTION, 101, 0, 120, 99); JsoStringMap<CodeBlock> files = JsoStringMap.<CodeBlock>create(); files.put(fileBar.getName(), fileBar); CodeGraphImpl codeGraph = CodeGraphImpl.make(); codeGraph.setCodeBlockMap(files); codeGraph.setInheritanceAssociations(JsoArray.from( createInheritanceAssociation(fileBar, prototypeFoo, fileBar, prototypeBar))); CodeGraphPrefixIndex prefixIndex = new CodeGraphPrefixIndex(codeGraph, SyntaxType.JS); assertEquals(JsonCollections.createStringSet( "Foo.prototype.doThird", "Foo.prototype.doThis", "Foo.prototype.doThat"), TestUtils.createNameSet(prefixIndex.search("Foo.prototype."))); } public void testRootImportAssociation() { /* * /lib.py: * * def foo: * return 42; */ CodeBlock fileLib = createCodeBlock("1", "/lib.py", CodeBlock.Type.FILE, 0, 0, 0, 99); CodeBlock funFoo = createCodeBlock(fileLib, "11", "foo", CodeBlock.Type.FUNCTION, 0, 0, 0, 99); /* * /api/ext/util.py: * * def bar: * return None; */ CodeBlock fileUtil = createCodeBlock("2", "/api/ext/util.py", CodeBlock.Type.FILE, 0, 0, 0, 99); CodeBlock funBar = createCodeBlock(fileUtil, "11", "bar", CodeBlock.Type.FUNCTION, 0, 0, 0, 99); /* * /main.py: * * import lib * from api.ext import util */ CodeBlock fileMain = createCodeBlock("3", "/main.py", CodeBlock.Type.FILE, 0, 0, 0, 99); ImportAssociation importLib = createRootImportAssociation(fileMain, fileLib); ImportAssociation importUtil = createRootImportAssociation(fileMain, fileUtil); JsoStringMap<CodeBlock> files = JsoStringMap.<CodeBlock>create(); files.put(fileLib.getId(), fileLib); files.put(fileMain.getId(), fileMain); files.put(fileUtil.getId(), fileUtil); CodeGraphImpl codeGraph = CodeGraphImpl.make(); codeGraph.setCodeBlockMap(files); codeGraph.setImportAssociations(JsoArray.from(importLib, importUtil)); CodeGraphPrefixIndex prefixIndex = new CodeGraphPrefixIndex(codeGraph, SyntaxType.PY); assertEquals(JsonCollections.createStringSet("lib.foo"), TestUtils.createNameSet(prefixIndex.search("lib.f"))); assertEquals(JsonCollections.createStringSet("util.bar"), TestUtils.createNameSet(prefixIndex.search("util."))); } public void testNoGlobalNamespace() { /* * /file1.py: * * def foo1: * return 42; */ CodeBlock file1 = createCodeBlock("1", "/file1.py", CodeBlock.Type.FILE, 0, 0, 0, 99); CodeBlock funFoo1 = createCodeBlock(file1, "11", "foo1", CodeBlock.Type.FUNCTION, 0, 0, 0, 99); /* * /file2.py: * * def foo2: * return 24; */ CodeBlock file2 = createCodeBlock("2", "/file2.py", CodeBlock.Type.FILE, 0, 0, 0, 99); CodeBlock funFoo2 = createCodeBlock(file2, "21", "foo2", CodeBlock.Type.FUNCTION, 0, 0, 0, 99); JsoStringMap<CodeBlock> files = JsoStringMap.<CodeBlock>create(); files.put(file1.getId(), file1); files.put(file2.getId(), file2); CodeGraphImpl codeGraph = CodeGraphImpl.make(); codeGraph.setCodeBlockMap(files); CodeGraphPrefixIndex prefixIndex = new CodeGraphPrefixIndex( codeGraph, SyntaxType.PY, new PathUtil("/file1.py")); assertEquals(JsonCollections.createStringSet("foo1"), TestUtils.createNameSet(prefixIndex.search("f"))); } public void testFilesWithSameName() { /* * /file1.py: * * def foo1: * return 1; * * def foo3: * return 3; */ CodeBlock file1a = createCodeBlock("1", "/file1.py", CodeBlock.Type.FILE, 0, 0, 3, 0); CodeBlock funFoo1a = createCodeBlock( file1a, "11", "foo1", CodeBlock.Type.FIELD, 0, 0, 1, 0); CodeBlock funFoo3 = createCodeBlock( file1a, "11", "foo3", CodeBlock.Type.FIELD, 1, 0, 2, 0); /* * /file1.py: * * def foo1: * return 1; * * def foo2: * return 2; */ CodeBlock file1b = createCodeBlock("2", "/file1.py", CodeBlock.Type.FILE, 0, 0, 3, 0); CodeBlock funFoo1b = createCodeBlock( file1b, "21", "foo1", CodeBlock.Type.FUNCTION, 0, 0, 0, 99); CodeBlock funFoo2 = createCodeBlock( file1b, "22", "foo2", CodeBlock.Type.FUNCTION, 1, 0, 1, 99); JsoStringMap<CodeBlock> files = JsoStringMap.<CodeBlock>create(); files.put(file1a.getId(), file1a); files.put(file1b.getId(), file1b); CodeGraphImpl codeGraph = CodeGraphImpl.make(); codeGraph.setCodeBlockMap(files); CodeGraphPrefixIndex prefixIndex = new CodeGraphPrefixIndex( codeGraph, SyntaxType.PY, new PathUtil("/file1.py")); assertEquals(JsonCollections.createStringSet("foo1", "foo2", "foo3"), TestUtils.createNameSet(prefixIndex.search("f"))); } public void testPackages() { CodeBlock defaultPackage = createCodeBlock("p1", "", CodeBlock.Type.PACKAGE, 0, 0, 0, 0); CodeBlock pkgGoogle = createCodeBlock( defaultPackage, "p2", "google", CodeBlock.Type.PACKAGE, 0, 0, 0, 0); CodeBlock pkgAppengine = createCodeBlock( defaultPackage, "p3", "google.appengine", CodeBlock.Type.PACKAGE, 0, 0, 0, 0); CodeBlock pkgExt = createCodeBlock( defaultPackage, "p4", "google.ext", CodeBlock.Type.PACKAGE, 0, 0, 0, 0); CodeGraphImpl codeGraph = CodeGraphImpl.make(); codeGraph.setDefaultPackage(defaultPackage); codeGraph.setCodeBlockMap(JsoStringMap.<CodeBlock>create()); CodeGraphPrefixIndex prefixIndex = new CodeGraphPrefixIndex(codeGraph, SyntaxType.PY); assertEquals(JsonCollections.createStringSet("google"), TestUtils.createNameSet(prefixIndex.search("goo"))); assertEquals(JsonCollections.createStringSet("google.appengine", "google.ext"), TestUtils.createNameSet(prefixIndex.search("google."))); assertEquals(JsonCollections.createStringSet("google.appengine"), TestUtils.createNameSet(prefixIndex.search("google.a"))); assertEquals(JsonCollections.createStringSet("google.ext"), TestUtils.createNameSet(prefixIndex.search("google.e"))); } }