Improving terraform hcl

This commit is contained in:
Hugo Fonseca 2020-09-02 23:38:01 +01:00
parent 3efc637414
commit 9d8859a82d
3 changed files with 1400 additions and 239 deletions

View file

@ -7,8 +7,8 @@
import { registerLanguage } from '../_.contribution'; import { registerLanguage } from '../_.contribution';
registerLanguage({ registerLanguage({
id: 'hcl', id: 'hcl',
extensions: ['.tf', '.tfvars', '.hcl'], extensions: ['.tf', '.tfvars', '.hcl'],
aliases: ['Terraform', 'tf', 'HCL', 'hcl'], aliases: ['Terraform', 'tf', 'HCL', 'hcl'],
loader: () => import('./hcl') loader: () => import('./hcl')
}); });

1201
src/hcl/hcl.test.ts Normal file

File diff suppressed because it is too large Load diff

View file

@ -9,245 +9,205 @@ import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
import ILanguage = monaco.languages.IMonarchLanguage; import ILanguage = monaco.languages.IMonarchLanguage;
export const conf: IRichLanguageConfiguration = { export const conf: IRichLanguageConfiguration = {
comments: { comments: {
lineComment: '//', lineComment: '//',
blockComment: ['/*', '*/'] blockComment: ['/*', '*/'],
}, },
brackets: [ brackets: [
['{', '}'], ['{', '}'],
['[', ']'], ['[', ']'],
['(', ')'] ['(', ')']
], ],
autoClosingPairs: [ autoClosingPairs: [
{ open: '{', close: '}' }, { open: '{', close: '}' },
{ open: '[', close: ']' }, { open: '[', close: ']' },
{ open: '(', close: ')' }, { open: '(', close: ')' },
{ open: '"', close: '"', notIn: ['string'] }, { open: '"', close: '"', notIn: ['string'] },
{ open: "'", close: "'", notIn: ['string', 'comment'] } ],
], surroundingPairs: [
surroundingPairs: [ { open: '{', close: '}' },
{ open: '{', close: '}' }, { open: '[', close: ']' },
{ open: '[', close: ']' }, { open: '(', close: ')' },
{ open: '(', close: ')' }, { open: '"', close: '"' },
{ open: '"', close: '"' }, ]
{ open: "'", close: "'" }
]
}; };
export const language = <ILanguage>{ export const language = <ILanguage>{
defaultToken: '', defaultToken: "",
tokenPostfix: '.tf', tokenPostfix: ".hcl",
keywords: [ keywords: [
'var', "var",
'local', "local",
'module', "path",
'data', "for_each",
'path', "any",
'terraform', "string",
'resource', "number",
'provider', "bool",
'variable', "true",
'output', "false",
'locals', "null",
'any', "if ",
'string', "else ",
'number', "endif ",
'bool', "for ",
'abs', "in",
'ceil', "endfor",
'floor', ],
'log',
'max',
'min',
'pow',
'signum',
'chomp',
'format',
'formatlist',
'indent',
'join',
'lower',
'regex',
'regexall',
'replace',
'split',
'strrev',
'substr',
'title',
'trimspace',
'upper',
'chunklist',
'coalesce',
'coalescelist',
'compact',
'concat',
'contains',
'distinct',
'element',
'flatten',
'index',
'keys',
'length',
'list',
'lookup',
'map',
'matchkeys',
'merge',
'range',
'reverse',
'setintersection',
'setproduct',
'setunion',
'slice',
'sort',
'transpose',
'values',
'zipmap',
'base64decode',
'base64encode',
'base64gzip',
'csvdecode',
'jsondecode',
'jsonencode',
'urlencode',
'yamldecode',
'yamlencode',
'abspath',
'dirname',
'pathexpand',
'basename',
'file',
'fileexists',
'fileset',
'filebase64',
'templatefile',
'formatdate',
'timeadd',
'timestamp',
'base64sha256',
'base64sha512',
'bcrypt',
'filebase64sha256',
'filebase64sha512',
'filemd5',
'filemd1',
'filesha256',
'filesha512',
'md5',
'rsadecrypt',
'sha1',
'sha256',
'sha512',
'uuid',
'uuidv5',
'cidrhost',
'cidrnetmask',
'cidrsubnet',
'tobool',
'tolist',
'tomap',
'tonumber',
'toset',
'tostring',
'true',
'false',
'null',
'if ',
'else ',
'endif ',
'for ',
'in',
'endfor'
],
operators: [ operators: [
'>=', "=",
'<=', ">=",
'==', "<=",
'!=', "==",
'+', "!=",
'-', "+",
'*', "-",
'/', "*",
'%', "/",
'&&', "%",
'||', "&&",
'!', "||",
'<', "!",
'>', "<",
'?', ">",
'...', "?",
':' "...",
], ":",
],
// we include these common regular expressions symbols: /[=><!~?:&|+\-*\/\^%]+/,
symbols: /[=><!~?:&|+\-*\/\^%]+/, escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/, terraformFunctions: /(abs|ceil|floor|log|max|min|pow|signum|chomp|format|formatlist|indent|join|lower|regex|regexall|replace|split|strrev|substr|title|trimspace|upper|chunklist|coalesce|coalescelist|compact|concat|contains|distinct|element|flatten|index|keys|length|list|lookup|map|matchkeys|merge|range|reverse|setintersection|setproduct|setunion|slice|sort|transpose|values|zipmap|base64decode|base64encode|base64gzip|csvdecode|jsondecode|jsonencode|urlencode|yamldecode|yamlencode|abspath|dirname|pathexpand|basename|file|fileexists|fileset|filebase64|templatefile|formatdate|timeadd|timestamp|base64sha256|base64sha512|bcrypt|filebase64sha256|filebase64sha512|filemd5|filemd1|filesha256|filesha512|md5|rsadecrypt|sha1|sha256|sha512|uuid|uuidv5|cidrhost|cidrnetmask|cidrsubnet|tobool|tolist|tomap|tonumber|toset|tostring)/,
variable: /\${?[\w]+}?/, terraformMainBlocks: /(module|data|terraform|resource|provider|variable|output|locals)/,
tokenizer: {
// The main tokenizer for our languages root: [
tokenizer: { // highlight main blocks
root: [ [
// identifiers and keywords /^@terraformMainBlocks([ \t]*)([\w-]+|"[\w-]+"|)([ \t]*)([\w-]+|"[\w-]+"|)([ \t]*)(\{)/,
[ [
/[a-zA-Z_]\w*/, "type",
{ "",
cases: { "string",
'@keywords': { token: 'keyword.$0' }, "",
'@default': 'identifier' "string",
} "",
} "@brackets",
], ],
],
// whitespace // highlight all the remaining blocks
{ include: '@whitespace' }, [
/(\w+[ \t]+)([ \t]*)([\w-]+|"[\w-]+"|)([ \t]*)([\w-]+|"[\w-]+"|)([ \t]*)(\{)/,
// delimiters and operators [
[/[{}()\[\]]/, '@brackets'], "identifier",
[/[<>](?!@symbols)/, '@brackets'], "",
[ "string",
/@symbols/, "",
{ "string",
cases: { "",
'@operators': 'delimiter', "@brackets",
'@default': '' ],
} ],
} // highlight block
], [
/(\w+[ \t]+)([ \t]*)([\w-]+|"[\w-]+"|)([ \t]*)([\w-]+|"[\w-]+"|)(=)(\{)/,
// numbers [
[/\d*\d+[eE]([\-+]?\d+)?/, 'number.float'], "identifier",
[/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'], "",
[/\d[\d']*/, 'number'], "string",
[/\d/, 'number'], "",
"operator",
// delimiter: after number because of .\d floats "",
[/[;,.]/, 'delimiter'], "@brackets",
],
// strings ],
[/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string // terraform general highlight - shared with expressions
[/"/, 'string', '@string'] { include: "@terraform" },
], ],
terraform : [
whitespace: [ // highlight terraform functions
[/[ \t\r\n]+/, ''], [/@terraformFunctions(\()/, ['type', '@brackets']],
[/\/\*/, 'comment', '@comment'], // all other words are variables or keywords
[/\/\/.*$/, 'comment'], [
[/#.*$/, 'comment'] /[a-zA-Z_]\w*-*/, // must work with variables such as foo-bar and also with negative numbers
], {
cases: {
comment: [ "@keywords": { token: "keyword.$0" },
[/[^\/*]+/, 'comment'], "@default": "variable",
[/\*\//, 'comment', '@pop'], },
[/[\/*]/, 'comment'] },
], ],
{ include: "@whitespace" },
string: [ { include: '@heredoc' },
[/[^\\"]+/, 'string'], // delimiters and operators
[/@escapes/, 'string.escape'], [/[{}()\[\]]/, "@brackets"],
[/\\./, 'string.escape.invalid'], [/[<>](?!@symbols)/, "@brackets"],
[/"/, 'string', '@pop'] [
] /@symbols/,
} {
cases: {
"@operators": "operator",
"@default": "",
},
},
],
// numbers
[/\d*\d+[eE]([\-+]?\d+)?/, "number.float"],
[/\d*\.\d+([eE][\-+]?\d+)?/, "number.float"],
[/\d[\d']*/, "number"],
[/\d/, "number"],
[/[;,.]/, "delimiter"], // delimiter: after number because of .\d floats
// strings
[/"/, "string", "@string"], // this will include expressions
[/'/, "invalid"],
],
heredoc: [
[
/<<[-]*\s*["]?([\w\-]+)["]?/,
{ token: 'string.heredoc.delimiter', next: '@heredocBody.$1' },
],
],
heredocBody: [
[
/^([\w\-]+)$/,
{
cases: {
'$1==$S2': [{ token: 'string.heredoc.delimiter', next: '@popall' }],
'@default': 'string.heredoc',
},
},
],
[/./, 'string.heredoc'],
],
whitespace: [
[/[ \t\r\n]+/, ""],
[/\/\*/, "comment", "@comment"],
[/\/\/.*$/, "comment"],
[/#.*$/, "comment"],
],
comment: [
[/[^\/*]+/, "comment"],
[/\*\//, "comment", "@pop"],
[/[\/*]/, "comment"],
],
string: [
[/\$\{/, { token: "delimiter", next: "@stringExpression" }],
[/[^\\"\$]+/, "string"],
[/@escapes/, "string.escape"],
[/\\./, "string.escape.invalid"],
[/"/, "string", "@popall"],
],
stringInsideExpression: [
[/[^\\"]+/, "string"],
[/@escapes/, "string.escape"],
[/\\./, "string.escape.invalid"],
[/"/, "string", "@pop"],
],
stringExpression: [
[/\}/, { token: "delimiter", next: "@pop" }],
[/"/, "string", "@stringInsideExpression"],
{ include: "@terraform" },
],
},
}; };