public override IScanner GetScanner(IVsTextLines buffer) { // Since Visual Studio handles language service associations by file // extension, CMakeLanguageService must handle all *.txt files in order to // handle CMakeLists.txt. Detect if the buffer represents an ordinary text // files. If so, disable syntax highlighting. This is a kludge, but it's // the best that can be done here. string path = FilePathUtilities.GetFilePath(buffer); return(new CMakeScanner(!CMakeSource.IsCMakeFile(path))); }
protected override int QueryCommandStatus(ref Guid guidCmdGroup, uint nCmdId) { if (guidCmdGroup == VSConstants.VSStd2K && CMakeSource.IsCMakeFile(Source.GetFilePath())) { if (nCmdId == (uint)VSConstants.VSStd2KCmdID.INSERTSNIPPET) { // Show and enable the Insert Snippet command. return((int)(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED)); } else if (nCmdId == (uint)VSConstants.VSStd2KCmdID.OPENFILE) { // Show and enable the Open File command if the current token is a // file name. string extraSearchPath; if (GetCurrentTokenFileName(out extraSearchPath) != null) { return((int)(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED)); } } } else if (guidCmdGroup == VSConstants.GUID_VSStandardCommandSet97 && !CMakeSource.IsCMakeFile(Source.GetFilePath())) { // Visual Studio does not show these commands for ordinary text files. // All text files get associated with the CMake language service in order // to facilitate handling CMakeLists.txt. When the current file is an // ordinary text file, hide these commands to match what Visual Studio // would otherwise do. if (nCmdId == (uint)VSConstants.VSStd97CmdID.GotoDecl || nCmdId == (uint)VSConstants.VSStd97CmdID.GotoDefn || nCmdId == (uint)VSConstants.VSStd97CmdID.GotoRef) { return((int)(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_INVISIBLE)); } } return(base.QueryCommandStatus(ref guidCmdGroup, nCmdId)); }
public override AuthoringScope ParseSource(ParseRequest req) { CMakeAuthoringScope scope = new CMakeAuthoringScope(); if (!CMakeSource.IsCMakeFile(req.FileName)) { // Don't do IntelliSense parsing for ordinary text files. return(scope); } CMakeSource source = (CMakeSource)GetSource(req.FileName); if (req.Sink.HiddenRegions) { req.Sink.ProcessHiddenRegions = true; List <TextSpan> regions = CMakeParsing.ParseForFunctionBodies( source.GetLines()); foreach (TextSpan textSpan in regions) { req.Sink.AddHiddenRegion(textSpan); } } if (req.Sink.BraceMatching) { List <CMakeParsing.SpanPair> pairs = null; switch ((CMakeToken)req.TokenInfo.Token) { case CMakeToken.OpenParen: case CMakeToken.CloseParen: pairs = CMakeParsing.ParseForParens(source.GetLines()); break; case CMakeToken.VariableStart: case CMakeToken.VariableStartEnv: case CMakeToken.VariableStartCache: case CMakeToken.VariableStartSetEnv: case CMakeToken.VariableEnd: pairs = CMakeParsing.ParseForVariableBraces(source.GetLines(), req.Line); break; case CMakeToken.GeneratorStart: case CMakeToken.GeneratorEnd: pairs = CMakeParsing.ParseForGeneratorBraces(source.GetLines(), req.Line); break; } if (pairs != null) { foreach (CMakeParsing.SpanPair pair in pairs) { req.Sink.MatchPair(pair.First, pair.Second, 0); } } } if (req.Reason == ParseReason.MemberSelect || req.Reason == ParseReason.MemberSelectAndHighlightBraces || req.Reason == ParseReason.CompleteWord) { // Set an appropriate declarations object depending on the token that // triggered member selection. CMakeToken token = (CMakeToken)req.TokenInfo.Token; if (token == CMakeToken.String) { // If the token is a string and the user has began to reference a // variable inside the string, treat the string as if it was the // appropriate type of variable start token and display member // selection for variables. string line = source.GetLine(req.Line); string tokenText = line.ExtractToken(req.TokenInfo); if (tokenText.EndsWith("${")) { token = CMakeToken.VariableStart; } else if (tokenText.EndsWith("$ENV{")) { token = CMakeToken.VariableStartEnv; } else if (tokenText.EndsWith("$CACHE{")) { token = CMakeToken.VariableStartCache; } } if (token == CMakeToken.VariableStart) { List <string> vars = CMakeParsing.ParseForVariables( source.GetLines(), req.Line); CMakeVariableDeclarations decls = new CMakeVariableDeclarations(vars, CMakeVariableType.Variable); decls.AddItems(source.GetIncludeCacheVariables(), CMakeItemDeclarations.ItemType.Variable); string functionName = CMakeParsing.ParseForCurrentFunction( source.GetLines(), req.Line); if (functionName != null) { List <string> paramNames = CMakeParsing.ParseForParameterNames( source.GetLines(), functionName); paramNames.Add("ARGN"); decls.AddItems(paramNames, CMakeItemDeclarations.ItemType.Variable); } scope.SetDeclarations(decls); } else if (token == CMakeToken.VariableStartEnv) { List <string> vars = CMakeParsing.ParseForEnvVariables( source.GetLines()); CMakeVariableDeclarations decls = new CMakeVariableDeclarations(vars, CMakeVariableType.EnvVariable); decls.AddItems(source.GetIncludeCacheEnvVariables(), CMakeItemDeclarations.ItemType.Variable); scope.SetDeclarations(decls); } else if (token == CMakeToken.VariableStartCache) { List <string> vars = CMakeParsing.ParseForCacheVariables( source.GetLines()); CMakeVariableDeclarations decls = new CMakeVariableDeclarations(vars, CMakeVariableType.CacheVariable); decls.AddItems(source.GetIncludeCacheCacheVariables(), CMakeItemDeclarations.ItemType.Variable); scope.SetDeclarations(decls); } else if (token == CMakeToken.Identifier) { CMakeParsing.TokenData tokenData; CMakeParsing.ParseForToken(source.GetLines(), req.Line, req.TokenInfo.StartIndex, out tokenData); if (!tokenData.InParens) { CMakeItemDeclarations decls = new CMakeItemDeclarations(); IEnumerable <string> commands = CMakeKeywords.GetAllCommands( CMakePackage.Instance.CMakeOptionPage.ShowDeprecated); if (!CMakePackage.Instance.CMakeOptionPage.CommandsLower) { commands = commands.Select(x => x.ToUpper()); } decls.AddItems(commands, CMakeItemDeclarations.ItemType.Command); decls.AddItems( CMakeParsing.ParseForFunctionNames(source.GetLines(), false), CMakeItemDeclarations.ItemType.Function); decls.AddItems( CMakeParsing.ParseForFunctionNames(source.GetLines(), true), CMakeItemDeclarations.ItemType.Macro); decls.AddItems(source.GetIncludeCacheFunctions(), CMakeItemDeclarations.ItemType.Function); decls.AddItems(source.GetIncludeCacheMacros(), CMakeItemDeclarations.ItemType.Macro); scope.SetDeclarations(decls); } else { Declarations decls = CMakeDeclarationsFactory.CreateDeclarations( tokenData.Command, req, source, tokenData.ParameterIndex > 0 ? tokenData.PriorParameters : null); scope.SetDeclarations(decls); } } else if (token == CMakeToken.OpenParen) { CMakeCommandId id = CMakeParsing.ParseForTriggerCommandId( source.GetLines(), req.Line, req.TokenInfo.StartIndex); Declarations decls = CMakeDeclarationsFactory.CreateDeclarations( id, req, source); scope.SetDeclarations(decls); } else if (token == CMakeToken.WhiteSpace) { CMakeParsing.TokenData tokenData; CMakeParsing.ParseForToken(source.GetLines(), req.Line, req.TokenInfo.StartIndex, out tokenData); Declarations decls = CMakeDeclarationsFactory.CreateDeclarations( tokenData.Command, req, source, tokenData.ParameterIndex > 0 ? tokenData.PriorParameters : null); scope.SetDeclarations(decls); } else if (token == CMakeToken.GeneratorStart) { scope.SetDeclarations(new CMakeGeneratorDeclarations()); } } else if (req.Reason == ParseReason.MethodTip) { CMakeParsing.ParameterInfoResult result = CMakeParsing.ParseForParameterInfo(source.GetLines(), req.Line, req.TokenInfo.EndIndex); if (result.CommandName != null && result.CommandSpan.HasValue) { if (result.SubcommandName == null) { req.Sink.StartName(result.CommandSpan.Value, result.CommandName); } else { req.Sink.StartName(result.CommandSpan.Value, result.CommandSpan + "(" + result.SubcommandName); } if (result.BeginSpan.HasValue) { req.Sink.StartParameters(result.BeginSpan.Value); } foreach (TextSpan span in result.SeparatorSpans) { req.Sink.NextParameter(span); } if (result.EndSpan.HasValue) { req.Sink.EndParameters(result.EndSpan.Value); } CMakeCommandId id = CMakeKeywords.GetCommandId(result.CommandName); if (id == CMakeCommandId.Unspecified) { // If it's a user-defined function or macro, parse to try to find // its parameters. List <string> parameters = CMakeParsing.ParseForParameterNames( source.GetLines(), result.CommandName); if (parameters == null) { parameters = source.GetParametersFromIncludeCache( result.CommandName); } if (parameters != null) { scope.SetMethods(new CMakeUserMethods(result.CommandName, parameters)); } } else { scope.SetMethods(CMakeMethods.GetCommandParameters(id, result.SubcommandName)); } } } else if (req.Reason == ParseReason.Goto) { scope.SetLines(source.GetLines()); scope.SetFileName(req.FileName); } else if (req.Reason == ParseReason.QuickInfo) { scope.SetLines(source.GetLines()); } else if (req.Reason == ParseReason.Check) { foreach (ParseForErrorMethod method in _parseForErrorMethods) { List <CMakeErrorInfo> info = method(source.GetLines()); foreach (CMakeErrorInfo item in info) { CMakeError err = item.ErrorCode; if (_errorStrings.ContainsKey(err) && (!_enabledMethods.ContainsKey(err) || _enabledMethods[err]())) { req.Sink.AddError(req.FileName, _errorStrings[err], item.Span, item.Warning ? Severity.Warning : Severity.Error); } } } if (CMakePackage.Instance.CMakeOptionPage.ParseIncludedFiles) { source.BuildIncludeCache(source.GetLines()); source.UpdateIncludeCache(); source.PruneIncludeCache(); } else { source.ClearIncludeCache(); } } return(scope); }