// 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.gotodefinition; import com.google.collide.client.documentparser.DocumentParser; import com.google.collide.client.testing.StubIncrementalScheduler; import com.google.collide.client.testutil.CodeMirrorTestCase; import com.google.collide.client.util.PathUtil; import com.google.collide.client.workspace.FileTreeModel; import com.google.collide.client.workspace.FileTreeNode; import com.google.collide.client.workspace.MockOutgoingController; import com.google.collide.codemirror2.CodeMirror2; import com.google.collide.codemirror2.Token; import com.google.collide.dto.DirInfo; import com.google.collide.json.shared.JsonArray; import com.google.collide.shared.document.Document; import com.google.collide.shared.document.LineInfo; import com.google.gwt.regexp.shared.MatchResult; import javax.annotation.Nullable; /** * Tests for {@link AnchorTagParser}. * */ public class DynamicReferenceProviderTest extends CodeMirrorTestCase { private Document document; private DocumentParser parser; @Override public String getModuleName() { return "com.google.collide.client.TestCode"; } private DynamicReferenceProvider createDynamicReferenceProvider(String path, String source) { PathUtil filePath = new PathUtil(path); document = Document.createFromString(source); parser = DocumentParser.create( document, CodeMirror2.getParser(filePath), new StubIncrementalScheduler(50, 50)); FileTreeNode root = FileTreeNode.transform(buildSimpleTree()); FileTreeModel model = new FileTreeModel(new MockOutgoingController()); model.replaceNode(PathUtil.WORKSPACE_ROOT, root, "1"); return new DynamicReferenceProvider(path, new DeferringLineParser(parser), model, null); } public void testLocalAndAbsoluteFileReferences() { // Some PathUtil sanity tests. String contextPath = "/src/index.html"; PathUtil contextDir = PathUtil.createExcludingLastN(new PathUtil(contextPath), 1); assertEquals("/src", contextDir.getPathString()); PathUtil filePathInContextDir = PathUtil.concatenate(contextDir, new PathUtil("foo.js")); assertEquals("/src/foo.js", filePathInContextDir.getPathString()); DynamicReferenceProvider provider = createDynamicReferenceProvider("/index.html", ""); tryFindFileNode(provider, "/asdf.js", null); tryFindFileNode(provider, "asdf.js", null); tryFindFileNode(provider, "/foo.js", "/foo.js"); tryFindFileNode(provider, "foo.js", "/foo.js"); tryFindFileNode(provider, "/src/world.js", "/src/world.js"); tryFindFileNode(provider, "src/world.js", "/src/world.js"); provider = createDynamicReferenceProvider("/src/index.html", ""); tryFindFileNode(provider, "/asdf.js", null); tryFindFileNode(provider, "asdf.js", null); tryFindFileNode(provider, "/foo.js", "/foo.js"); tryFindFileNode(provider, "foo.js", null); tryFindFileNode(provider, "world.js", "/src/world.js"); tryFindFileNode(provider, "/src/world.js", "/src/world.js"); tryFindFileNode(provider, "src/world.js", null); } private void tryFindFileNode(DynamicReferenceProvider provider, String displayPath, @Nullable String expectedFileNodePath) { FileTreeNode fileNode = provider.findFileNode(displayPath); if (expectedFileNodePath == null) { assertNull(fileNode); } else { assertEquals(expectedFileNodePath, fileNode.getNodePath().getPathString()); } } public void testUrlReference() { String url1 = "http://www.google.com/"; String url2 = "http://www.ru/?q=1&p=2"; String url3 = "https://somesafeurl.com"; String beforeUrl1Text = "/* start "; String middleText = " text "; DynamicReferenceProvider dynamicReferenceProvider = createDynamicReferenceProvider("test.js", "" + beforeUrl1Text + url1 + middleText + url2 + ". */\n" + "var a = 5;\n" + "// " + url3 + ".\n"); int url1StartColumn = beforeUrl1Text.length(); tryDynamicUrlReference(dynamicReferenceProvider, 0, url1StartColumn - 1, -1, null); tryDynamicUrlReference(dynamicReferenceProvider, 0, url1StartColumn, url1StartColumn, url1); tryDynamicUrlReference( dynamicReferenceProvider, 0, url1StartColumn + url1.length() - 1, url1StartColumn, url1); tryDynamicUrlReference(dynamicReferenceProvider, 0, url1StartColumn + url1.length(), -1, null); int url2StartColumn = url1StartColumn + url1.length() + middleText.length(); tryDynamicUrlReference(dynamicReferenceProvider, 0, url2StartColumn - 1, -1, null); tryDynamicUrlReference(dynamicReferenceProvider, 0, url2StartColumn, url2StartColumn, url2); tryDynamicUrlReference( dynamicReferenceProvider, 0, url2StartColumn + url2.length() - 1, url2StartColumn, url2); tryDynamicUrlReference(dynamicReferenceProvider, 0, url2StartColumn + url2.length(), -1, null); // Need to parse line 1 (second line), otherwise parseLineSync returns null for line 2. tryDynamicUrlReference(dynamicReferenceProvider, 1, 0, -1, null); int url3StartColumn = 3; tryDynamicUrlReference(dynamicReferenceProvider, 2, url3StartColumn - 1, -1, null); tryDynamicUrlReference(dynamicReferenceProvider, 2, url3StartColumn, url3StartColumn, url3); tryDynamicUrlReference( dynamicReferenceProvider, 2, url3StartColumn + url3.length() - 1, url3StartColumn, url3); tryDynamicUrlReference(dynamicReferenceProvider, 2, url3StartColumn + url3.length(), -1, null); } private void tryDynamicUrlReference(DynamicReferenceProvider provider, int lineNumber, int column, int referenceStartColumn, @Nullable String url) { LineInfo lineInfo = document.getLineFinder().findLine(lineNumber); assertNotNull(lineInfo); JsonArray<Token> tokens = parser.parseLineSync(lineInfo.line()); if (tokens == null) { throw new RuntimeException(lineInfo.line().getText()); } assertNotNull(tokens); NavigableReference.UrlReference reference = (NavigableReference.UrlReference) provider.getReferenceAt(lineInfo, column, tokens); if (url == null) { assertNull(reference); } else { assertNotNull(reference); assertEquals(lineNumber, reference.getLineNumber()); assertEquals(referenceStartColumn, reference.getStartColumn()); assertEquals(url, reference.getUrl()); } } public void testLocalFileReference() { DynamicReferenceProvider dynamicReferenceProvider = createDynamicReferenceProvider("test.html", "<script src=\"foo.js\"></script>"); tryDynamicFileReference(dynamicReferenceProvider, 0, 12, -1, null); tryDynamicFileReference(dynamicReferenceProvider, 0, 13, 13, "/foo.js"); tryDynamicFileReference(dynamicReferenceProvider, 0, 18, 13, "/foo.js"); tryDynamicFileReference(dynamicReferenceProvider, 0, 19, -1, null); dynamicReferenceProvider = createDynamicReferenceProvider("/src/test.html", "<script src=\"world.js\"></script>"); tryDynamicFileReference(dynamicReferenceProvider, 0, 12, -1, null); tryDynamicFileReference(dynamicReferenceProvider, 0, 13, 13, "/src/world.js"); tryDynamicFileReference(dynamicReferenceProvider, 0, 20, 13, "/src/world.js"); tryDynamicFileReference(dynamicReferenceProvider, 0, 21, -1, null); } private void tryDynamicFileReference(DynamicReferenceProvider provider, int lineNumber, int column, int referenceStartColumn, @Nullable String filePath) { LineInfo lineInfo = document.getLineFinder().findLine(lineNumber); JsonArray<Token> tokens = parser.parseLineSync(lineInfo.line()); NavigableReference.FileReference reference = (NavigableReference.FileReference) provider.getReferenceAt(lineInfo, column, tokens); if (filePath == null) { assertNull(reference); } else { assertNotNull(reference); assertEquals(lineNumber, reference.getLineNumber()); assertEquals(referenceStartColumn, reference.getStartColumn()); assertEquals(filePath, reference.getTargetFilePath()); } } public void testUrlMatches() { tryMatchUrl("sdf http://www.google.com/ alsg", "http://www.google.com/"); tryMatchUrl("http://www.google.com.", "http://www.google.com"); tryMatchUrl("a www.google.com", null); tryMatchUrl("ftp://192.168.1.1:23/somepath/.", "ftp://192.168.1.1:23/somepath/"); tryMatchUrl("adflkhttp://www.google.com/asdg", null); tryMatchUrl("http://www.ru?1=2&2=3 text", "http://www.ru?1=2&2=3"); tryMatchUrl("text1.http://go/someplace#url=test.", "http://go/someplace#url=test"); tryMatchUrl("<a href='ftp://myawesomeftp.com/'>link</a>", "ftp://myawesomeftp.com/"); tryMatchUrl("<img src=\"http://somedomain.com/somepath/someimage.jpg\">", "http://somedomain.com/somepath/someimage.jpg"); tryMatchUrl("many whitespaces http://www.com/path/foo ", "http://www.com/path/foo"); tryMatchUrl("many whitespaces http://www.com/path/img.png text", "http://www.com/path/img.png"); // THE FOLLOWING TEST CASE DOES NOT WORK YET! It takes the end of comment ("*/") as URL. // tryMatchUrl("/* Go to http://www.google.com/.*/", "http://www.google.com/"); } private void tryMatchUrl(String text, @Nullable String url) { DynamicReferenceProvider.REGEXP_URL.setLastIndex(0); MatchResult matchResult = DynamicReferenceProvider.REGEXP_URL.exec(text); if (url == null) { assertNull(matchResult); return; } assertNotNull(matchResult); assertEquals(url, matchResult.getGroup(0)); } /** * Stole from TreeWalkFileNameSearchImpltest */ private final native DirInfo buildSimpleTree() /*-{ return { // Root node is magic nodeType : @com.google.collide.dto.TreeNodeInfo::DIR_TYPE, id : "1", originId : "1", name : "root", files : [ { nodeType : @com.google.collide.dto.TreeNodeInfo::FILE_TYPE, id : "5", originId : "5", name : "foo.js", rootId : "2", path : "/foo.js", size : "1234" } ], isComplete : true, subDirectories : [ { nodeType : @com.google.collide.dto.TreeNodeInfo::DIR_TYPE, id : "2", originId : "2", name : "src", path : "/src", files : [ { nodeType : @com.google.collide.dto.TreeNodeInfo::FILE_TYPE, id : "7", originId : "7", name : "world.js", rootId : "2", path : "/src/world.js", size : "1234" } ], isComplete : true, subDirectories : [] } ] }; }-*/; }