kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/extractors/config/preprocessor/modifier/build_gradle_modifier.go (about)

     1  /*
     2   * Copyright 2018 The Kythe Authors. All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *   http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  // Package modifier provides a library for adding a forked javac executable
    18  // into a build.gradle file or pom.xml file.
    19  package modifier // import "kythe.io/kythe/go/extractors/config/preprocessor/modifier"
    20  
    21  import (
    22  	"fmt"
    23  	"io/ioutil"
    24  	"os"
    25  	"regexp"
    26  )
    27  
    28  // These are the lines necessary for gradle build to use a different javac.
    29  const kytheJavacWrapper = `
    30  allprojects {
    31    gradle.projectsEvaluated {
    32      tasks.withType(JavaCompile) {
    33        options.fork = true
    34        options.forkOptions.executable = '%s'
    35      }
    36    }
    37  }
    38  `
    39  
    40  // This matches a line which sets the javac to use Kythe's javac-wrapper.sh
    41  func kytheMatcher(javacWrapper string) *regexp.Regexp {
    42  	return regexp.MustCompile(fmt.Sprintf(`\n\s*options\.forkOptions\.executable\ =\ '%s'`, javacWrapper))
    43  }
    44  
    45  // This matches any line which sets a new javac executable, useful for detecting
    46  // edge cases which already modify javac.
    47  var javacMatcher = regexp.MustCompile(`\n\s*options\.forkOptions\.executable\ =`)
    48  
    49  // PreProcessBuildGradle takes a build.gradle file and either verifies that it
    50  // already has the bits necessary to run kythe's javac wrapper, or adds that
    51  // functionality.
    52  //
    53  // Note this potentially modifies the input file, so make a copy beforehand if
    54  // you need to keep the original.
    55  func PreProcessBuildGradle(buildGradleFile, javacWrapper string) error {
    56  	k, err := hasKytheWrapper(buildGradleFile, javacWrapper)
    57  	if err != nil {
    58  		return err
    59  	}
    60  	if k {
    61  		// Already has the kythe javac-wrapper.
    62  		return nil
    63  	}
    64  	return appendKytheWrapper(buildGradleFile, javacWrapper)
    65  }
    66  
    67  func hasKytheWrapper(buildGradleFile, javacWrapper string) (bool, error) {
    68  	bits, err := ioutil.ReadFile(buildGradleFile)
    69  	if err != nil {
    70  		return false, fmt.Errorf("reading file %s: %v", buildGradleFile, err)
    71  	}
    72  	if kytheMatcher(javacWrapper).Match(bits) {
    73  		return true, nil
    74  	}
    75  	if javacMatcher.Match(bits) {
    76  		return false, fmt.Errorf("found existing non-kythe javac override for file %s, which we can't handle yet", buildGradleFile)
    77  	}
    78  	return false, nil
    79  }
    80  
    81  func appendKytheWrapper(buildGradleFile, javacWrapper string) error {
    82  	f, err := os.OpenFile(buildGradleFile, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
    83  	if err != nil {
    84  		return fmt.Errorf("opening file %s for append: %v", buildGradleFile, err)
    85  	}
    86  	if _, err := fmt.Fprintf(f, kytheJavacWrapper, javacWrapper); err != nil {
    87  		return fmt.Errorf("appending javac-wrapper to %s: %v", buildGradleFile, err)
    88  	}
    89  	return f.Close()
    90  }