Looker の Liquid 構文パーサー

Looker は、Looker 21.6 で新しい Liquid 構文パーサーをリリースしました。新しい Looker Liquid 構文パーサーは LookML の検証で使用され、Liquid 構文エラーが公開されます。このパーサーの目的は、サイレント エラーの防止、Liquid 構文のデバッグを容易にすること、ユーザー属性参照と結果のキャッシュ保存のセキュリティを向上させ、動的フィールド参照をより効果的に検出することです。このパーサーは、有効な Liquid 構文を対象として新しいチェックを行うため、既存の Liquid 構文に関する新しい検証メッセージが表示されることがあります。

22.2 より前のバージョンの Looker では、構文容認機能という以前の機能によってパーサーが制御されていました。この従来の機能は、パーサーの使用そのものに影響を与えるものではなく、パーサーによって公開されるエラーのレベルにも影響を与えました。従来の構文容器の液体機能をオンにしたときに、すべてのエラーが情報提供に分類されるようになりました。Looker 22.2 の時点で、構文容認液体機能は完全に削除されています。詳しくは、レガシー機能のサポート終了スケジュールをご覧ください。

新しい Liquid パーサーでは、すべてのエラーが警告に分類されるため、プロジェクトのコード品質の設定によっては、コードの commit に影響する可能性があります。

Liquid パーサーは現在、実行中の Liquid をレンダリングしません。今後のリリースノートで、このアップデートをご確認ください。

Liquid 構文警告の解釈

Liquid 構文の新しい警告は冗長で、次の情報が明示的に含まれます。

  • 問題入力の後に Liquid ブロック内での入力の行とインデックス番号が続く
  • 関連する LookML ビューファイルとコード行へのリンク

次のエラーの例を見てみましょう。

Error parsing liquid: Liquid parse exception: parser error "extraneous input '{{' expecting {Str, '(', '[', DoubleNum, LongNum, 'capture', 'endcapture', 'comment'
'endcomment', RawStart, 'if ', 'elsif', 'endif', 'unless ', 'endunless', 'else ', 'contains', 'case', 'endcase', 'when', 'cycle', 'for', 'endfor', 'in ', 'and', 'or'
'tablerow', 'endtablerow', 'assign', 'true', 'false', Nil, 'include', 'with ', 'empty','blank', EndId, Id, RawEnd}" on line 1, index 16
view_name.view:60 (project_name:view_name)
moonrise-replaceb31ccc9e870d47bbb1cdb5539e5ae502moonrise-replace

このエラーは、LookML ファイルの 60 行目から始まるディメンション foo の定義に基づいています。

moonrise-replace68e9c70b6fde4012abe52df45dd9851cmoonrise-replace
dimension: foo {
  type: number
  sql: ${TABLE}.bar ;;
  html:
      moonrise-replace7a4e9c835e8d431dbb72f1f88ab89011moonrise-replace
      {{var}}
    ;;
}

この警告は、{{moonrise-replace77cc38e4d9644ca9914c5726caf305f3moonrise-replace 入力が view_name の 1 行目の moonrise-replaced33c1b18b057421e8590edfdc38e9ce2moonrise-replacemoonrise-replaced6ac8c5833c044a09ee82e583c2057dcmoonrise-replacemoonrise-replace4f3ca4d486a04f62aba0a309797ceeb3moonrise-replace タグ内と 60 行目の Liquid ブロックのインデックス 16 で不適切に使用されていることを意味します。Liquid にはこのような状況下で許可される入力のルールがあり、そのような入力は次のように示されています。

moonrise-replace3ceb1aa6af834d1e973d69070de53735moonrise-replace
{Str ,'(' ,'[' , DoubleNum , LongNum ,'capture' ,'endcapture' ,'comment' ,'endcomment' ,RawStart ,'if' ,'elsif' ,'endif' ,'unless' ,'endunless' ,'else' ,'contains'
'case' , 'endcase' ,'when' , 'cycle' ,'for' ,'endfor' ,'in' ,'and' ,'or' ,'tablerow' ,'endtablerow' ,'assign' ,'true' ,'false' , Nil,'include' ,'with' ,'empty' ,'blank' , EndId, Id, RawEnd}.
moonrise-replace4004137e441f4829b7e7ebdfd8b28ae0moonrise-replace

value の周囲の moonrise-replace937d36b6c7b841068a7b252e0e89947bmoonrise-replace{{...}} を削除すると、Liquid は正常に解析されます。

新しい警告は構造的なパターンに従いますが、メッセージの仕様にバリエーションがあります。他のバリエーションの例と、それを解決するための高レベルのポインタを以下に示します。

例 1

警告:

  Error  parsing liquid: Liquid parse exception: lexer error  \ "token recognition error at: '(token)'\" on line x, index y

これは、予期しないトークン(# など)が使用されるとスローされる可能性があります。

dimension: foo {
  type: number
  sql: ${TABLE}.bar ;;
  html:
      {% assign var = #value %}
      {{var}}
    ;;
}

予期しないトークン(この場合は #)を削除すると、警告が解決されます。

例 2

警告:

Error  parsing liquid: Liquid parse exception: parser error  \ "mismatched input (input)|' expecting {TagEnd, '.', NEq, '==', '>=', '>', '<=', '<', '[', '?','contains', 'and', 'or'}\" on line x, index y

この関数は、if 条件内で関数が | トークンと連結されている場合にスローされる場合があります。

dimension: foo {
  type: number
  sql: ${TABLE}.bar ;;
  html:
      {% dynamic if 20 |divided_by(7) |times(1.0) >= 2 %}
        hello world
      {% dynamic endif %}
    ;;
}

関数チェーンの出力を変数に割り当て、その変数を if 条件に含めると、警告が解決されます。

例 3

警告:

Error parsing liquid: Liquid parse exception: parser error "missing '(character)' at '%}'" on line x, index y

この警告は、次の例の {% assign var = (true and false %} 行の閉じかっこなど、必要な文字が不足している場合にスローされます。

dimension: foo {
    type: number
    sql: ${TABLE}.bar ;;
    html:
        {% assign var = (true and false %}
        {{var}}
      ;;
}

警告の文字を閉じるには、必要な文字(この場合は閉じかっこ ))を追加します。