public void TestLocationInMethodDefinition_Cpp() { ////Foo.h //class Foo { //public: // int bar(int); //} var hXml = @"<class pos:line=""1"" pos:column=""1"">class <name pos:line=""1"" pos:column=""7"">Foo</name> <block pos:line=""1"" pos:column=""11"">{<private type=""default"" pos:line=""1"" pos:column=""12""> </private><public pos:line=""2"" pos:column=""1"">public: <function_decl><type><name pos:line=""3"" pos:column=""5"">int</name></type> <name pos:line=""3"" pos:column=""9"">bar</name><parameter_list pos:line=""3"" pos:column=""12"">(<param><decl><type><name pos:line=""3"" pos:column=""13"">int</name></type></decl></param>)</parameter_list>;</function_decl> </public>}</block><decl/></class>"; var hUnit = fileSetup[Language.CPlusPlus].GetFileUnitForXmlSnippet(hXml, "Foo.h"); INamedScope globalScope = parser[Language.CPlusPlus].ParseFileUnit(hUnit); ////Foo.cpp //#include "Foo.h" //int Foo::bar(int baz) { // return baz + 1; //} var cppXml = @"<cpp:include pos:line=""1"" pos:column=""1"">#<cpp:directive pos:line=""1"" pos:column=""2"">include</cpp:directive> <cpp:file><lit:literal type=""string"" pos:line=""1"" pos:column=""10"">""Foo.h""</lit:literal></cpp:file></cpp:include> <function><type><name pos:line=""2"" pos:column=""1"">int</name></type> <name><name pos:line=""2"" pos:column=""5"">Foo</name><op:operator pos:line=""2"" pos:column=""8"">::</op:operator><name pos:line=""2"" pos:column=""10"">bar</name></name><parameter_list pos:line=""2"" pos:column=""13"">(<param><decl><type><name pos:line=""2"" pos:column=""14"">int</name></type> <name pos:line=""2"" pos:column=""18"">baz</name></decl></param>)</parameter_list> <block pos:line=""2"" pos:column=""23"">{ <return pos:line=""3"" pos:column=""5"">return <expr><name pos:line=""3"" pos:column=""12"">baz</name> <op:operator pos:line=""3"" pos:column=""16"">+</op:operator> <lit:literal type=""number"" pos:line=""3"" pos:column=""18"">1</lit:literal></expr>;</return> }</block></function>"; var cppUnit = fileSetup[Language.CPlusPlus].GetFileUnitForXmlSnippet(cppXml, "Foo.cpp"); globalScope = globalScope.Merge(parser[Language.CPlusPlus].ParseFileUnit(cppUnit)) as INamedScope; var bar = globalScope.ChildScopes.First().ChildScopes.OfType <IMethodDefinition>().First(); Assert.AreEqual("bar", bar.Name); Assert.AreEqual(bar, globalScope.GetScopeForLocation(new SourceLocation("Foo.cpp", 3, 2))); }
/// <summary> /// Merges two NamedVariableScopes together. It works like this: <list type="bullet"> /// <item><description>If this is the same type or more specific than /// <paramref name="otherScope"/>, then create a new merged NamedScope from /// <paramref name="otherScope"/>and this.</description></item> <item><description>If /// <paramref name="otherScope"/>is more specific than this, call /// <c>otherScope.Merge</c></description></item> </list> /// </summary> /// <param name="otherScope">The scope to merge with</param> /// <returns>The new merged scope; null if they couldn't be merged</returns> public virtual INamedScope Merge(INamedScope otherScope) { INamedScope mergedScope = null; if (otherScope != null) { if (otherScope.CanBeMergedInto(this)) { // this and other scope can be merged normally either they are the same type or // this is a subclass of NamedScope and otherScope is a NamedScope mergedScope = new NamedScope(this); mergedScope.AddFrom(otherScope); } else if (this.CanBeMergedInto(otherScope) && !otherScope.CanBeMergedInto(this)) { // this is a NamedScope and otherScope is a subclass useful information (type, // method, or namespace data) are in otherScope mergedScope = otherScope.Merge(this); } } return(mergedScope); }