private static PostfixTemplateContext TryReparseWith([NotNull] ISolution solution, [NotNull] ITextControl textControl, [NotNull] string reparseString) { var offset = textControl.Caret.Offset(); var document = textControl.Document; try { document.InsertText(offset, reparseString); solution.GetPsiServices().Files.CommitAllDocuments(); foreach (var position in TextControlToPsi.GetElements <ITreeNode>(solution, document, offset)) { var templateContextFactory = LanguageManager.Instance.TryGetService <IPostfixTemplateContextFactory>(position.Language); if (templateContextFactory != null) { var executionContext = new PostfixTemplateExecutionContext( solution, textControl, position.GetSettingsStore(), reparseString, false); return(templateContextFactory.TryCreate(position, executionContext)); } } return(null); } finally { var reparseRange = TextRange.FromLength(offset, reparseString.Length); document.DeleteText(reparseRange); } }
private IList <IPostfixLookupItem> TryReparseWith([NotNull] ISolution solution, [NotNull] ITextControl textControl, [NotNull] string templateName, [NotNull] string reparseString) { var offset = textControl.Caret.Offset(); var document = textControl.Document; try { document.InsertText(offset, reparseString); solution.GetPsiServices().CommitAllDocuments(); var itemsOwner = myItemsOwnerFactory.CreateLookupItemsOwner(textControl); var executionContext = new PostfixExecutionContext( myLifetime, solution, textControl, itemsOwner, reparseString, false); foreach (var position in TextControlToPsi.GetElements <ITokenNode>(solution, document, offset)) { var postfixContext = myTemplatesManager.IsAvailable(position, executionContext); if (postfixContext == null) { continue; } return(myTemplatesManager.CollectItems(postfixContext, templateName: templateName)); } return(null); } finally { var reparseRange = TextRange.FromLength(offset, reparseString.Length); document.DeleteText(reparseRange); } }
private static IEnumerable <LocalOccurrence> SearchInCurrentFile( [NotNull] string searchText, [NotNull] IPsiSourceFile sourceFile) { var document = sourceFile.Document; var fileText = document.GetText(); if (fileText == null) { yield break; } var offset = 0; while ((offset = fileText.IndexOf(searchText, offset, StringComparison.OrdinalIgnoreCase)) >= 0) { var occurrenceRange = TextRange.FromLength(offset, searchText.Length); var documentRange = new DocumentRange(document, occurrenceRange); var documentLine = (int)document.GetCoordsByOffset(offset).Line; var foundText = fileText.Substring(offset, searchText.Length); var leftIndex = Math.Max(0, offset - 10); var leftFragment = fileText.Substring(leftIndex, offset - leftIndex); var endOffset = offset + searchText.Length; var rightIndex = Math.Min(endOffset + 10, fileText.Length); var rightFragment = fileText.Substring(endOffset, rightIndex - endOffset); yield return(new LocalOccurrence( documentRange, documentLine, foundText, leftFragment, rightFragment)); offset++; } }
private static void SearchInFile( [NotNull] string searchText, [NotNull] IPsiSourceFile sourceFile, [NotNull] List <IOccurence> consumer, [NotNull] CheckForInterrupt checkCanceled) { var fileText = sourceFile.Document.GetText(); if (fileText == null) { return; } var index = 0; while ((index = fileText.IndexOf(searchText, index, StringComparison.OrdinalIgnoreCase)) >= 0) { var occurrenceRange = TextRange.FromLength(index, searchText.Length); var documentRange = new DocumentRange(sourceFile.Document, occurrenceRange); var occurrence = new RangeOccurence(sourceFile, documentRange); lock (consumer) { consumer.Add(occurrence); } if (checkCanceled()) { break; } index++; } }
private ReferenceCollection CreateTypeNameReferences(ICSharpLiteralExpression literal, ExpectedObjectTypeReferenceKind kind) { var literalValue = (string)literal.ConstantValue.Value; if (literalValue == null) { return(ReferenceCollection.Empty); } var symbolCache = literal.GetPsiServices().Symbols; IQualifier qualifier = null; var references = new LocalList <IReference>(); var startIndex = 0; var nextDotIndex = literalValue.IndexOf('.'); while (true) { var endIndex = nextDotIndex != -1 ? nextDotIndex : literalValue.Length; // startIndex + 1 to skip leading quote in tree node, which doesn't exist in literalValue var rangeWithin = TextRange.FromLength(startIndex + 1, endIndex - startIndex); // Behaviour and resolution is almost identical for each part. // For a single component, it is either a Unity object with an inferred namespace, a type in the global // namespace, or the namespace for an as yet uncompleted qualified type name // For a trailing component, it is a qualified reference, and could be a type, or a continuation of the // namespace qualification // For a middle component, it could be a namespace, or the user typing a new type, with the trailing // text being the old component // When there is no qualifier, resolve should match: // * inferred type, with expected type check // * type in global namespace, with expected type check // * namespace, with expected type check (so namespace won't be the last thing) // When there is a qualifier, resolve should match // * namespaces // * qualified type with expected type check // For the final component, resolve should match namespaces, but with the expected type check // At all times, completion should show both namespaces and qualified types // Leading and trailing space are treated as part of a name, and will cause resolve to fail // TODO: Handle trailing dot var isFinalPart = nextDotIndex == -1; var reference = new UnityObjectTypeOrNamespaceReference(literal, qualifier, literal.Literal, rangeWithin, kind, symbolCache, isFinalPart); references.Add(reference); if (nextDotIndex == -1) { break; } startIndex = nextDotIndex + 1; nextDotIndex = literalValue.IndexOf('.', startIndex); qualifier = reference; } return(new ReferenceCollection(references.ReadOnlyList())); }
public sealed override TextRange GetTextRangeToDelete() { if (this.GenerationMode == ByPatternInPlaceGenerationMode.ReplaceMatchedText) { return(this.MatchResult.GetDocumentRange().TextRange); } return(TextRange.FromLength(0)); }
/// <nodoc /> public static SymbolLocation GetLocationFromNode(INode node, ISymbol symbol) { return(SymbolLocation.LocalLocation( node.GetSourceFile().Path.AbsolutePath, TextRange.FromLength( node.GetNodeStartPositionWithoutTrivia(), node.GetNodeWidth()), symbol)); }
public void Execute(IDataContext context, DelegateExecute nextExecute) { var solution = context.GetData(ProjectModel.DataContext.DataConstants.SOLUTION); if (solution == null) { return; } var textControl = context.GetData(TextControl.DataContext.DataConstants.TEXT_CONTROL); if (textControl == null) { return; } if (myLookupWindowManager.CurrentLookup != null) { return; } const string commandName = "Expanding postfix template with [Tab]"; var updateCookie = myChangeUnitFactory.CreateChangeUnit(textControl, commandName); try { using (myCommandProcessor.UsingCommand(commandName)) { var postfixItem = GetTemplateFromTextControl(solution, textControl); if (postfixItem != null) { TipsManager.Instance.FeatureIsUsed( "Plugin.ControlFlow.PostfixTemplates.<tab>", textControl.Document, solution); var nameLength = postfixItem.Identity.Length; var offset = textControl.Caret.Offset() - nameLength; postfixItem.Accept( textControl, TextRange.FromLength(offset, nameLength), LookupItemInsertType.Insert, Suffix.Empty, solution, keepCaretStill: false); return; } updateCookie.Dispose(); } } catch { updateCookie.Dispose(); throw; } nextExecute(); }
public bool Navigate(ISolution solution, PopupWindowContextSource windowContext, bool transferFocus, TabOptions tabOptions = TabOptions.Default) { var psiFile = mySourceFile.GetPrimaryPsiFile(); if (psiFile == null || !psiFile.Language.Is <JsonLanguage>()) { return(false); } var range = TextRange.FromLength(myNavigationTreeOffset, myName.Length); return(mySourceFile.Navigate(range, transferFocus, tabOptions, windowContext)); }
public string DumpToString() { // +2 for the quotes, +1 to put it after the quote var range = TextRange.FromLength(myDeclaredElementTreeOffset, myName.Length + 3); var line = RangeOccurrenceUtil.GetTrimmedLinePossibleMultiline(mySourceFile, range, null, out var occurrenceInLineRange) .Insert(occurrenceInLineRange.StartOffset, "|") .Insert(occurrenceInLineRange.EndOffset, "|"); var builder = new StringBuilder(); builder.AppendFormat("TO: [O] {0}", line); builder.AppendFormat(" RANGE: {0} @ {1}", range.ToInvariantString(), mySourceFile.DisplayName); return(builder.ToString()); }
private bool IsAvailableOrExecuteEww([NotNull] ISolution solution, [NotNull] ITextControl textControl, bool execute) { var offset = textControl.Caret.Offset(); var prefix = LiveTemplatesManager.GetPrefix(textControl.Document, offset); if (!TemplateWithNameExists(prefix)) { return(false); } var files = textControl.Document.GetPsiSourceFiles(solution); var allLanguages = files.SelectMany(file => file.GetPsiServices().Files.GetLanguages(file, PsiLanguageCategories.Primary)).Distinct(); foreach (var psiLanguageType in allLanguages) { var contextFactory = LanguageManager.Instance.TryGetService <IPostfixTemplateContextFactory>(psiLanguageType); if (contextFactory == null) { continue; } foreach (var reparseString in contextFactory.GetReparseStrings()) { var templateContext = TryReparseWith(solution, textControl, reparseString); if (templateContext != null) { if (!templateContext.IsSemanticallyMakeSence()) { return(false); } var templatesManager = LanguageManager.Instance.GetService <IPostfixTemplatesManager>(psiLanguageType); if (execute) { var nameRange = TextRange.FromLength(offset - prefix.Length, prefix.Length); templatesManager.ExecuteTemplateByName(templateContext, prefix, textControl, nameRange); return(true); } return(templatesManager.IsTemplateAvailableByName(templateContext, prefix)); } } } return(false); }
public override void Execute(IDataContext context, DelegateExecute nextExecute) { var solution = context.GetData(ProjectModel.DataContext.DataConstants.SOLUTION); Assertion.AssertNotNull(solution, "solution == null"); var textControl = context.GetData(TextControl.DataContext.DataConstants.TEXT_CONTROL); Assertion.AssertNotNull(textControl, "textControl == null"); var commandProcessor = Shell.Instance.GetComponent <ICommandProcessor>(); var documentTransactionManager = solution.GetComponent <DocumentTransactionManager>(); using (commandProcessor.UsingCommand("ZenCoding")) { using (documentTransactionManager.CreateTransactionCookie(DefaultAction.Commit, "ZenCoding")) { string abbr; var abbrRange = textControl.Selection.OneDocRangeWithCaret(); if (abbrRange.IsValid && abbrRange.Length > 0) { abbr = textControl.Document.GetText(abbrRange); } else { var coords = textControl.Caret.PositionValue.ToDocLineColumn(); int start; var engine = GetEngine(solution); var lineText = textControl.Document.GetLineText(coords.Line); abbr = engine.FindAbbreviationInLine(lineText, (int)coords.Column, out start); if (start == -1) { Win32Declarations.MessageBeep(MessageBeepType.Error); return; } abbrRange = TextRange .FromLength(textControl.Caret.PositionValue.ToDocOffset(), -abbr.Length) .Normalized(); } int insertPoint; var projectFile = textControl.ToProjectFile(solution); var expanded = GetEngine(solution).ExpandAbbreviation(abbr, GetDocTypeForFile(projectFile), out insertPoint); CheckAndIndent(solution, projectFile, textControl, abbrRange, expanded, insertPoint); } } }
private TextRange GetPostfixRange([NotNull] ITextControl textControl, TextRange nameRange) { Assertion.Assert(nameRange.IsValid, "nameRange.IsValid"); var length = nameRange.Length + myReparseString.Length; var textRange = TextRange.FromLength(nameRange.StartOffset, length); // find dot before postfix template name var buffer = textControl.Document.Buffer; for (var index = nameRange.StartOffset - 1; index > 0; index--) { if (buffer[index] == '.') { return(textRange.SetStartTo(index)); } } return(textRange); }
protected override IReference BindToInternal(IDeclaredElement declaredElement, ISubstitution substitution) { // Fix up name if (declaredElement.ShortName != GetName()) { var newReference = ReferenceWithinElementUtil <ITokenNode> .SetText(this, declaredElement.ShortName, (node, buffer) => { // The new name is substituted into the existing text, which includes quotes var unquotedStringValue = buffer.GetText(TextRange.FromLength(1, buffer.Length - 2)); return(CSharpElementFactory.GetInstance(node) .CreateStringLiteralExpression(unquotedStringValue) .Literal); }); return(newReference.BindTo(declaredElement)); } // Fix up qualification (e.g. move namespace) if (declaredElement is ITypeElement newType && !newType.Equals(Resolve().DeclaredElement)) { var oldRange = new TreeTextRange(TreeOffset.Zero, new TreeOffset(myOwner.GetTextLength())); ReferenceWithinElementUtil <ITokenNode> .SetText(myOwner.Literal, oldRange, newType.GetClrName().FullName, (node, buffer) => { // We're replacing the whole text and don't provide quotes in the new string var unquotedStringValue = buffer.GetText(); return(CSharpElementFactory.GetInstance(node) .CreateStringLiteralExpression(unquotedStringValue) .Literal); }, myOwner); var newReference = myOwner.FindReference <UnityObjectTypeOrNamespaceReference>(r => r.myIsFinalPart); Assertion.AssertNotNull(newReference, "newReference != null"); return(newReference); } return(this); }
private static string InsertQualifierAsArgument([NotNull] ICSharpExpression qualifierExpression, [NotNull] IList <IMethod> allMethods, int argumentsCount, [NotNull] ITextControl textControl, TextRange decoration, [NotNull] string decorationText) { var qualifierText = qualifierExpression.GetText(); var enumerationType = FindEnumerationType(qualifierExpression); if (enumerationType != null) { qualifierText = "typeof(" + qualifierText + ")"; } if (FirstArgumentAlwaysPassByRef(allMethods)) { qualifierText = "ref " + qualifierText; } if (argumentsCount > 0 || HasOnlyMultipleParameters(allMethods)) { qualifierText += ", "; } var parenthesisOpenIndex = decorationText.IndexOf('('); if (parenthesisOpenIndex < 0) { qualifierText = "(" + qualifierText; } // insert qualifier as first argument var shift = (parenthesisOpenIndex >= 0) ? parenthesisOpenIndex + 1 : decoration.Length; var argPosition = TextRange.FromLength(decoration.StartOffset + shift, 0); textControl.Document.ReplaceText(argPosition, qualifierText); return(qualifierText); }
public void ShowMenu( [NotNull] IProjectModelElement projectElement, [CanBeNull] ITextControl textControl, [CanBeNull] GotoByNameDataConstants.SearchTextData initialText) { var solution = projectElement.GetSolution(); var definition = Lifetimes.Define(solution.GetLifetime()); var controller = new GotoWordController( definition.Lifetime, myShellLocks, projectElement, textControl); if (textControl != null) { // use selected text if there is no initial // todo: how to make this work with recent list? var selection = textControl.Selection.Ranges.Value; if (selection != null && selection.Count == 1) { var docRange = selection[0].ToDocRangeNormalized(); if (docRange.Length > 0) { var selectedText = textControl.Document.GetText(docRange); initialText = new GotoByNameDataConstants.SearchTextData( selectedText, TextRange.FromLength(selectedText.Length)); } } } var menu = new GotoByNameMenu( myMenuComponent, definition, controller.Model, myUiApplication.MainWindow, initialText); var menuDoc = menu.MenuView.Value.Document.NotNull("menuDoc != null"); menuDoc.SelectedItem.FlowInto( definition.Lifetime, controller.SelectedItem, FConverter: item => (item != null) ? item.Key : null); }
private ILookupItem CreateMethodItem(CSharpCodeCompletionContext context, UnityEventFunction eventFunction, IClassLikeDeclaration declaration, bool hasReturnType, AccessRights accessRights, MemberGenerationContext generationContext) { if (CSharpLanguage.Instance == null) { return(null); } // Only show the modifier in the list text if it's not already specified and there isn't a return type, in // which case we default to `private`. E.g. if someone types `OnAnim`, then show `private void OnAnimate...` // but if they type `void OnAnim`, they don't want a modifier, and if they type `public void OnAnim` then // they want to use `public` var showModifier = false; if (!hasReturnType && accessRights == AccessRights.NONE) { showModifier = true; accessRights = AccessRights.PRIVATE; } // Note that we can't keep this declaration - it will become invalid as the user types to narrow down the // search and modifies the PSI file. This only affects ReSharper, Rider has different code completion // mechanism var factory = CSharpElementFactory.GetInstance(declaration, false); var methodDeclaration = eventFunction.CreateDeclaration(factory, declaration, accessRights); if (methodDeclaration.DeclaredElement == null) { return(null); } // This is effectively the same as GenerateMemberPresentation, but without the overhead that comes // with the flexibility of formatting any time of declared element. We just hard code the format var predefinedType = context.PsiModule.GetPredefinedType(); var parameters = string.Empty; if (eventFunction.Parameters.Length > 0) { var sb = new StringBuilder(); for (var i = 0; i < eventFunction.Parameters.Length; i++) { if (i > 0) { sb.Append(", "); } var parameter = eventFunction.Parameters[i]; var type = predefinedType.TryGetType(parameter.ClrTypeName, NullableAnnotation.Unknown); var typeName = type?.GetPresentableName(CSharpLanguage.Instance) ?? parameter.ClrTypeName.ShortName; sb.AppendFormat("{0}{1}{2}", parameter.IsByRef ? "out" : string.Empty, typeName, parameter.IsArray ? "[]" : string.Empty); } parameters = sb.ToString(); } var text = $"{eventFunction.Name}({parameters})"; var parameterOffset = eventFunction.Name.Length; var modifier = showModifier ? CSharpDeclaredElementPresenter.Instance.Format(accessRights) + " " : string.Empty; var psiIconManager = context.BasicContext.LookupItemsOwner.Services.PsiIconManager; // Note that because this is a text based lookup item, then it won't be included if the normal C# method // filter is applied. We can't make it a method based lookup item because the DeclaredElement isn't valid in // this situation - it's not a real method, and a DeclaredElementInfo would try to store a pointer to it, // and be unable to recreate it when it's needed. var textualInfo = new UnityEventFunctionTextualInfo(generationContext.MemberReplaceRanges, text, text) { Ranges = context.CompletionRanges }; var lookupItem = LookupItemFactory.CreateLookupItem(textualInfo) .WithPresentation(item => { var displayName = new RichText($"{modifier}{text} {{ ... }}"); // GenerateMemberPresentation marks everything as bold, and the parameters + block syntax as not important var parameterStartOffset = modifier.Length + parameterOffset; LookupUtil.MarkAsNotImportant(displayName, TextRange.FromLength(parameterStartOffset, displayName.Length - parameterStartOffset)); LookupUtil.AddEmphasize(displayName, new TextRange(modifier.Length, displayName.Length)); var image = psiIconManager.GetImage(CLRDeclaredElementType.METHOD); psiIconManager.AttachExtensions(image, GetAccessExtensions(accessRights)); var marker = item.Info.Ranges.CreateVisualReplaceRangeMarker(); return(new SimplePresentation(displayName, image, marker)); }) .WithBehavior(_ => new UnityEventFunctionBehavior(textualInfo, eventFunction, accessRights)) .WithMatcher(_ => new ShiftedDeclaredElementMatcher(eventFunction.Name, modifier.Length, textualInfo)); var description = GetDescription(context, methodDeclaration); return(new WrappedLookupItem(lookupItem, description)); }
private ILookupItem CreateMethodItem(CSharpCodeCompletionContext context, UnityEventFunction eventFunction, IClassLikeDeclaration declaration, bool hasReturnType, AccessRights accessRights) { if (CSharpLanguage.Instance == null) { return(null); } // Only show the modifier in the list text if it's not already specified and there isn't a return type, in // which case we default to `private`. E.g. if someone types `OnAnim`, then show `private void OnAnimate...` // but if they type `void OnAnim`, they don't want a modifier, and if they type `public void OnAnim` then // they want to use `public` var showModifier = false; if (!hasReturnType && accessRights == AccessRights.NONE) { showModifier = true; accessRights = AccessRights.PRIVATE; } var factory = CSharpElementFactory.GetInstance(declaration, false); var methodDeclaration = eventFunction.CreateDeclaration(factory, declaration, accessRights); if (methodDeclaration.DeclaredElement == null) { return(null); } var instance = new DeclaredElementInstance(methodDeclaration.DeclaredElement); var declaredElementInfo = new DeclaredElementInfoWithoutParameterInfo(methodDeclaration.DeclaredName, instance, CSharpLanguage.Instance, context.BasicContext.LookupItemsOwner, context) { Ranges = context.CompletionRanges }; // This is effectively the same as GenerateMemberPresentation, but without the overhead that comes // with the flexibility of formatting any time of declared element. We just hard code the format var predefinedType = context.PsiModule.GetPredefinedType(); var parameters = string.Empty; if (eventFunction.Parameters.Length > 0) { var sb = new StringBuilder(); for (var i = 0; i < eventFunction.Parameters.Length; i++) { if (i > 0) { sb.Append(", "); } var parameter = eventFunction.Parameters[i]; var type = predefinedType.TryGetType(parameter.ClrTypeName, NullableAnnotation.Unknown); var typeName = type?.GetPresentableName(CSharpLanguage.Instance) ?? parameter.ClrTypeName.ShortName; sb.AppendFormat("{0}{1}{2}", parameter.IsByRef ? "out" : string.Empty, typeName, parameter.IsArray ? "[]" : string.Empty); } parameters = sb.ToString(); } var text = $"{eventFunction.Name}({parameters})"; var parameterOffset = eventFunction.Name.Length; var modifier = showModifier ? CSharpDeclaredElementPresenter.Instance.Format(accessRights) + " " : string.Empty; var psiIconManager = context.BasicContext.LookupItemsOwner.Services.PsiIconManager; return(LookupItemFactory.CreateLookupItem(declaredElementInfo) .WithPresentation(item => { var displayName = new RichText($"{modifier}{text} {{ ... }}"); // GenerateMemberPresentation marks everything as bold, and the parameters + block syntax as not important var parameterStartOffset = modifier.Length + parameterOffset; LookupUtil.MarkAsNotImportant(displayName, TextRange.FromLength(parameterStartOffset, displayName.Length - parameterStartOffset)); LookupUtil.AddEmphasize(displayName, new TextRange(modifier.Length, displayName.Length)); var image = psiIconManager.GetImage(methodDeclaration.DeclaredElement, methodDeclaration.DeclaredElement.PresentationLanguage, true); var marker = item.Info.Ranges.CreateVisualReplaceRangeMarker(); return new SimplePresentation(displayName, image, marker); }) .WithBehavior(_ => new UnityEventFunctionBehavior(myShellLocks, declaredElementInfo, eventFunction, accessRights)) .WithMatcher(_ => new ShiftedDeclaredElementMatcher(eventFunction.Name, modifier.Length, declaredElementInfo, context.BasicContext.IdentifierMatchingStyle))); }
protected override void DoTest(IProject testProject) { var positionsToCheck = GetCaretPositions().DefaultIfEmpty(GetCaretPosition()).ToList(); Assert.IsNotEmpty(positionsToCheck, "Nothing to check - put {caret} where necessary"); var reparsedNodes = new List <ITreeNode>(); ShellInstance.GetComponent <TestIdGenerator>().Reset(); var psiFiles = Solution.GetPsiServices().Files; void PsiChanged(ITreeNode node, PsiChangedElementType type) { if (node != null) { reparsedNodes.Add(node); } } psiFiles.AfterPsiChanged += PsiChanged; try { var textControl = OpenTextControl(); { using (CompilationContextCookie.GetOrCreate(testProject.GetResolveContext())) { // number of original files var originalFiles = new Dictionary <IPsiSourceFile, int>(); foreach (var caretPosition in positionsToCheck) { var projectFile = GetProjectFile(testProject, caretPosition.FileName); Assert.NotNull(projectFile); foreach (var psiSourceFile in projectFile.ToSourceFiles()) { originalFiles.Add(psiSourceFile, GetPsiFiles(psiSourceFile).Count); } } var checkAll = GetSetting(textControl.Document.Buffer, "CHECKALL"); // change text var actions = GetSettings(textControl.Document.Buffer, "ACTION"); if (actions.Count == 0) { throw new Exception("No actions found"); } foreach (var action in actions) { if (action.Length == 0) { continue; } var text = action.Substring(1).Replace("{LEFT}", "{").Replace("{RIGHT}", "}"); switch (action.ToCharArray()[0]) { case '+': textControl.Document.InsertText(textControl.Caret.Offset(), text); break; case '-': textControl.Document.DeleteText(TextRange.FromLength(textControl.Caret.Offset(), Convert.ToInt32(text))); break; case '>': textControl.Caret.MoveTo(textControl.Caret.Offset() + Convert.ToInt32(text), CaretVisualPlacement.Generic); break; case '<': textControl.Caret.MoveTo(textControl.Caret.Offset() - Convert.ToInt32(text), CaretVisualPlacement.Generic); break; default: var actionManager = ShellInstance.GetComponent <IActionManager>(); actionManager.Defs.GetActionDefById(TextControlActions.Composition.Compose(action, false)) .EvaluateAndExecute(actionManager); break; } if (String.Equals(checkAll, "true", StringComparison.InvariantCultureIgnoreCase)) { foreach (var data in originalFiles) { GetPsiFiles(data.Key); } } } foreach (var data in originalFiles) { var psiSourceFile = data.Key; Assert.IsTrue(psiSourceFile.IsValid()); // get reparsed files var reparsedFiles = GetPsiFiles(psiSourceFile); Assert.AreEqual(reparsedFiles.Count, data.Value, "Reparsed psi files count mismatch for {0}", psiSourceFile); // check reparsed element ExecuteWithGold(psiSourceFile, writer => { if (reparsedNodes.IsEmpty()) { writer.Write("Fully reparsed"); } else { reparsedNodes.Sort((n1, n2) => String.CompareOrdinal(n1.Language.Name, n2.Language.Name)); foreach (var reparsedNode in reparsedNodes) { if (reparsedNode is IFile) { writer.WriteLine("{0}: Fully reparsed", reparsedNode.Language); } else { var nodeType = reparsedNode.GetType(); writer.WriteLine("{0}: reparsed node type: {1}, text: {2}", reparsedNode.Language, PresentNodeType(nodeType), reparsedNode.GetText()); } } } if (DoDumpRanges) { DumpRanges <PsiLanguageType>(psiSourceFile, writer); } }); // drop psi files cache WriteLockCookie.Execute(() => psiFiles.MarkAsDirty(psiSourceFile)); var files = GetPsiFiles(psiSourceFile); Assert.AreEqual(files.Count, reparsedFiles.Count, "Psi files count mismatch"); foreach (var pair in files) { var language = pair.Key; Assert.IsTrue(reparsedFiles.TryGetValue(language, out var reparsedFile), "Failed to find psi file for {0}", language); CompareTrees(pair.Value, reparsedFile); } } } } } finally { psiFiles.AfterPsiChanged -= PsiChanged; reparsedNodes.Clear(); } }
private static ILookupItem CreateMethodItem(CSharpCodeCompletionContext context, UnityEventFunction eventFunction, IClassLikeDeclaration declaration, bool addModifier) { if (CSharpLanguage.Instance == null) { return(null); } var method = eventFunction.CreateDeclaration(CSharpElementFactory.GetInstance(declaration, false), declaration); if (method.DeclaredElement == null) { return(null); } var instance = new DeclaredElementInstance(method.DeclaredElement); var declaredElementInfo = new DeclaredElementInfoWithoutParameterInfo(method.DeclaredName, instance, CSharpLanguage.Instance, context.BasicContext.LookupItemsOwner, context) { Ranges = context.CompletionRanges }; // This is effectively the same as GenerateMemberPresentation, but without the overhead that comes // with the flexibility of formatting any time of declared element. We just hard code the format var predefinedType = context.PsiModule.GetPredefinedType(); var parameters = string.Empty; if (eventFunction.Parameters.Length > 0) { var sb = new StringBuilder(); for (var i = 0; i < eventFunction.Parameters.Length; i++) { if (i > 0) { sb.Append(", "); } var parameter = eventFunction.Parameters[i]; var type = predefinedType.TryGetType(parameter.ClrTypeName); var typeName = type?.GetPresentableName(CSharpLanguage.Instance) ?? parameter.ClrTypeName.ShortName; sb.AppendFormat("{0}{1}{2}", parameter.IsByRef ? "out" : string.Empty, typeName, parameter.IsArray ? "[]" : string.Empty); } parameters = sb.ToString(); } var text = $"{eventFunction.Name}({parameters})"; var parameterOffset = eventFunction.Name.Length; var modifier = addModifier ? "private " : string.Empty; var psiIconManager = context.BasicContext.LookupItemsOwner.Services.PsiIconManager; return(LookupItemFactory.CreateLookupItem(declaredElementInfo) .WithPresentation(item => { var displayName = new RichText($"{modifier}{text} {{ ... }}"); // GenerateMemberPresentation marks everything as bold, and the parameters + block syntax as not important var parameterStartOffset = modifier.Length + parameterOffset; LookupUtil.MarkAsNotImportant(displayName, TextRange.FromLength(parameterStartOffset, displayName.Length - parameterStartOffset)); LookupUtil.AddEmphasize(displayName, new TextRange(modifier.Length, displayName.Length)); var image = psiIconManager.GetImage(CLRDeclaredElementType.METHOD, PsiIconExtension.Private); var marker = item.Info.Ranges.CreateVisualReplaceRangeMarker(); return new SimplePresentation(displayName, image, marker); }) .WithBehavior(_ => new UnityEventFunctionBehavior(declaredElementInfo, eventFunction)) .WithMatcher(_ => new ShiftedDeclaredElementMatcher(text, modifier.Length, declaredElementInfo, context.BasicContext.IdentifierMatchingStyle))); }