public static TypeReferencesResult Scan(DModule ast, ResolutionContext ctxt) { if (ast == null) return new TypeReferencesResult(); var typeRefFinder = new TypeReferenceFinder(ctxt); ContextFrame backupFrame = null; if(ctxt.ScopedBlock == ast) backupFrame = ctxt.Pop (); if (ctxt.CurrentContext == null) { ctxt.Push(backupFrame); backupFrame = null; } //typeRefFinder.ast = ast; // Enum all identifiers ast.Accept (typeRefFinder); if (backupFrame != null) ctxt.Push (backupFrame); // Crawl through all remaining expressions by evaluating their types and check if they're actual type references. /*typeRefFinder.queueCount = typeRefFinder.q.Count; typeRefFinder.ResolveAllIdentifiers(); */ return typeRefFinder.result; }
/// <summary> /// </summary> /// <param name="ast">The syntax tree to scan</param> /// <param name="symbol">Might not be a child symbol of ast</param> /// <param name="ctxt">The context required to search for symbols</param> /// <returns></returns> public static IEnumerable<ISyntaxRegion> Scan(DModule ast, INode symbol, ResolutionContext ctxt, bool includeDefinition = true) { if (ast == null || symbol == null || ctxt == null) return null; var f = new ReferencesFinder(symbol, ast, ctxt); using(ctxt.Push(ast)) ast.Accept (f); var nodeRoot = symbol.NodeRoot as DModule; if (includeDefinition && nodeRoot != null && nodeRoot.FileName == ast.FileName) { var dc = symbol.Parent as DClassLike; if (dc != null && dc.ClassType == D_Parser.Parser.DTokens.Template && dc.NameHash == symbol.NameHash) { f.l.Insert(0, new IdentifierDeclaration(dc.NameHash) { Location = dc.NameLocation, EndLocation = new CodeLocation(dc.NameLocation.Column + dc.Name.Length, dc.NameLocation.Line) }); } f.l.Insert(0, new IdentifierDeclaration(symbol.NameHash) { Location = symbol.NameLocation, EndLocation = new CodeLocation(symbol.NameLocation.Column + symbol.Name.Length, symbol.NameLocation.Line) }); } return f.l; }
/// <summary> /// Add 'superior' template parameters to the current symbol because /// the parameters might be re-used in the nested class. /// </summary> List <TemplateParameterSymbol> GetInvisibleTypeParameters(DNode n) { var invisibleTypeParams = new List <TemplateParameterSymbol>(); var tStk = new Stack <ContextFrame>(); do { var curCtxt = ctxt.Pop(); tStk.Push(curCtxt); foreach (var kv in curCtxt.DeducedTemplateParameters) { if (!n.ContainsTemplateParameter(kv.Value.Parameter)) { invisibleTypeParams.Add(kv.Value); } } }while (ctxt.PrevContextIsInSameHierarchy); while (tStk.Count != 0) { ctxt.Push(tStk.Pop()); } return(invisibleTypeParams); }
bool IsMoreSpecialized(ITypeDeclaration Spec, TemplateParameter t2, Dictionary <TemplateParameter, ISemantic> t1_DummyParamList) { AbstractType t1_TypeResults; // Make a type out of t1's specialization using (ctxt.Push(ctxt.ScopedBlock != null ? ctxt.ScopedBlock.Parent : null)) { var dict = ctxt.CurrentContext.DeducedTemplateParameters; // Make the T in e.g. T[] a virtual type so T will be replaced by it // T** will be X** then - so a theoretically valid type instead of a template param var dummyType = new ClassType(new DClassLike { Name = "X" }, null, null); foreach (var kv in t1_DummyParamList) { dict[kv.Key] = new TemplateParameterSymbol(t2, dummyType); } t1_TypeResults = Resolver.TypeResolution.TypeDeclarationResolver.ResolveSingle(Spec, ctxt); } if (t1_TypeResults == null) { return(true); } // Now try to fit the virtual Type t2 into t1 - and return true if it's possible return(new TemplateParameterDeduction(new DeducedTypeDictionary(), ctxt).Handle(t2, t1_TypeResults)); }
protected override void BuildCompletionDataInternal(IEditorData Editor, char enteredChar) { ed = Editor; ctxt = ResolutionContext.Create(Editor, false); AbstractType t = null; CodeCompletion.DoTimeoutableCompletionTask(CompletionDataGenerator,ctxt,() => { try { ctxt.Push(Editor); if (AccessExpression is IExpression) t = ExpressionTypeEvaluation.EvaluateType(AccessExpression as IExpression, ctxt); else if (AccessExpression is ITypeDeclaration) t = TypeDeclarationResolver.ResolveSingle(AccessExpression as ITypeDeclaration, ctxt); }catch(Exception ex) { Logger.LogWarn("Error during member completion", ex); } }); if (t == null) //TODO: Add after-space list creation when an unbound . (Dot) was entered which means to access the global scope return; t.Accept(this); }
protected override void BuildCompletionDataInternal(IEditorData Editor, char enteredChar) { ed = Editor; ctxt = ResolutionContext.Create(Editor, false); AbstractType t = null; CodeCompletion.DoTimeoutableCompletionTask(CompletionDataGenerator, ctxt, () => { ctxt.Push(Editor); if (AccessExpression is IExpression) { t = ExpressionTypeEvaluation.EvaluateType(AccessExpression as IExpression, ctxt); } else if (AccessExpression is ITypeDeclaration) { t = TypeDeclarationResolver.ResolveSingle(AccessExpression as ITypeDeclaration, ctxt); } }); if (t == null) //TODO: Add after-space list creation when an unbound . (Dot) was entered which means to access the global scope { return; } t.Accept(this); }
/// <summary> /// http://dlang.org/operatoroverloading.html#Dispatch /// Check for the existence of an opDispatch overload. /// Important: Because static opDispatches are allowed as well, do check whether we can access non-static overloads from non-instance expressions or such /// </summary> public static IEnumerable<AbstractType> TryResolveFurtherIdViaOpDispatch (ResolutionContext ctxt, int nextIdentifierHash, UserDefinedType b, ISyntaxRegion typeBase = null) { // The usual SO prevention if (nextIdentifierHash == opDispatchId || b == null) yield break; AbstractType[] overloads; var opt = ctxt.CurrentContext.ContextDependentOptions; // Look for opDispatch-Members inside b's Definition using (ctxt.Push(b)) { ctxt.CurrentContext.ContextDependentOptions = opt; // Mainly required for not resolving opDispatch's return type, as this will be performed later on in higher levels overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(opDispatchId, b, ctxt, typeBase, false); } if (overloads == null || overloads.Length < 0) yield break; var av = new ArrayValue (Evaluation.GetStringType(ctxt), Strings.TryGet(nextIdentifierHash)); foreach (DSymbol o in overloads) { var dn = o.Definition; if (dn.TemplateParameters != null && dn.TemplateParameters.Length > 0 && dn.TemplateParameters[0] is TemplateValueParameter) { //TODO: Test parameter types for being a string value o.SetDeducedTypes(new[]{ new TemplateParameterSymbol(dn.TemplateParameters[0], av) }); yield return o; } } }
public static void Run() { Parse (); var pcw = new LegacyParseCacheView (new[]{ srcDir }); var ctxt = new ResolutionContext (pcw, new ConditionalCompilationFlags(versions,0, true)); var mod = pcw.LookupModuleName (null, "botan.pubkey.algo.dsa").First(); var scope = ResolutionTests.N<DMethod> (mod, "DSAVerificationOperation.verify"); var scopedStmt = ResolutionTests.S (scope, 9); ctxt.Push (scope, scopedStmt.Location); ITypeDeclaration td = new IdentifierDeclaration ("q"){ Location = scopedStmt.Location }; AbstractType t; var sw = new Stopwatch (); Console.WriteLine ("Begin resolving..."); sw.Restart (); t = TypeDeclarationResolver.ResolveSingle(td, ctxt); sw.Stop (); Console.WriteLine ("Finished resolution. {0} ms.", sw.ElapsedMilliseconds); sw.Restart (); t = TypeDeclarationResolver.ResolveSingle(td, ctxt); sw.Stop (); Console.WriteLine ("Finished resolution. {0} ms.", sw.ElapsedMilliseconds); }
public ContextFrame(ResolutionContext ctxt, IBlockNode b, IStatement stmt = null) { this.ctxt = ctxt; declarationCondititons = new ConditionalCompilation.ConditionSet(ctxt.CompilationEnvironment); ctxt.Push(this); Set(b,stmt); }
public static TypeReferencesResult Scan(DModule ast, ResolutionContext ctxt) { if (ast == null) { return(new TypeReferencesResult()); } var typeRefFinder = new TypeReferenceFinder(ctxt); ContextFrame backupFrame = null; if (ctxt.ScopedBlock == ast) { backupFrame = ctxt.Pop(); } if (ctxt.CurrentContext == null) { ctxt.Push(backupFrame); backupFrame = null; } //typeRefFinder.ast = ast; // Enum all identifiers ast.Accept(typeRefFinder); if (backupFrame != null) { ctxt.Push(backupFrame); } // Crawl through all remaining expressions by evaluating their types and check if they're actual type references. /*typeRefFinder.queueCount = typeRefFinder.q.Count; * typeRefFinder.ResolveAllIdentifiers(); */ return(typeRefFinder.result); }
/// <summary> /// </summary> /// <param name="ast">The syntax tree to scan</param> /// <param name="symbol">Might not be a child symbol of ast</param> /// <param name="ctxt">The context required to search for symbols</param> /// <returns></returns> public static IEnumerable <ISyntaxRegion> Scan(DModule ast, INode symbol, ResolutionContext ctxt, bool includeDefinition = true) { if (ast == null || symbol == null || ctxt == null) { return(null); } var f = new ReferencesFinder(symbol, ast, ctxt); using (ctxt.Push(ast)) ast.Accept(f); var nodeRoot = symbol.NodeRoot as DModule; if (includeDefinition && nodeRoot != null && nodeRoot.FileName == ast.FileName) { var dc = symbol.Parent as DClassLike; if (dc != null && dc.ClassType == D_Parser.Parser.DTokens.Template && dc.NameHash == symbol.NameHash) { f.l.Insert(0, new IdentifierDeclaration(dc.NameHash) { Location = dc.NameLocation, EndLocation = new CodeLocation(dc.NameLocation.Column + dc.Name.Length, dc.NameLocation.Line) }); } var loc = symbol.NameLocation; bool add = !f.l.AsParallel().Any( (o) => (o is TemplateParameter && (o as TemplateParameter).NameLocation == loc) || (o is INode && (o as INode).NameLocation == loc)); if (add) { f.l.Insert(0, new IdentifierDeclaration(symbol.NameHash) { Location = loc, EndLocation = new CodeLocation(loc.Column + symbol.Name.Length, loc.Line) }); } } return(f.l); }
internal override IAnalysisSet Resolve(AnalysisUnit unit, ResolutionContext context) { if (context.Cache.TryGetValue(this, out var res)) { return(res); } if (!Push()) { return(AnalysisSet.Empty); } try { if (!context.Push()) { return(AnalysisSet.Empty); } try { res = ResolveOnce(unit, context, out var allowCache); bool changed = !Equals(res); while (changed && context.ResolveFully) { res = res.Resolve(unit, context, out changed); } if (context.ResolveFully) { res.Split <LazyValueInfo>(out _, out res); } if (allowCache) { context.Cache[this] = res; } return(res); } finally { context.Pop(); } } finally { Pop(); } }
/// <summary> /// http://dlang.org/operatoroverloading.html#Dispatch /// Check for the existence of an opDispatch overload. /// Important: Because static opDispatches are allowed as well, do check whether we can access non-static overloads from non-instance expressions or such /// </summary> public static IEnumerable <AbstractType> TryResolveFurtherIdViaOpDispatch(ResolutionContext ctxt, int nextIdentifierHash, UserDefinedType b, ISyntaxRegion typeBase = null) { // The usual SO prevention if (nextIdentifierHash == opDispatchId || b == null) { yield break; } AbstractType[] overloads; var opt = ctxt.CurrentContext.ContextDependentOptions; // Look for opDispatch-Members inside b's Definition using (ctxt.Push(b)) { ctxt.CurrentContext.ContextDependentOptions = opt; // Mainly required for not resolving opDispatch's return type, as this will be performed later on in higher levels overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(opDispatchId, new[] { b }, ctxt, typeBase, false); } if (overloads == null || overloads.Length < 0) { yield break; } var av = new ArrayValue(Evaluation.GetStringType(ctxt), Strings.TryGet(nextIdentifierHash)); foreach (DSymbol o in overloads) { var dn = o.Definition; if (dn.TemplateParameters != null && dn.TemplateParameters.Length > 0 && dn.TemplateParameters[0] is TemplateValueParameter) { //TODO: Test parameter types for being a string value o.DeducedTypes = new System.Collections.ObjectModel.ReadOnlyCollection <TemplateParameterSymbol> ( new[] { new TemplateParameterSymbol(dn.TemplateParameters[0], av) }); yield return(o); } } }
/// <summary> /// </summary> /// <param name="ast">The syntax tree to scan</param> /// <param name="symbol">Might not be a child symbol of ast</param> /// <param name="ctxt">The context required to search for symbols</param> /// <returns></returns> public static IEnumerable<ISyntaxRegion> SearchModuleForASTNodeReferences(DModule ast, INode symbol, ResolutionContext ctxt, bool includeDefinition = true) { if (ast == null || symbol == null || ctxt == null) return null; var f = new ReferencesFinder(symbol, ast, ctxt); using(ctxt.Push(ast)) ast.Accept (f); var nodeRoot = symbol.NodeRoot as DModule; if (includeDefinition && nodeRoot != null && nodeRoot.FileName == ast.FileName) { var dc = symbol.Parent as DClassLike; if (dc != null && dc.ClassType == D_Parser.Parser.DTokens.Template && dc.NameHash == symbol.NameHash) { f.l.Insert(0, new IdentifierDeclaration(dc.NameHash) { Location = dc.NameLocation, EndLocation = new CodeLocation(dc.NameLocation.Column + dc.Name.Length, dc.NameLocation.Line) }); } var loc = symbol.NameLocation; bool add = !f.l.AsParallel().Any( (o) => (o is TemplateParameter && (o as TemplateParameter).NameLocation == loc) || (o is INode && (o as INode).NameLocation == loc)); if(add) f.l.Insert(0, new IdentifierDeclaration(symbol.NameHash) { Location = loc, EndLocation = new CodeLocation(loc.Column + symbol.Name.Length, loc.Line) }); } return f.l; }
public static AbstractType ResolveType(IEditorData editor, ResolutionContext ctxt = null) { var o = GetScopedCodeObject(editor); if (ctxt == null) { ctxt = ResolutionContext.Create(editor, false); } AbstractType ret = null; CodeCompletion.DoTimeoutableCompletionTask(null, ctxt, () => { ctxt.Push(editor); var optionBackup = ctxt.CurrentContext.ContextDependentOptions; ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly; if (o is IExpression) { ret = ExpressionTypeEvaluation.EvaluateType((IExpression)o, ctxt, false); } else if (o is ITypeDeclaration) { ret = TypeDeclarationResolver.ResolveSingle((ITypeDeclaration)o, ctxt); } else if (o is INode) { ret = TypeDeclarationResolver.HandleNodeMatch(o as INode, ctxt); } ctxt.CurrentContext.ContextDependentOptions = optionBackup; }); return(ret); }
public static AbstractType ResolveTypeLoosely(IEditorData editor, out NodeResolutionAttempt resolutionAttempt, ResolutionContext ctxt = null) { var o = GetScopedCodeObject(editor); if (ctxt == null) { ctxt = ResolutionContext.Create(editor, false); } AbstractType ret = null; NodeResolutionAttempt resAttempt = NodeResolutionAttempt.Normal; CodeCompletion.DoTimeoutableCompletionTask(null, ctxt, () => { ctxt.Push(editor); var optionBackup = ctxt.CurrentContext.ContextDependentOptions; ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly | ResolutionOptions.DontResolveAliases; if (o is IExpression) { ret = ExpressionTypeEvaluation.EvaluateType((IExpression)o, ctxt, false); } else if (o is ITypeDeclaration) { ret = TypeDeclarationResolver.ResolveSingle((ITypeDeclaration)o, ctxt); } else if (o is INode) { ret = TypeDeclarationResolver.HandleNodeMatch(o as INode, ctxt, null, o); } else { ret = null; } if (ret == null) { resAttempt = NodeResolutionAttempt.NoParameterOrTemplateDeduction; if (o is PostfixExpression_MethodCall) { o = (o as PostfixExpression_MethodCall).PostfixForeExpression; } ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.NoTemplateParameterDeduction | ResolutionOptions.DontResolveAliases; if (o is IdentifierExpression) { ret = AmbiguousType.Get(ExpressionTypeEvaluation.GetOverloads(o as IdentifierExpression, ctxt, deduceParameters: false), o); } else if (o is ITypeDeclaration) { ret = TypeDeclarationResolver.ResolveSingle(o as ITypeDeclaration, ctxt); } else if (o is IExpression) { ret = ExpressionTypeEvaluation.EvaluateType(o as IExpression, ctxt, false); } } if (ret == null) { resAttempt = NodeResolutionAttempt.RawSymbolLookup; var overloads = TypeDeclarationResolver.HandleNodeMatches(LookupIdRawly(editor, o as ISyntaxRegion), ctxt, null, o); ret = AmbiguousType.Get(overloads, o); } ctxt.CurrentContext.ContextDependentOptions = optionBackup; }); resolutionAttempt = resAttempt; if (ret != null) { ret.DeclarationOrExpressionBase = o; } return(ret); }
static void HandleDMethodOverload(ResolutionContext ctxt, bool eval, ISymbolValue baseValue, List <ISemantic> callArguments, bool returnBaseTypeOnly, List <AbstractType> argTypeFilteredOverloads, ref bool hasHandledUfcsResultBefore, MemberSymbol ms, ref AbstractType untemplatedMethod) { var dm = ms.Definition as DMethod; if (dm == null) { return; } ISemantic firstUfcsArg; bool isUfcs = UFCSResolver.IsUfcsResult(ms, out firstUfcsArg); // In the case of an ufcs, insert the first argument into the CallArguments list if (isUfcs && !hasHandledUfcsResultBefore) { callArguments.Insert(0, eval ? baseValue as ISemantic : firstUfcsArg); hasHandledUfcsResultBefore = true; } else if (!isUfcs && hasHandledUfcsResultBefore) // In the rare case of having a ufcs result occuring _after_ a normal member result, remove the initial arg again { callArguments.RemoveAt(0); hasHandledUfcsResultBefore = false; } if (dm.Parameters.Count == 0 && callArguments.Count > 0) { return; } var deducedTypeDict = new DeducedTypeDictionary(ms); var templateParamDeduction = new TemplateParameterDeduction(deducedTypeDict, ctxt); var back = ctxt.ScopedBlock; using (ctxt.Push(ms)) { if (ctxt.ScopedBlock != back) { ctxt.CurrentContext.DeducedTemplateParameters = deducedTypeDict; } bool add = true; int currentArg = 0; if (dm.Parameters.Count > 0 || callArguments.Count > 0) { bool hadDTuples = false; for (int i = 0; i < dm.Parameters.Count; i++) { var paramType = dm.Parameters[i].Type; // Handle the usage of tuples: Tuples may only be used as as-is, so not as an array, pointer or in a modified way.. if (paramType is IdentifierDeclaration && (hadDTuples |= TryHandleMethodArgumentTuple(ctxt, ref add, callArguments, dm, deducedTypeDict, i, ref currentArg))) { continue; } else if (currentArg < callArguments.Count) { if (!(add = templateParamDeduction.HandleDecl(null, paramType, callArguments[currentArg++]))) { break; } } else { // If there are more parameters than arguments given, check if the param has default values add = !(dm.Parameters[i] is DVariable) || (dm.Parameters[i] as DVariable).Initializer != null; // Assume that all further method parameters do have default values - and don't check further parameters break; } } // Too few args if (!hadDTuples && currentArg < callArguments.Count) { add = false; } } if (!add) { return; } // If type params were unassigned, try to take the defaults if (dm.TemplateParameters != null) { foreach (var tpar in dm.TemplateParameters) { if (deducedTypeDict[tpar] == null && !templateParamDeduction.Handle(tpar, null)) { return; } } } if (deducedTypeDict.AllParamatersSatisfied) { ms.DeducedTypes = deducedTypeDict.ToReadonly(); var bt = TypeDeclarationResolver.GetMethodReturnType(dm, ctxt) ?? ms.Base; if (eval || !returnBaseTypeOnly) { bt = new MemberSymbol(dm, bt, ms.DeclarationOrExpressionBase, ms.DeducedTypes) { Tag = ms.Tag } } ; if (dm.TemplateParameters == null || dm.TemplateParameters.Length == 0) { untemplatedMethod = bt; //ISSUE: Have another state that indicates an ambiguous non-templated method matching. } argTypeFilteredOverloads.Add(bt); } } }
/// <summary> /// Takes the class passed via the tr, and resolves its base class and/or implemented interfaces. /// Also usable for enums. /// /// Never returns null. Instead, the original 'tr' object will be returned if no base class was resolved. /// Will clone 'tr', whereas the new object will contain the base class. /// </summary> public static TemplateIntermediateType ResolveClassOrInterface(DClassLike dc, ResolutionContext ctxt, ISyntaxRegion instanceDeclaration, bool ResolveFirstBaseIdOnly = false, IEnumerable <TemplateParameterSymbol> extraDeducedTemplateParams = null) { if (parsedClassInstanceDecls == null) { parsedClassInstanceDecls = new List <ISyntaxRegion> (); } switch (dc.ClassType) { case DTokens.Class: case DTokens.Interface: break; default: if (dc.BaseClasses.Count != 0) { ctxt.LogError(dc, "Only classes and interfaces may inherit from other classes/interfaces"); } return(null); } bool isClass = dc.ClassType == DTokens.Class; if (bcStack > 6 || (instanceDeclaration != null && parsedClassInstanceDecls.Contains(instanceDeclaration))) { return(isClass ? new ClassType(dc, instanceDeclaration, null) as TemplateIntermediateType : new InterfaceType(dc, instanceDeclaration)); } if (instanceDeclaration != null) { parsedClassInstanceDecls.Add(instanceDeclaration); } bcStack++; var deducedTypes = new DeducedTypeDictionary(dc); var tix = instanceDeclaration as TemplateInstanceExpression; if (tix != null && (ctxt.Options & ResolutionOptions.NoTemplateParameterDeduction) == 0) { // Pop a context frame as we still need to resolve the template instance expression args in the place where the expression occurs, not the instantiated class' location var backup = ctxt.Pop(); if (ctxt.CurrentContext == null) { ctxt.Push(backup); } var givenTemplateArguments = TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt); if (ctxt.CurrentContext != backup) { foreach (var kv in ctxt.CurrentContext.DeducedTemplateParameters) { backup.DeducedTemplateParameters [kv.Key] = kv.Value; deducedTypes [kv.Key] = kv.Value; } ctxt.Push(backup); } if (!TemplateInstanceHandler.DeduceParams(givenTemplateArguments, false, ctxt, null, dc, deducedTypes)) { parsedClassInstanceDecls.Remove(instanceDeclaration); bcStack--; return(null); } } if (extraDeducedTemplateParams != null) { foreach (var tps in extraDeducedTemplateParams) { deducedTypes[tps.Parameter] = tps; } } if (dc.BaseClasses == null || dc.BaseClasses.Count < 1) { parsedClassInstanceDecls.Remove(instanceDeclaration); bcStack--; // The Object class has no further base class; // Normal class instances have the object as base class; // Interfaces must not have any default base class/interface return(isClass ? new ClassType(dc, instanceDeclaration, dc.NameHash != ObjectNameHash ? ctxt.ParseCache.ObjectClassResult : null, null, deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null) : new InterfaceType(dc, instanceDeclaration, null, deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null) as TemplateIntermediateType); } #region Base class & interface resolution TemplateIntermediateType baseClass = null; var interfaces = new List <InterfaceType>(); var back = ctxt.ScopedBlock; using (ctxt.Push(dc.Parent)) { var pop = back != ctxt.ScopedBlock; foreach (var kv in deducedTypes) { ctxt.CurrentContext.DeducedTemplateParameters[kv.Key] = kv.Value; } try { for (int i = 0; i < (ResolveFirstBaseIdOnly ? 1 : dc.BaseClasses.Count); i++) { var type = dc.BaseClasses[i]; // If there's an explicit 'Object' inheritance, also return the pre-resolved object class if (type is IdentifierDeclaration && (type as IdentifierDeclaration).IdHash == ObjectNameHash) { if (baseClass != null) { ctxt.LogError(new ResolutionError(dc, "Class must not have two base classes")); continue; } else if (i != 0) { ctxt.LogError(new ResolutionError(dc, "The base class name must preceed base interfaces")); continue; } baseClass = ctxt.ParseCache.ObjectClassResult; continue; } if (type == null || (type is IdentifierDeclaration && (type as IdentifierDeclaration).IdHash == dc.NameHash) || dc.NodeRoot == dc) { ctxt.LogError(new ResolutionError(dc, "A class cannot inherit from itself")); continue; } var r = DResolver.StripMemberSymbols(TypeDeclarationResolver.ResolveSingle(type, ctxt)); if (r is ClassType || r is TemplateType) { if (!isClass) { ctxt.LogError(new ResolutionError(type, "An interface cannot inherit from non-interfaces")); } else if (i == 0) { baseClass = r as TemplateIntermediateType; } else { ctxt.LogError(new ResolutionError(dc, "The base " + (r is ClassType ? "class" : "template") + " name must preceed base interfaces")); } } else if (r is InterfaceType) { interfaces.Add(r as InterfaceType); if (isClass && dc.NameHash != ObjectNameHash && baseClass == null) { baseClass = ctxt.ParseCache.ObjectClassResult; } } else { ctxt.LogError(new ResolutionError(type, "Resolved class is neither a class nor an interface")); continue; } } } finally { bcStack--; parsedClassInstanceDecls.Remove(instanceDeclaration); } if (!pop) { foreach (var kv in deducedTypes) // May be backup old tps? { ctxt.CurrentContext.DeducedTemplateParameters.Remove(kv.Key); } } } #endregion if (isClass) { return(new ClassType(dc, instanceDeclaration, baseClass, interfaces.Count == 0 ? null : interfaces.ToArray(), deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null)); } return(new InterfaceType(dc, instanceDeclaration, interfaces.Count == 0 ? null : interfaces.ToArray(), deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null)); }
/// <summary> /// Add 'superior' template parameters to the current symbol because /// the parameters might be re-used in the nested class. /// </summary> static List<TemplateParameterSymbol> GetInvisibleTypeParameters(DNode n,ResolutionContext ctxt) { var invisibleTypeParams = new List<TemplateParameterSymbol> (); var tStk = new Stack<ContextFrame> (); do { var curCtxt = ctxt.Pop (); tStk.Push (curCtxt); foreach (var kv in curCtxt.DeducedTemplateParameters) if (!n.ContainsTemplateParameter (kv.Value.Parameter)) invisibleTypeParams.Add (kv.Value); } while (ctxt.PrevContextIsInSameHierarchy); while (tStk.Count != 0) ctxt.Push (tStk.Pop ()); return invisibleTypeParams; }
public override void VisitAbstractStmt(AbstractStatement stmt) { using (ctxt.Push(stmt.ParentNode, stmt.Location)) base.VisitAbstractStmt(stmt); }
static string GetMixinContent(MixinStatement mx, ResolutionContext ctxt, bool takeStmtCache ,out ISyntaxRegion cachedContent) { cachedContent = null; if(!CheckAndPushAnalysisStack(mx)) return null; ISemantic v; using (ctxt.Push(mx.ParentNode, mx)) { bool hadCachedItem; if (takeStmtCache) { BlockStatement stmt; hadCachedItem = mixinStmtCache.TryGet(ctxt, mx, out stmt); cachedContent = stmt; } else { DModule mod; hadCachedItem = mixinDeclCache.TryGet(ctxt, mx, out mod); cachedContent = mod; } if (hadCachedItem) { stmtsBeingAnalysed.Remove(mx); return null; } try // 'try' because there is always a risk of e.g. not having something implemented or having an evaluation exception... { // Evaluate the mixin expression v = Evaluation.EvaluateValue(mx.MixinExpression, ctxt); } catch { v = null; } stmtsBeingAnalysed.Remove(mx); } // Ensure it's a string literal var av = v as ArrayValue; if(av != null && av.IsString) return av.StringValue; if(takeStmtCache) mixinStmtCache.Add(ctxt, mx, null); else mixinDeclCache.Add(ctxt, mx, null); return null; }
public bool UpdateTypeResolutionContext () { if (!NeedsResolutionContextUpdate && resolutionCtx != null) return true; NeedsResolutionContextUpdate = false; var ff = DebuggingService.CurrentCallStack.GetFrame(Backtrace.CurrentFrameIndex); var document = Ide.IdeApp.Workbench.OpenDocument (ff.SourceLocation.FileName); if (document == null) return false; var codeLocation = new CodeLocation (ff.SourceLocation.Column, ff.SourceLocation.Line); // Only create new if the cursor location is different from the previous if (firstFrameEditorData != null && firstFrameEditorData.SyntaxTree.FileName == ff.SourceLocation.FileName && firstFrameEditorData.CaretLocation.Line == codeLocation.Line) return true; firstFrameEditorData = DResolverWrapper.CreateEditorData (document); firstFrameEditorData.CaretLocation = codeLocation; resolutionCtx = ResolutionContext.Create (firstFrameEditorData, false); CodeCompletion.DoTimeoutableCompletionTask (null, resolutionCtx, () => resolutionCtx.Push (firstFrameEditorData)); return true; }