/* * Copyright 2015-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.intellij.ideabuck.annotator; import com.facebook.buck.intellij.ideabuck.build.BuckBuildUtil; import com.facebook.buck.intellij.ideabuck.external.IntellijBuckAction; import com.facebook.buck.intellij.ideabuck.highlight.BuckSyntaxHighlighter; import com.facebook.buck.intellij.ideabuck.lang.psi.BuckPsiUtils; import com.facebook.buck.intellij.ideabuck.lang.psi.BuckTypes; import com.facebook.buck.intellij.ideabuck.lang.psi.BuckValue; import com.intellij.lang.annotation.Annotation; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; /** Annotator for Buck, it helps highlight and annotate any issue in Buck files. */ public class BuckAnnotator implements Annotator { private static final String ANNOTATOR_ERROR_CANNOT_LOCATE_TARGET = "Cannot locate the Buck target"; @Override public void annotate(PsiElement psiElement, AnnotationHolder annotationHolder) { if (annotateIdentifier(psiElement, annotationHolder)) { return; } annotateErrors(psiElement, annotationHolder); } private void annotateErrors(PsiElement psiElement, AnnotationHolder annotationHolder) { BuckValue value = PsiTreeUtil.getParentOfType(psiElement, BuckValue.class); if (value == null) { return; } final Project project = psiElement.getProject(); if (project == null) { return; } String target = psiElement.getText(); if (target.matches("\".*\"") || target.matches("'.*'")) { target = target.substring(1, target.length() - 1); } else { return; } if (!BuckBuildUtil.isValidAbsoluteTarget(target)) { return; } VirtualFile buckDir = project.getBaseDir().findFileByRelativePath(BuckBuildUtil.extractAbsoluteTarget(target)); VirtualFile targetBuckFile = buckDir != null ? buckDir.findChild("BUCK") : null; if (targetBuckFile == null) { TextRange range = new TextRange( psiElement.getTextRange().getStartOffset(), psiElement.getTextRange().getEndOffset()); annotationHolder.createErrorAnnotation(range, ANNOTATOR_ERROR_CANNOT_LOCATE_TARGET); project .getMessageBus() .syncPublisher(IntellijBuckAction.EVENT) .consume(this.getClass().toString()); } } private boolean annotateIdentifier(PsiElement psiElement, AnnotationHolder annotationHolder) { if (psiElement.getNode().getElementType() != BuckTypes.IDENTIFIER) { return false; } PsiElement parent = psiElement.getParent(); assert parent != null; final Annotation annotation = annotationHolder.createInfoAnnotation(psiElement, null); if (BuckPsiUtils.testType(parent, BuckTypes.RULE_NAME)) { annotation.setTextAttributes(BuckSyntaxHighlighter.BUCK_RULE_NAME); return true; } else if (BuckPsiUtils.testType(parent, BuckTypes.PROPERTY_LVALUE)) { annotation.setTextAttributes(BuckSyntaxHighlighter.BUCK_KEYWORD); return true; } return false; } }