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> /// Checks to see if this is an alias for /// <paramref name="namedScope"/></summary> /// <param name="namedScope">The named scope to check</param> /// <returns>True if this alias can apply to the provided named scope; false /// otherwise</returns> public bool IsAliasFor(INamedScope namedScope) { if (this.IsNamespaceImport) { return(true); } return(false); }
/// <summary> /// Small helper that works like <see cref="HashSet{T}.Add(T)"/> on the <see cref="INamedScope.Memory"/> /// dictionary. /// </summary> /// <param name="this">This scope.</param> /// <param name="key">The memory key. Must not be null or empty.</param> /// <returns>True if the key is new to the memory (and has been added), false if the key is already known.</returns> public static bool MemorizeOnce(this INamedScope @this, string key) { if (String.IsNullOrEmpty(key)) { throw new ArgumentException("Key must not be null or white space.", nameof(key)); } return(@this.Memory.TryAdd(key, null)); }
private static bool TestEquality(INamedScope a, INamedScope b) { //Assert.AreEqual(a.Name, b.Name); ////Accessibility isn't undone right now, so don't check it ////Assert.AreEqual(a.Accessibility, b.Accessibility); //Assert.IsTrue(CollectionsAreEqual(a.ParentScopeCandidates, b.ParentScopeCandidates, NamedScopeUsesAreEqual)); //Assert.IsTrue(NamedScopeUsesAreEqual(a.UnresolvedParentScopeInUse, b.UnresolvedParentScopeInUse)); //return TestEquality((Scope)a, (Scope)b); return(a.Name == b.Name && CollectionsAreEqual(a.ParentScopeCandidates, b.ParentScopeCandidates, NamedScopeUsesAreEqual) && NamedScopeUsesAreEqual(a.UnresolvedParentScopeInUse, b.UnresolvedParentScopeInUse) && TestEquality((Scope)a, (Scope)b)); }
/// <summary> /// Merges this namespace definition with /// <paramref name="otherScope"/>. This happens when <c>otherScope.CanBeMergedInto(this)</c> /// evaluates to true. /// </summary> /// <param name="otherScope">the scope to merge with</param> /// <returns>a new namespace definition from this and otherScope, or null if they couldn't /// be merged.</returns> public override INamedScope Merge(INamedScope otherScope) { NamespaceDefinition mergedScope = null; if (otherScope != null) { if (otherScope.CanBeMergedInto(this)) { mergedScope = new NamespaceDefinition(this); mergedScope.AddFrom(otherScope); } } return(mergedScope); }
internal FunctionScopeImpl(CodeWorkspaceImpl ws, INamedScope parent) : base(ws, parent) { _funcs = new FunctionDefiner(true); INamedScope?p = parent; for (; ;) { if (p is ITypeScope t) { EnclosingType = t; break; } p = p.Parent; Debug.Assert(p != null, "We eventually reached a top level type."); } }
/// <summary> /// Merges this type definition with /// <paramref name="otherScope"/>. This happens when <c>otherScope.CanBeMergedInto(this)</c> /// evaluates to true. /// </summary> /// <param name="otherScope">the scope to merge with</param> /// <returns>a new type definition from this and otherScope, or null if they couldn't be /// merged</returns> public override INamedScope Merge(INamedScope otherScope) { ITypeDefinition mergedScope = null; if (otherScope != null) { if (otherScope.CanBeMergedInto(this)) { mergedScope = new TypeDefinition(this); mergedScope.AddFrom(otherScope); if (mergedScope.Accessibility == AccessModifier.None) { mergedScope.Accessibility = otherScope.Accessibility; } } } return(mergedScope as INamedScope); }
internal TypeScopeImpl(CodeWorkspaceImpl ws, INamedScope parent) : base(ws, parent) { UniqueId = ws.GetNextTypeScopeIdentifier(); _funcs = new FunctionDefiner(true); INamedScope?p = parent; for (; ;) { if (p is INamespaceScope ns) { Namespace = ns; break; } p = p.Parent; Debug.Assert(p != null, "We eventually reached the root namespace."); } }
/// <summary> /// Sets up unresolved links between this and /// <paramref name="childScope"/>if needed. /// </summary> /// <param name="childScope">The child scope to add</param> protected void AddNamedChildScope(INamedScope childScope) { var scopeToAdd = childScope; if (childScope.UnresolvedParentScopeInUse == null && childScope.ParentScopeCandidates.Any()) { var selectedScope = childScope.SelectUnresolvedScope(); scopeToAdd = selectedScope.CreateScope(); IScope latest = scopeToAdd, current; do { current = latest; latest = current.ChildScopes.FirstOrDefault(); } while(latest != null); current.AddChildScope(childScope); } base.AddChildScope(scopeToAdd); }
/// <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); }
public CodePart(INamedScope owner) { _owner = owner; }
internal FunctionScopeImpl(CodeWorkspaceImpl ws, INamedScope parent, FunctionDefinition def) : this(ws, parent) { _fDef = def; SetName(_fDef.Key); }
/// <summary> /// Builds and returns the code. /// </summary> /// <param name="this">This scope.</param> /// <param name="closeScope">True to close the scope.</param> /// <returns>The source code of this named scope.</returns> public static string ToString(this INamedScope @this, bool closeScope) { return(@this.Build(new StringBuilder(), closeScope).ToString()); }